From 3242e3371bc489eb13644f04323c646dd74fd42e Mon Sep 17 00:00:00 2001 From: Erik Seliger Date: Sat, 22 Aug 2026 22:47:32 +0000 Subject: [PATCH 1/2] Emit external symbol information Amp-Thread-ID: https://ampcode.com/threads/T-01a029e2-5095-710a-9cce-0c6d8645c173 --- src/main.test.ts | 34 +++++++++++++++++++++++++++++++++- src/main.ts | 19 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main.test.ts b/src/main.test.ts index ff06cdd7..8cac7283 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -88,6 +88,25 @@ for (const snapshotDirectory of snapshotDirectories) { document.symbols.map(symbol => symbol.symbol) ) ) + const externalSymbolInformation = new Set( + index.external_symbols.map(symbol => symbol.symbol) + ) + assert.equal( + externalSymbolInformation.size, + index.external_symbols.length, + 'external SymbolInformation should be unique' + ) + assert.equal( + index.external_symbols + .map(symbol => symbol.symbol) + .filter(symbol => symbolInformation.has(symbol)), + [], + 'symbols should not be both internal and external' + ) + const availableSymbols = new Set([ + ...symbolInformation, + ...externalSymbolInformation, + ]) const indexedPackages = new Set( [...symbolInformation] .filter(symbol => !symbol.startsWith('local ')) @@ -121,6 +140,19 @@ for (const snapshotDirectory of snapshotDirectories) { [], `${document.relative_path} should not contain duplicate occurrences` ) + const missingOccurrenceSymbols = document.occurrences + .map(occurrence => occurrence.symbol) + .filter( + symbol => + symbol && + !symbol.startsWith('local ') && + !availableSymbols.has(symbol) + ) + assert.equal( + missingOccurrenceSymbols, + [], + `${document.relative_path} global occurrences should have SymbolInformation` + ) const missingInternalSymbols = document.occurrences .map(occurrence => occurrence.symbol) .filter( @@ -157,7 +189,7 @@ for (const snapshotDirectory of snapshotDirectories) { ? fs.readFileSync(outputPath).toString() : '' const input = Input.fromFile(inputPath) - const obtained = formatSnapshot(input, document) + const obtained = formatSnapshot(input, document, index.external_symbols) if (obtained === expected) { // Test passed continue diff --git a/src/main.ts b/src/main.ts index e6b5b40c..787d1697 100644 --- a/src/main.ts +++ b/src/main.ts @@ -46,8 +46,20 @@ export function indexCommand( } const output = fs.openSync(options.output, 'w') let documentCount = 0 + const definedSymbols = new Set() + const occurrenceSymbols = new Set() const writeIndex = (index: scip.scip.Index): void => { documentCount += index.documents.length + for (const document of index.documents) { + for (const symbol of document.symbols) { + definedSymbols.add(symbol.symbol) + } + for (const occurrence of document.occurrences) { + if (occurrence.symbol && !occurrence.symbol.startsWith('local ')) { + occurrenceSymbols.add(occurrence.symbol) + } + } + } fs.writeSync(output, index.serializeBinary()) } @@ -85,6 +97,13 @@ export function indexCommand( cache ) } + writeIndex( + new scip.scip.Index({ + external_symbols: [...occurrenceSymbols] + .filter(symbol => !definedSymbols.has(symbol)) + .map(symbol => new scip.scip.SymbolInformation({ symbol })), + }) + ) } finally { fs.close(output) if (documentCount > 0) { From e670cdd1de9ac4eb4c0159c65f1fef90ef297fd5 Mon Sep 17 00:00:00 2001 From: Erik Seliger Date: Sun, 23 Aug 2026 00:48:56 +0000 Subject: [PATCH 2/2] Render external symbols in snapshots Amp-Thread-ID: https://ampcode.com/threads/T-01a029e2-5095-710a-9cce-0c6d8645c173 --- snapshots/input/react/src/LoaderInput.tsx | 2 ++ snapshots/output/react/src/LoaderInput.tsx | 10 ++++++++++ src/SnapshotTesting.ts | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/snapshots/input/react/src/LoaderInput.tsx b/snapshots/input/react/src/LoaderInput.tsx index c89ec888..0fc5a33e 100644 --- a/snapshots/input/react/src/LoaderInput.tsx +++ b/snapshots/input/react/src/LoaderInput.tsx @@ -1,3 +1,5 @@ +// format-options: showExternalSymbols + import React from 'react' /** Takes loading prop, input component as child */ diff --git a/snapshots/output/react/src/LoaderInput.tsx b/snapshots/output/react/src/LoaderInput.tsx index 957ddbb1..ef370ad8 100644 --- a/snapshots/output/react/src/LoaderInput.tsx +++ b/snapshots/output/react/src/LoaderInput.tsx @@ -1,9 +1,13 @@ // language TypeScriptReact // < definition react-example 1.0.0 src/`LoaderInput.tsx`/ +// format-options: showExternalSymbols + import React from 'react' // ^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/ +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/ // ^^^^^^^ reference @types/react 19.2.18 `index.d.ts`/ +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/ /** Takes loading prop, input component as child */ interface Props { @@ -14,12 +18,14 @@ interface Props { //^^^^^^^^ definition react-example 1.0.0 src/`LoaderInput.tsx`/Props#children. // ^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/ // ^^^^^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/ReactNode# +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/ReactNode# } export const LoaderInput: React.FunctionComponent = ({ // ^^^^^^^^^^^ definition react-example 1.0.0 src/`LoaderInput.tsx`/LoaderInput. // ^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/ // ^^^^^^^^^^^^^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/FunctionComponent# +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/FunctionComponent# // ^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props# loading, //^^^^^^^ definition local 3 @@ -30,12 +36,15 @@ export const LoaderInput: React.FunctionComponent = ({ }) => (
// ^^^ reference @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#div. +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#div. // ^^^^^^^^^ reference @types/react 19.2.18 `index.d.ts`/React/HTMLAttributes#className. +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/HTMLAttributes#className. {children} // ^^^^^^^^ reference local 4 {loading &&

