From 8ba90f9f927e07cd685d886c8639a99d2bfe1e8b Mon Sep 17 00:00:00 2001 From: Robbie Hume Date: Thu, 26 Mar 2026 11:04:26 -0500 Subject: [PATCH] Fix shorthand property resolution in typed contexts When a shorthand property (e.g., `new ApolloServer({ resolvers })`) is passed to a typed parameter, SCIP emits the type-property reference but misses the local variable reference. This adds the missing reference by checking if the original node is a shorthand property assignment and emitting an additional occurrence for the local binding. Fixes behavior reported in sourcegraph/scip-typescript#415 and #440. --- .../src/object-literals-call-signatures.ts | 2 ++ src/FileIndexer.ts | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/snapshots/output/syntax/src/object-literals-call-signatures.ts b/snapshots/output/syntax/src/object-literals-call-signatures.ts index f23e6cff..c2c82e73 100644 --- a/snapshots/output/syntax/src/object-literals-call-signatures.ts +++ b/snapshots/output/syntax/src/object-literals-call-signatures.ts @@ -151,8 +151,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/src/FileIndexer.ts b/src/FileIndexer.ts index 991ce9dc..61be6fbd 100644 --- a/src/FileIndexer.ts +++ b/src/FileIndexer.ts @@ -254,6 +254,27 @@ export class FileIndexer { break } } + // Shorthand properties in typed contexts: also emit local variable reference. + // When getDeclarationsForPropertyAssignment finds type-side declarations, + // isDefinitionNode is false, so handleShorthandPropertyDefinition is never + // called. This block emits the missing local variable reference. + if ( + declarations.length > 0 && + ts.isShorthandPropertyAssignment(node.parent) + ) { + const valueSymbol = + this.checker.getShorthandAssignmentValueSymbol(node.parent) + if (valueSymbol) { + for (const decl of valueSymbol.declarations || []) { + const scipSymbol = this.scipSymbol(decl) + if (!scipSymbol.isEmpty()) { + this.pushOccurrence( + new scip.scip.Occurrence({ range, symbol: scipSymbol.value }) + ) + } + } + } + } } /**