From 8b501f579c554771c513891bd439dd08b2e8dd6a Mon Sep 17 00:00:00 2001 From: Erik Seliger Date: Sat, 22 Aug 2026 21:07:14 +0000 Subject: [PATCH] Fix contextual shorthand property references Amp-Thread-ID: https://ampcode.com/threads/T-01a029e2-5095-710a-9cce-0c6d8645c173 --- .../syntax/src/property-assignment-reference.ts | 8 ++++++++ .../input/syntax/src/property-assignment.ts | 1 + .../src/object-literals-call-signatures.ts | 2 ++ .../syntax/src/property-assignment-reference.ts | 17 +++++++++++++++++ .../output/syntax/src/property-assignment.ts | 2 ++ src/FileIndexer.ts | 17 +++++++++++------ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/snapshots/input/syntax/src/property-assignment-reference.ts b/snapshots/input/syntax/src/property-assignment-reference.ts index 0ebb2fe4..5428c324 100644 --- a/snapshots/input/syntax/src/property-assignment-reference.ts +++ b/snapshots/input/syntax/src/property-assignment-reference.ts @@ -1,8 +1,16 @@ import { + importedShorthand, propertyAssignment, shorthandPropertyAssignment, } from './property-assignment' +interface ContextualProperties { + importedShorthand: string +} + +function acceptContext(_value: ContextualProperties): void {} + export function run(): string { + acceptContext({ importedShorthand }) return propertyAssignment().a + shorthandPropertyAssignment().a } diff --git a/snapshots/input/syntax/src/property-assignment.ts b/snapshots/input/syntax/src/property-assignment.ts index dca670ac..36663d13 100644 --- a/snapshots/input/syntax/src/property-assignment.ts +++ b/snapshots/input/syntax/src/property-assignment.ts @@ -5,6 +5,7 @@ export function shorthandPropertyAssignment() { const a = 'a' return { a } } +export const importedShorthand = 'value' type A = { a: string; b: number } export function typedPropertyAssignment(): A { // prettier-ignore diff --git a/snapshots/output/syntax/src/object-literals-call-signatures.ts b/snapshots/output/syntax/src/object-literals-call-signatures.ts index d3b5a099..c79832c2 100644 --- a/snapshots/output/syntax/src/object-literals-call-signatures.ts +++ b/snapshots/output/syntax/src/object-literals-call-signatures.ts @@ -152,8 +152,10 @@ export function handleShorthand() { //^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`object-literals-call-signatures.ts`/consumesInterface(). interfaceMethod, // ^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`reusable-types.ts`/Superinterface#interfaceMethod(). +// ^^^^^^^^^^^^^^^ reference local 26 property, // ^^^^^^^^ reference syntax 1.0.0 src/`reusable-types.ts`/Superinterface#property. +// ^^^^^^^^ reference local 23 }) } diff --git a/snapshots/output/syntax/src/property-assignment-reference.ts b/snapshots/output/syntax/src/property-assignment-reference.ts index 812a3ae1..cfb6a4da 100644 --- a/snapshots/output/syntax/src/property-assignment-reference.ts +++ b/snapshots/output/syntax/src/property-assignment-reference.ts @@ -2,6 +2,8 @@ // < definition syntax 1.0.0 src/`property-assignment-reference.ts`/ import { + importedShorthand, +//^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment.ts`/importedShorthand. propertyAssignment, //^^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment.ts`/propertyAssignment(). shorthandPropertyAssignment, @@ -9,8 +11,23 @@ import { } from './property-assignment' // ^^^^^^^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment.ts`/ +interface ContextualProperties { +// ^^^^^^^^^^^^^^^^^^^^ definition syntax 1.0.0 src/`property-assignment-reference.ts`/ContextualProperties# + importedShorthand: string +//^^^^^^^^^^^^^^^^^ definition syntax 1.0.0 src/`property-assignment-reference.ts`/ContextualProperties#importedShorthand. +} + +function acceptContext(_value: ContextualProperties): void {} +// ^^^^^^^^^^^^^ definition syntax 1.0.0 src/`property-assignment-reference.ts`/acceptContext(). +// ^^^^^^ definition syntax 1.0.0 src/`property-assignment-reference.ts`/acceptContext().(_value) +// ^^^^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment-reference.ts`/ContextualProperties# + export function run(): string { // ^^^ definition syntax 1.0.0 src/`property-assignment-reference.ts`/run(). + acceptContext({ importedShorthand }) +//^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment-reference.ts`/acceptContext(). +// ^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment-reference.ts`/ContextualProperties#importedShorthand. +// ^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment.ts`/importedShorthand. return propertyAssignment().a + shorthandPropertyAssignment().a // ^^^^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`property-assignment.ts`/propertyAssignment(). // ^ reference syntax 1.0.0 src/`property-assignment.ts`/a0: diff --git a/snapshots/output/syntax/src/property-assignment.ts b/snapshots/output/syntax/src/property-assignment.ts index 26656820..b5e0ec2d 100644 --- a/snapshots/output/syntax/src/property-assignment.ts +++ b/snapshots/output/syntax/src/property-assignment.ts @@ -14,6 +14,8 @@ export function shorthandPropertyAssignment() { // ^ definition syntax 1.0.0 src/`property-assignment.ts`/a1: // ^ reference local 2 } +export const importedShorthand = 'value' +// ^^^^^^^^^^^^^^^^^ definition syntax 1.0.0 src/`property-assignment.ts`/importedShorthand. type A = { a: string; b: number } // ^ definition syntax 1.0.0 src/`property-assignment.ts`/A# // ^ definition syntax 1.0.0 src/`property-assignment.ts`/A#typeLiteral3:a. diff --git a/src/FileIndexer.ts b/src/FileIndexer.ts index 2cadbeca..bcae42ee 100644 --- a/src/FileIndexer.ts +++ b/src/FileIndexer.ts @@ -249,12 +249,12 @@ export class FileIndexer { ) if (isDefinitionNode) { this.addSymbolInformation(node, sym, declaration, scipSymbol) - this.handleShorthandPropertyDefinition(declaration, range) this.handleObjectBindingPattern(node, range) // Only emit one symbol for definitions sites, see https://github.com/sourcegraph/lsif-typescript/issues/45 break } } + this.handleShorthandPropertyValue(node.parent, range) } /** @@ -293,7 +293,7 @@ export class FileIndexer { /** * Handles the special-case around shorthand property syntax so that we emit two occurrences instead of only one. - * Shorthand properties need two symbols because they both define a symbol and reference a symbol. For example: + * Shorthand properties need two symbols because the token is both a property and a reference to its value. For example: * ``` * const a = 42 * const b = {a} @@ -301,20 +301,25 @@ export class FileIndexer { * const c = b.a * // ^ reference to the property `a`, not the local const * ``` + * Contextually typed properties similarly reference both the contextual property + * and the local or imported value at the same range. */ - private handleShorthandPropertyDefinition( + private handleShorthandPropertyValue( declaration: ts.Node, range: number[] ): void { - if (declaration.kind !== ts.SyntaxKind.ShorthandPropertyAssignment) { + if (!ts.isShorthandPropertyAssignment(declaration)) { return } - const valueSymbol = + let valueSymbol = this.checker.getShorthandAssignmentValueSymbol(declaration) if (!valueSymbol) { return } - for (const symbol of valueSymbol?.declarations || []) { + if (valueSymbol.flags & ts.SymbolFlags.Alias) { + valueSymbol = this.checker.getAliasedSymbol(valueSymbol) + } + for (const symbol of valueSymbol.declarations || []) { const scipSymbol = this.scipSymbol(symbol) if (scipSymbol.isEmpty()) { continue