spinner

} // ^^^^^^^ reference local 3 // ^ reference @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#p. +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#p. // ^ reference @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#p.
// ^^^ reference @types/react 19.2.18 `index.d.ts`/React/JSX/IntrinsicElements#div. @@ -51,6 +60,7 @@ export const LoaderInput2: React.FunctionComponent = props => { // ^^^^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/LoaderInput. // ^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#loading. // ^^^ reference @types/react 19.2.18 `index.d.ts`/React/Attributes#key. +// external SymbolInformation @types/react 19.2.18 `index.d.ts`/React/Attributes#key. // ^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#children. // ^^^^^ reference local 6 // ^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#children. diff --git a/src/SnapshotTesting.ts b/src/SnapshotTesting.ts index da810e8e..66fc1af1 100644 --- a/src/SnapshotTesting.ts +++ b/src/SnapshotTesting.ts @@ -18,11 +18,13 @@ function getSymbolTable( function parseOptions(lines: string[]): { showDocs: boolean + showExternalSymbols: boolean showKinds: boolean showRanges: boolean } { const formatOptions = { showDocs: false, + showExternalSymbols: false, showKinds: false, showRanges: false, } @@ -184,6 +186,10 @@ export function formatSnapshot( const externalSymbol = externalSymbolTable.get(symbol) if (externalSymbol) { + if (formatOptions.showExternalSymbols) { + out.push(prefix) + out.push(`external SymbolInformation ${symbolNameForSnapshot(symbol)}`) + } pushKind(externalSymbol.kind) pushOneDoc(externalSymbol.documentation, true) pushOneRelationship(externalSymbol.relationships)