Skip to content

Commit 72393d2

Browse files
committed
Gracefully handle incomplete package.json files
Previously, scip-typescript didn't emit the required `scip-typescript npm PACKAGE_NAME PACKAGE_VERSION` prefix for global symbols when a package.json file was missing either the `name` or `version` field. Now, scip-typescript guarantees that all global symbols have this prefix. When the `version` field is missing, we fallback to the version `"HEAD"`.
1 parent bb7a95d commit 72393d2

File tree

15 files changed

+133
-12
lines changed

15 files changed

+133
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ node_modules
33
.eslintcache
44
yarn-error.log
55
snapshots/output/**/*.scip
6+
tsconfig.tsbuildinfo
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "invalid-package-json",
3+
"version": "1.0.0",
4+
"description": "Example TS/JS project",
5+
"main": "src/main.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"private": true,
12+
"packageManager": "[email protected]"
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@example/a",
3+
"description": "Example TS/JS project",
4+
"main": "src/a.ts",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1"
7+
},
8+
"author": "",
9+
"license": "ISC"
10+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function a(): string {
2+
return ''
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"rootDir": ".",
5+
"baseUrl": ".",
6+
"outDir": "dist"
7+
},
8+
"include": ["src/*"]
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"description": "Example TS/JS project",
3+
"main": "src/b.ts",
4+
"scripts": {
5+
"test": "echo \"Error: no test specified\" && exit 1"
6+
},
7+
"author": "",
8+
"license": "ISC",
9+
"dependencies": {
10+
"@example/a": "1.0.0"
11+
}
12+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { a } from '@example/a'
2+
3+
export function b() {
4+
return a()
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"rootDir": ".",
5+
"baseUrl": "./src",
6+
"sourceRoot": "src",
7+
"outDir": "dist"
8+
},
9+
"include": ["src/*"],
10+
"references": [{ "path": "../a" }]
11+
}

snapshots/input/invalid-package-json/pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
packages:
2+
- 'packages/*'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"extends": "@sourcegraph/tsconfig",
3+
"compilerOptions": {
4+
"target": "es2020",
5+
"module": "commonjs",
6+
"allowJs": false,
7+
"moduleResolution": "node",
8+
"esModuleInterop": true,
9+
"lib": ["esnext", "dom", "dom.iterable"],
10+
"sourceMap": true,
11+
"declaration": true,
12+
"declarationMap": true,
13+
"skipLibCheck": true,
14+
"skipDefaultLibCheck": true,
15+
"noErrorTruncation": true,
16+
"importHelpers": true,
17+
"resolveJsonModule": true,
18+
"composite": true,
19+
"outDir": "out",
20+
"rootDir": "."
21+
},
22+
"include": [],
23+
"exclude": ["out", "node_modules", "dist"]
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function a(): string {
2+
// definition @example/a HEAD src/`a.ts`/
3+
//documentation ```ts\nmodule "a.ts"\n```
4+
// ^ definition @example/a HEAD src/`a.ts`/a().
5+
// documentation ```ts\nfunction a(): string\n```
6+
return ''
7+
}
8+

src/FileIndexer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,8 @@ export class FileIndexer {
319319
}
320320
if (ts.isSourceFile(node)) {
321321
const package_ = this.packages.symbol(node.fileName)
322-
if (!package_) {
323-
return this.cached(node, ScipSymbol.empty())
322+
if (package_.isEmpty()) {
323+
return this.cached(node, ScipSymbol.anonymousPackage())
324324
}
325325
return this.cached(node, package_)
326326
}

src/Packages.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,33 @@ export class Packages {
3232
const version = packageJson.version
3333
if (typeof name === 'string' && typeof version === 'string') {
3434
return this.cached(filePath, ScipSymbol.package(name, version))
35+
} else if (typeof name === 'string') {
36+
return this.cached(filePath, ScipSymbol.package(name, 'HEAD'))
37+
} else {
38+
return this.cached(filePath, ScipSymbol.anonymousPackage())
3539
}
3640
}
3741
} catch (error) {
3842
console.error(`error parsing ${packageJsonPath}`, error)
39-
return this.cached(filePath, ScipSymbol.empty())
43+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4044
}
4145

4246
if (filePath === this.projectRoot) {
43-
return this.cached(filePath, ScipSymbol.empty())
47+
// Don't look for package.json in a parent directory of the root.
48+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4449
}
4550

4651
const dirname = path.dirname(filePath)
4752
if (dirname === filePath) {
48-
return this.cached(filePath, ScipSymbol.empty())
53+
// Avoid infinite recursion when `path.dirname(path) === path`
54+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4955
}
56+
5057
const owner = this.symbol(dirname)
51-
if (owner) {
52-
return this.cached(
53-
filePath,
54-
ScipSymbol.global(owner, packageDescriptor(path.basename(filePath)))
55-
)
56-
}
57-
return this.cached(filePath, ScipSymbol.empty())
58+
return this.cached(
59+
filePath,
60+
ScipSymbol.global(owner, packageDescriptor(path.basename(filePath)))
61+
)
5862
}
5963

6064
private cached(filePath: string, sym: ScipSymbol): ScipSymbol {

src/ScipSymbol.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export class ScipSymbol {
2424
return new ScipSymbol(`scip-typescript npm ${name} ${version} `)
2525
}
2626

27+
public static anonymousPackage(): ScipSymbol {
28+
return ScipSymbol.package('.', '.')
29+
}
30+
2731
public static global(
2832
owner: ScipSymbol,
2933
descriptor: scip.scip.Descriptor

0 commit comments

Comments
 (0)