diff --git a/src/services/utilities.ts b/src/services/utilities.ts index d0e75c5522f..6a4b85ba901 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2218,22 +2218,22 @@ namespace ts { type PackageJsonRaw = Record | undefined>; const dependencyKeys = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"] as const; const stringContent = host.readFile(fileName); - const content = stringContent && tryParseJson(stringContent) as PackageJsonRaw; - if (!content) { - return undefined; - } + if (!stringContent) return undefined; + const content = tryParseJson(stringContent) as PackageJsonRaw; const info: Pick = {}; - for (const key of dependencyKeys) { - const dependencies = content[key]; - if (!dependencies) { - continue; + if (content) { + for (const key of dependencyKeys) { + const dependencies = content[key]; + if (!dependencies) { + continue; + } + const dependencyMap = createMap(); + for (const packageName in dependencies) { + dependencyMap.set(packageName, dependencies[packageName]); + } + info[key] = dependencyMap; } - const dependencyMap = createMap(); - for (const packageName in dependencies) { - dependencyMap.set(packageName, dependencies[packageName]); - } - info[key] = dependencyMap; } const dependencyGroups = [ diff --git a/src/testRunner/unittests/tsserver/packageJsonInfo.ts b/src/testRunner/unittests/tsserver/packageJsonInfo.ts index aad479fccfb..4d2e3dd26dc 100644 --- a/src/testRunner/unittests/tsserver/packageJsonInfo.ts +++ b/src/testRunner/unittests/tsserver/packageJsonInfo.ts @@ -71,6 +71,18 @@ namespace ts.projectSystem { assert.lengthOf(project.getPackageJsonsVisibleToFile("/a.ts" as Path), 1); assert.lengthOf(project.getPackageJsonsVisibleToFile("/src/b.ts" as Path), 2); }); + + it("handles errors in json parsing of package.json", () => { + const packageJsonContent = `{ "mod" }`; + const { project } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]); + project.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + const packageJsonInfo = project.packageJsonCache.getInDirectory("/" as Path)!; + assert.isObject(packageJsonInfo); + assert.isUndefined(packageJsonInfo.dependencies); + assert.isUndefined(packageJsonInfo.devDependencies); + assert.isUndefined(packageJsonInfo.peerDependencies); + assert.isUndefined(packageJsonInfo.optionalDependencies); + }); }); function setup(files: readonly File[] = [tsConfig, packageJson]) { diff --git a/tests/cases/fourslash/server/importSuggestionsCache_invalidPackageJson.ts b/tests/cases/fourslash/server/importSuggestionsCache_invalidPackageJson.ts new file mode 100644 index 00000000000..d18ab19f5d2 --- /dev/null +++ b/tests/cases/fourslash/server/importSuggestionsCache_invalidPackageJson.ts @@ -0,0 +1,57 @@ +/// + +// @Filename: /jsconfig.json +////{ +//// "compilerOptions": { +//// "module": "commonjs", +//// }, +////} + +// @Filename: /node_modules/@types/node/index.d.ts +////declare module 'fs' { +//// export function readFile(): void; +////} +////declare module 'util' { +//// export function promisify(): void; +////} + +// @Filename: /package.json +////{ "mod" } + +// @Filename: /a.js +//// +////readF/**/ + +verifyExcludes("readFile"); +edit.replaceLine(0, "import { promisify } from 'util';"); +verifyIncludes("readFile"); +edit.deleteLine(0); +verifyExcludes("readFile"); + +function verifyIncludes(name: string) { + goTo.marker(""); + verify.completions({ + includes: { + name, + source: "fs", + hasAction: true, + sortText: completion.SortText.AutoImportSuggestions, + }, + preferences: { + includeCompletionsForModuleExports: true, + includeInsertTextCompletions: true, + }, + }); +} + +function verifyExcludes(name: string) { + goTo.marker(""); + verify.completions({ + excludes: name, + preferences: { + includeCompletionsForModuleExports: true, + includeInsertTextCompletions: true, + }, + }); +} +