Skip to content

Commit b3ceea3

Browse files
committed
- replacing TryParseJson with existing readConfig
- push error for invalid enableAutoDiscovery option - adding interfaces for jsons - removing updateNotFoundTypings - node_modules normalize file names before using - adding safeListPath to discoverTypings
1 parent 0346a98 commit b3ceea3

File tree

3 files changed

+71
-111
lines changed

3 files changed

+71
-111
lines changed

src/compiler/commandLineParser.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ namespace ts {
503503
*
504504
* This method replace comment content by whitespace rather than completely remove them to keep positions in json parsing error reporting accurate.
505505
*/
506-
export function removeComments(jsonText: string): string {
506+
function removeComments(jsonText: string): string {
507507
let output = "";
508508
const scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText);
509509
let token: SyntaxKind;
@@ -614,6 +614,9 @@ namespace ts {
614614
if (typeof jsonTypingOptions[id] === "boolean") {
615615
options.enableAutoDiscovery = jsonTypingOptions[id];
616616
}
617+
else {
618+
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_typing_option_0, id));
619+
}
617620
}
618621
else if (id === "include") {
619622
options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors);

src/services/jsTyping.ts

Lines changed: 63 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,47 @@ namespace ts.JsTyping {
1313
readDirectory: (path: string, extension?: string, exclude?: string[], depth?: number) => string[];
1414
};
1515

16+
interface TsdJson {
17+
version: string;
18+
repo: string;
19+
ref: string;
20+
path: string;
21+
installed?: Map<TsdInstalledItem>;
22+
};
23+
24+
interface TsdInstalledItem {
25+
commit: string;
26+
};
27+
28+
interface PackageJson {
29+
_requiredBy?: string[];
30+
dependencies?: Map<string>;
31+
devDependencies?: Map<string>;
32+
name: string;
33+
optionalDependencies?: Map<string>;
34+
peerDependencies?: Map<string>;
35+
typings?: string;
36+
};
37+
1638
// A map of loose file names to library names
1739
// that we are confident require typings
1840
let safeList: Map<string>;
19-
const notFoundTypingNames: string[] = [];
20-
21-
function tryParseJson(jsonPath: string, host: TypingResolutionHost): any {
22-
if (host.fileExists(jsonPath)) {
23-
try {
24-
const contents = removeComments(host.readFile(jsonPath));
25-
return JSON.parse(contents);
26-
}
27-
catch (e) { }
28-
}
29-
return undefined;
30-
}
3141

3242
/**
3343
* @param host is the object providing I/O related operations.
3444
* @param fileNames are the file names that belong to the same project.
35-
* @param globalCachePath is used to get the safe list file path and as cache path if the project root path isn't specified.
36-
* @param projectRootPath is the path to the project root directory. This is used for the local typings cache.
45+
* @param cachePath is the path to the typings cache
46+
* @param projectRootPath is the path to the project root directory
47+
* @param safeListPath is the path used to retrieve the safe list
3748
* @param typingOptions are used for customizing the typing inference process.
3849
* @param compilerOptions are used as a source of typing inference.
3950
*/
4051
export function discoverTypings(
4152
host: TypingResolutionHost,
4253
fileNames: string[],
43-
globalCachePath: Path,
54+
cachePath: Path,
4455
projectRootPath: Path,
56+
safeListPath: Path,
4557
typingOptions: TypingOptions,
4658
compilerOptions: CompilerOptions):
4759
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
@@ -53,13 +65,12 @@ namespace ts.JsTyping {
5365
return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
5466
}
5567

56-
const cachePath = projectRootPath || globalCachePath;
5768
// Only infer typings for .js and .jsx files
5869
fileNames = filter(map(fileNames, normalizePath), f => scriptKindIs(f, /*LanguageServiceHost*/ undefined, ScriptKind.JS, ScriptKind.JSX));
5970

60-
const safeListFilePath = combinePaths(globalCachePath, "safeList.json");
61-
if (!safeList && host.fileExists(safeListFilePath)) {
62-
safeList = tryParseJson(safeListFilePath, host);
71+
if (!safeList) {
72+
const result = readConfigFile(safeListPath, host.readFile);
73+
if (result.config) { safeList = result.config; }
6374
}
6475

6576
const filesToWatch: string[] = [];
@@ -86,26 +97,20 @@ namespace ts.JsTyping {
8697
const nodeModulesPath = combinePaths(searchDir, "node_modules");
8798
getTypingNamesFromNodeModuleFolder(nodeModulesPath, filesToWatch);
8899
}
89-
90100
getTypingNamesFromSourceFileNames(fileNames);
91-
getTypingNamesFromCompilerOptions(compilerOptions);
92101
}
93102

