Support goto-definition for index signatures (#23220)
* Support goto-definition for index signatures * Use checker.getIndexInfoOfType * Handle undefined info.declaration
This commit is contained in:
parent
fb02d670ff
commit
998beadba2
|
@ -1,6 +1,6 @@
|
|||
/* @internal */
|
||||
namespace ts.GoToDefinition {
|
||||
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] {
|
||||
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined {
|
||||
const reference = getReferenceAtPosition(sourceFile, position, program);
|
||||
if (reference) {
|
||||
return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
|
||||
|
@ -29,7 +29,7 @@ namespace ts.GoToDefinition {
|
|||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
|
||||
if (!symbol) {
|
||||
return undefined;
|
||||
return getDefinitionInfoForIndexSignatures(node, typeChecker);
|
||||
}
|
||||
|
||||
// If this is an alias, and the request came at the declaration location
|
||||
|
@ -157,6 +157,16 @@ namespace ts.GoToDefinition {
|
|||
return { definitions, textSpan };
|
||||
}
|
||||
|
||||
// At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations.
|
||||
function getDefinitionInfoForIndexSignatures(node: Node, checker: TypeChecker): DefinitionInfo[] | undefined {
|
||||
if (!isPropertyAccessExpression(node.parent) || node.parent.name !== node) return;
|
||||
const type = checker.getTypeAtLocation(node.parent.expression);
|
||||
return mapDefined(type.isUnionOrIntersection() ? type.types : [type], nonUnionType => {
|
||||
const info = checker.getIndexInfoOfType(nonUnionType, IndexKind.String);
|
||||
return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration);
|
||||
});
|
||||
}
|
||||
|
||||
// Go to the original declaration for cases:
|
||||
//
|
||||
// (1) when the aliased symbol was declared in the location(parent).
|
||||
|
|
15
tests/cases/fourslash/goToDefinitionIndexSignature.ts
Normal file
15
tests/cases/fourslash/goToDefinitionIndexSignature.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface I {
|
||||
//// /*defI*/[x: string]: boolean;
|
||||
////}
|
||||
////interface J {
|
||||
//// /*defJ*/[x: string]: number;
|
||||
////}
|
||||
////declare const i: I;
|
||||
////i.[|/*useI*/foo|];
|
||||
////declare const ij: I | J;
|
||||
////ij.[|/*useIJ*/foo|];
|
||||
|
||||
verify.goToDefinition("useI", ["defI"]);
|
||||
verify.goToDefinition("useIJ", ["defI", "defJ"]);
|
11
tests/cases/fourslash/goToDefinitionIndexSignature2.ts
Normal file
11
tests/cases/fourslash/goToDefinitionIndexSignature2.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// Tests that we don't crash for an index signature with no declaration.
|
||||
|
||||
// @allowJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
////const o = {};
|
||||
////o.[|/*use*/foo|];
|
||||
|
||||
verify.goToDefinition("use", []);
|
|
@ -8,5 +8,5 @@
|
|||
////let t: Gen;
|
||||
////var { x, ...rest } = t;
|
||||
////rest.[|/*2*/parent|];
|
||||
const ranges = test.ranges();
|
||||
|
||||
verify.goToDefinition('2', [ '1' ]);
|
||||
|
|
Loading…
Reference in a new issue