Skip to content

Commit dfa4329

Browse files
authored
Gracefully handle incomplete package.json files (#239)
* 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"`. * Empty commit to trigger ci * ESlint
1 parent bb7a95d commit dfa4329

File tree

15 files changed

+136
-12
lines changed

15 files changed

+136
-12
lines changed

.gitignore

+1
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
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+
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function a(): string {
2+
return ''
3+
}
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+
}
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+
}
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+
}
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

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
packages:
2+
- 'packages/*'
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+
}
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

+2-2
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

+17-10
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,35 @@ export class Packages {
3333
if (typeof name === 'string' && typeof version === 'string') {
3434
return this.cached(filePath, ScipSymbol.package(name, version))
3535
}
36+
if (typeof name === 'string') {
37+
// The version field is missing so we fallback to `"HEAD"`
38+
return this.cached(filePath, ScipSymbol.package(name, 'HEAD'))
39+
}
40+
// Fallback to an anonymous package because we found a package.json but
41+
// were unable to parse the name and version.
42+
return this.cached(filePath, ScipSymbol.anonymousPackage())
3643
}
3744
} catch (error) {
3845
console.error(`error parsing ${packageJsonPath}`, error)
39-
return this.cached(filePath, ScipSymbol.empty())
46+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4047
}
4148

4249
if (filePath === this.projectRoot) {
43-
return this.cached(filePath, ScipSymbol.empty())
50+
// Don't look for package.json in a parent directory of the root.
51+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4452
}
4553

4654
const dirname = path.dirname(filePath)
4755
if (dirname === filePath) {
48-
return this.cached(filePath, ScipSymbol.empty())
56+
// Avoid infinite recursion when `path.dirname(path) === path`
57+
return this.cached(filePath, ScipSymbol.anonymousPackage())
4958
}
59+
5060
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())
61+
return this.cached(
62+
filePath,
63+
ScipSymbol.global(owner, packageDescriptor(path.basename(filePath)))
64+
)
5865
}
5966

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

src/ScipSymbol.ts

+4
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)