Fix getDefinitionAtPosition to return correct kind for each merged declaration #62729
+92
−6
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #22467
Problem
When multiple declarations share the same name (merged declarations),
getDefinitionAtPosition()returns incorrectkindvalues for non-class declarations.Current behavior:
Given merged declarations (namespace, class, interface), all three return
kind: "class"Expected behavior:
Each declaration should return its actual kind:
kind: "module"kind: "class"kind: "interface"Reproduction
Test Code
Steps to Reproduce Bug (Without Fix)
languageService.getDefinitionAtPosition()on reference toAkindproperty from each returned definitionResult:
All three definitions report
kind: "class"instead of their individual kinds.Root Cause
In
src/services/goToDefinition.ts, the function usesSymbolDisplay.getSymbolKind()which checks combined symbol flags:For merged declarations with flags
SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.Module:flags & SymbolFlags.Classevaluates to trueScriptElementKind.classElementimmediatelySolution
Check each declaration's individual
SyntaxKindinstead of combined symbol flags.Added
getKindFromDeclaration()function:Updated call site in
createDefinitionInfo():Verification
Test Without Fix (CONTRIBUTING.md Requirement)
Per CONTRIBUTING.md: "At least one test should fail in the absence of your non-test code changes."
Procedure:
src/services/goToDefinition.tsnpx hereby runtests --tests=goToDefinitionMergedDeclarationsResult:
Test creates incorrect baseline (all "class") without the fix.
Test creates correct baseline (proper kinds) with the fix.
Test With Fix
Built TypeScript with fix applied.
Ran test:
npx hereby runtests --tests=goToDefinitionMergedDeclarationsResult:
All definitions return correct kinds:
kind: "module"kind: "class"kind: "interface"Full Test Suite
Ran complete test suite:
npx hereby runtests-parallelResult:
Linting: PASSED (0 errors, 0 warnings)
Baseline Updates
The fix corrected
kindvalues in 4 additional test baselines where declarations were previously misreported:goToDefinitionThis.baseline.jsonc
kind: "parameter"kind: "class"goToDefinitionTypeofThis.baseline.jsonc
kind: "parameter"kind: "class"goToTypeDefinition4.baseline.jsonc
kind: "const"kind: "type"goToTypeDefinition_arrayType.baseline.jsonc
kind: "var"kind: "interface"All baseline changes represent bug fixes, not regressions.
Performance Testing
Tested performance impact on
getDefinitionAtPosition()API.Test configuration:
Results:
Fix improves performance by 12.1% due to simplified code path:
Files Changed
Modified (5 files):
src/services/goToDefinition.ts- AddedgetKindFromDeclaration()functiontests/baselines/reference/goToDefinitionThis.baseline.jsonctests/baselines/reference/goToDefinitionTypeofThis.baseline.jsonctests/baselines/reference/goToTypeDefinition4.baseline.jsonctests/baselines/reference/goToTypeDefinition_arrayType.baseline.jsoncNew (2 files):
tests/cases/fourslash/goToDefinitionMergedDeclarations.ts- Test casetests/baselines/reference/goToDefinitionMergedDeclarations.baseline.jsonc- Expected outputTesting Summary
Note on Implementation Approach
Issue comment suggested using
getMeaningFromLocationandhasMatchingMeaningfor filtering definitions. This PR addresses the kind reporting issue (ensuring each declaration returns its correct kind) rather than filtering which definitions to return. The two approaches serve different purposes and could potentially complement each other.