94103
const typingsPath = combinePaths(cachePath, "typings");
95104
const tsdJsonPath = combinePaths(cachePath, "tsd.json");
96-
const tsdJsonDict = tryParseJson(tsdJsonPath, host);
97-
if (tsdJsonDict) {
98-
for (const notFoundTypingName of notFoundTypingNames) {
99-
if (hasProperty(inferredTypings, notFoundTypingName) && !inferredTypings[notFoundTypingName]) {
100-
delete inferredTypings[notFoundTypingName];
101-
}
102-
}
105+
const result = readConfigFile(tsdJsonPath, host.readFile);
106+
if (result.config) {
107+
const tsdJson: TsdJson = result.config;
103108

104109
// The "installed" property in the tsd.json serves as a registry of installed typings. Each item
105110
// of this object has a key of the relative file path, and a value that contains the corresponding
106111
// commit hash.
107-
if (hasProperty(tsdJsonDict, "installed")) {
108-
for (const cachedTypingPath in tsdJsonDict.installed) {
112+
if (tsdJson.installed) {
113+
for (const cachedTypingPath in tsdJson.installed) {
109114
// Assuming the cachedTypingPath has the format of "[package name]/[file name]"
110115
const cachedTypingName = cachedTypingPath.substr(0, cachedTypingPath.indexOf("/"));
111116
// If the inferred[cachedTypingName] is already not null, which means we found a corresponding
@@ -153,20 +158,21 @@ namespace ts.JsTyping {
153158
* Get the typing info from common package manager json files like package.json or bower.json
154159
*/
155160
function getTypingNamesFromJson(jsonPath: string, filesToWatch: string[]) {
156-
const jsonDict = tryParseJson(jsonPath, host);
157-
if (jsonDict) {
161+
const result = readConfigFile(jsonPath, host.readFile);
162+
if (result.config) {
163+
const jsonConfig: PackageJson = result.config;
158164
filesToWatch.push(jsonPath);
159-
if (hasProperty(jsonDict, "dependencies")) {
160-
mergeTypings(getKeys(jsonDict.dependencies));
165+
if (jsonConfig.dependencies) {
166+
mergeTypings(getKeys(jsonConfig.dependencies));
161167
}
162-
if (hasProperty(jsonDict, "devDependencies")) {
163-
mergeTypings(getKeys(jsonDict.devDependencies));
168+
if (jsonConfig.devDependencies) {
169+
mergeTypings(getKeys(jsonConfig.devDependencies));
164170
}
165-
if (hasProperty(jsonDict, "optionalDependencies")) {
166-
mergeTypings(getKeys(jsonDict.optionalDependencies));
171+
if (jsonConfig.optionalDependencies) {
172+
mergeTypings(getKeys(jsonConfig.optionalDependencies));
167173
}
168-
if (hasProperty(jsonDict, "peerDependencies")) {
169-
mergeTypings(getKeys(jsonDict.peerDependencies));
174+
if (jsonConfig.peerDependencies) {
175+
mergeTypings(getKeys(jsonConfig.peerDependencies));
170176
}
171177
}
172178
}
@@ -205,75 +211,36 @@ namespace ts.JsTyping {
205211
}
206212

207213
const typingNames: string[] = [];
208-
const jsonFiles = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2);
209-
for (const jsonFile of jsonFiles) {
210-
if (getBaseFileName(jsonFile) !== "package.json") { continue; }
211-
const packageJsonDict = tryParseJson(jsonFile, host);
212-
if (!packageJsonDict) { continue; }
213-
214-
filesToWatch.push(jsonFile);
215-
216-
// npm 3 has the package.json contains a "_requiredBy" field
214+
const fileNames = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2);
215+
for (const fileName of fileNames) {
216+
const normalizedFileName = normalizePath(fileName);
217+
if (getBaseFileName(normalizedFileName) !== "package.json") { continue; }
218+
const result = readConfigFile(normalizedFileName, host.readFile);
219+
if (!result.config) { continue; }
220+
const packageJson: PackageJson = result.config;
221+
filesToWatch.push(normalizedFileName);
222+
223+
// npm 3's package.json contains a "_requiredBy" field
217224
// we should include all the top level module names for npm 2, and only module names whose
218225
// "_requiredBy" field starts with "#" or equals "/" for npm 3.
219-
if (packageJsonDict._requiredBy &&
220-
filter(packageJsonDict._requiredBy, (r: string) => r[0] === "#" || r === "/").length === 0) {
226+
if (packageJson._requiredBy &&
227+
filter(packageJson._requiredBy, (r: string) => r[0] === "#" || r === "/").length === 0) {
221228
continue;
222229
}
223230

224231
// If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used
225232
// to download d.ts files from DefinitelyTyped
226-
const packageName = packageJsonDict["name"];
227-
if (hasProperty(packageJsonDict, "typings")) {
228-
const absolutePath = getNormalizedAbsolutePath(packageJsonDict.typings, getDirectoryPath(jsonFile));
229-
inferredTypings[packageName] = absolutePath;
233+
if (!packageJson.name) { continue; }
234+
if (packageJson.typings) {
235+
const absolutePath = getNormalizedAbsolutePath(packageJson.typings, getDirectoryPath(normalizedFileName));
236+
inferredTypings[packageJson.name] = absolutePath;
230237
}
231238
else {
232-
typingNames.push(packageName);
239+
typingNames.push(packageJson.name);
233240
}
234241
}
235242
mergeTypings(typingNames);
236243
}
237244

238-
function getTypingNamesFromCompilerOptions(options: CompilerOptions) {
239-
const typingNames: string[] = [];
240-
if (!options) {
241-
return;
242-
}
243-
mergeTypings(typingNames);
244-
}
245-
}
246-
247-
/**
248-
* Keep a list of typings names that we know cannot be obtained at the moment (could be because
249-
* of network issues or because the package doesn't hava a d.ts file in DefinitelyTyped), so
250-
* that we won't try again next time within this session.
251-
* @param newTypingNames The list of new typings that the host attempted to acquire
252-
* @param cachePath The path to the tsd.json cache
253-
* @param host The object providing I/O related operations.
254-
*/
255-
export function updateNotFoundTypingNames(newTypingNames: string[], cachePath: string, host: TypingResolutionHost): void {
256-
const tsdJsonPath = combinePaths(cachePath, "tsd.json");
257-
const cacheTsdJsonDict = tryParseJson(tsdJsonPath, host);
258-
if (cacheTsdJsonDict) {
259-
const installedTypingFiles = hasProperty(cacheTsdJsonDict, "installed")
260-
? getKeys(cacheTsdJsonDict.installed)
261-
: [];
262-
const newMissingTypingNames =
263-
filter(newTypingNames, name => notFoundTypingNames.indexOf(name) < 0 && !isInstalled(name, installedTypingFiles));
264-
for (const newMissingTypingName of newMissingTypingNames) {
265-
notFoundTypingNames.push(newMissingTypingName);
266-
}
267-
}
268-
}
269-
270-
function isInstalled(typing: string, installedKeys: string[]) {
271-
const typingPrefix = typing + "/";
272-
for (const key of installedKeys) {
273-
if (key.indexOf(typingPrefix) === 0) {
274-
return true;
275-
}
276-
}
277-
return false;
278245
}
279246
}

src/services/shims.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,7 @@ namespace ts {
232232
getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
233233
getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
234234
getDefaultCompilationSettings(): string;
235-
discoverTypings(fileNamesJson: string, globalCachePath: string, projectRootPath: string, typingOptionsJson: string, compilerOptionsJson: string): string;
236-
updateNotFoundTypingNames(newTypingsJson: string, globalCachePath: string, projectRootPath: string): string;
235+
discoverTypings(fileNamesJson: string, cachePath: string, projectRootPath: string, safeListPath: string, typingOptionsJson: string, compilerOptionsJson: string): string;
237236
}
238237

239238
function logInternalError(logger: Logger, err: Error) {
@@ -988,31 +987,22 @@ namespace ts {
988987
);
989988
}
990989

991-
public discoverTypings(fileNamesJson: string, globalCachePath: string, projectRootPath: string, typingOptionsJson: string, compilerOptionsJson: string): string {
990+
public discoverTypings(fileNamesJson: string, cachePath: string, projectRootPath: string, safeListPath: string, typingOptionsJson: string, compilerOptionsJson: string): string {
992991
const getCanonicalFileName = createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false);
993992
return this.forwardJSONCall("discoverTypings()", () => {
994-
const cachePath = projectRootPath ? projectRootPath : globalCachePath;
995993
const typingOptions = <TypingOptions>JSON.parse(typingOptionsJson);
996-
997994
const compilerOptions = <CompilerOptions>JSON.parse(compilerOptionsJson);
998995
const fileNames: string[] = JSON.parse(fileNamesJson);
999996
return ts.JsTyping.discoverTypings(
1000997
this.host,
1001998
fileNames,
1002-
toPath(globalCachePath, globalCachePath, getCanonicalFileName),
1003999
toPath(cachePath, cachePath, getCanonicalFileName),
1000+
toPath(projectRootPath, projectRootPath, getCanonicalFileName),
1001+
toPath(safeListPath, safeListPath, getCanonicalFileName),
10041002
typingOptions,
10051003
compilerOptions);
10061004
});
10071005
}
1008-
1009-
public updateNotFoundTypingNames(newTypingsJson: string, globalCachePath: string, projectRootPath: string): string {
1010-
return this.forwardJSONCall("updateNotFoundTypingNames()", () => {
1011-
const newTypingNames: string[] = JSON.parse(newTypingsJson);
1012-
const cachePath = projectRootPath ? projectRootPath : globalCachePath;
1013-
ts.JsTyping.updateNotFoundTypingNames(newTypingNames, cachePath, this.host);
1014-
});
1015-
}
10161006
}
10171007

10181008
export class TypeScriptServicesFactory implements ShimFactory {

0 commit comments

Comments
 (0)