diff --git a/snapshots/output/syntax/src/object-literals-arrow-function.ts b/snapshots/output/syntax/src/object-literals-arrow-function.ts index 0f77d535..3b7467d7 100644 --- a/snapshots/output/syntax/src/object-literals-arrow-function.ts +++ b/snapshots/output/syntax/src/object-literals-arrow-function.ts @@ -83,7 +83,7 @@ export function genericArrow2(): Foobar[] { return [1].map(n => ({ foobar: n + 1 })) // ^^^ reference typescript 6.0.3 lib/`lib.es5.d.ts`/Array#map(). // ^ definition local 26 -// ^^^^^^ reference syntax 1.0.0 src/`object-literals-arrow-function.ts`/foobar1: +// ^^^^^^ definition syntax 1.0.0 src/`object-literals-arrow-function.ts`/foobar1: // ^ reference local 26 } diff --git a/snapshots/output/syntax/src/structural-type.ts b/snapshots/output/syntax/src/structural-type.ts index f1d2d440..5ff9963d 100644 --- a/snapshots/output/syntax/src/structural-type.ts +++ b/snapshots/output/syntax/src/structural-type.ts @@ -14,7 +14,7 @@ export function foo(): Promise<{ member: number }> { // ^^^^^^^ reference typescript 6.0.3 lib/`lib.es2015.promise.d.ts`/Promise. // ^^^^^^^ reference typescript 6.0.3 lib/`lib.es2015.symbol.wellknown.d.ts`/Promise# // ^^^^^^^ reference typescript 6.0.3 lib/`lib.es2015.promise.d.ts`/PromiseConstructor#resolve(). -// ^^^^^^ reference syntax 1.0.0 src/`structural-type.ts`/member0: +// ^^^^^^ definition syntax 1.0.0 src/`structural-type.ts`/member0: } export function bar(): Promise { // ^^^ definition syntax 1.0.0 src/`structural-type.ts`/bar(). diff --git a/src/FileIndexer.ts b/src/FileIndexer.ts index 4418f10a..d7b04caa 100644 --- a/src/FileIndexer.ts +++ b/src/FileIndexer.ts @@ -166,7 +166,11 @@ export class FileIndexer { objectElement, contextualType ) - return symbol?.getDeclarations() + const declarations = symbol?.getDeclarations() + // Inferred object types can contextually resolve a property back to its + // own declaration. Treat that circular result as a definition instead of + // emitting a reference to a symbol that never gets SymbolInformation. + return declarations?.includes(objectElement) ? undefined : declarations } private visitSymbolOccurrence(node: ts.Node, sym: ts.Symbol): void { diff --git a/src/main.test.ts b/src/main.test.ts index 21152e51..ff06cdd7 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -83,6 +83,16 @@ for (const snapshotDirectory of snapshotDirectories) { documentPaths.add(document.relative_path) } assert.equal(duplicateDocuments, [], 'SCIP document paths should be unique') + const symbolInformation = new Set( + index.documents.flatMap(document => + document.symbols.map(symbol => symbol.symbol) + ) + ) + const indexedPackages = new Set( + [...symbolInformation] + .filter(symbol => !symbol.startsWith('local ')) + .map(symbolPackage) + ) for (const document of index.documents) { const symbols = new Set() const duplicateSymbols: string[] = [] @@ -111,6 +121,19 @@ for (const snapshotDirectory of snapshotDirectories) { [], `${document.relative_path} should not contain duplicate occurrences` ) + const missingInternalSymbols = document.occurrences + .map(occurrence => occurrence.symbol) + .filter( + symbol => + symbol && + indexedPackages.has(symbolPackage(symbol)) && + !symbolInformation.has(symbol) + ) + assert.equal( + missingInternalSymbols, + [], + `${document.relative_path} occurrences in indexed packages should have SymbolInformation` + ) assert.ok( document.language, `${document.relative_path} should have a SCIP document language` @@ -162,4 +185,8 @@ for (const snapshotDirectory of snapshotDirectories) { }) } +function symbolPackage(symbol: string): string { + return symbol.split(' ', 4).join(' ') +} + test.run()