Skip to content

Commit d7575ab

Browse files
sviat9440Святослав Зайцев
authored andcommitted
fix(51225): Go-to-definition on case or default should jump to the containing switch statement if available.
1 parent 8ac4652 commit d7575ab

8 files changed

+95
-4
lines changed

src/services/goToDefinition.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,22 @@ namespace ts.GoToDefinition {
2626
return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217
2727
}
2828

29-
if (node.kind === SyntaxKind.ReturnKeyword) {
30-
const functionDeclaration = findAncestor(node.parent, n =>
31-
isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
32-
return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
29+
switch (node.kind) {
30+
case SyntaxKind.ReturnKeyword:
31+
const functionDeclaration = findAncestor(node.parent, n =>
32+
isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
33+
return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
34+
case SyntaxKind.DefaultKeyword:
35+
if (!isDefaultClause(node.parent)) {
36+
break;
37+
}
38+
// falls through
39+
case SyntaxKind.CaseKeyword:
40+
const switchStatement = findAncestor(node.parent, isSwitchStatement);
41+
if (switchStatement) {
42+
return [createDefinitionInfoFromStatement(switchStatement, SyntaxKind.SwitchKeyword, sourceFile, "switch")];
43+
}
44+
break;
3345
}
3446

3547
if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) {
@@ -510,4 +522,25 @@ namespace ts.GoToDefinition {
510522
return false;
511523
}
512524
}
525+
526+
interface StatementWithExpression extends Statement {
527+
readonly expression: Expression
528+
}
529+
530+
function createDefinitionInfoFromStatement<K extends KeywordSyntaxKind>(statement: StatementWithExpression, keywordKind: K, sourceFile: SourceFile, name: string): DefinitionInfo {
531+
const keyword = find(statement.getChildren(sourceFile), (node): node is Token<K> => node.kind === keywordKind)!;
532+
return {
533+
fileName: sourceFile.fileName,
534+
textSpan: createTextSpanFromNode(keyword, sourceFile),
535+
kind: ScriptElementKind.keyword,
536+
name,
537+
containerKind: undefined!,
538+
containerName: "",
539+
contextSpan: createTextSpanFromNode(statement.expression, sourceFile),
540+
isLocal: true,
541+
isAmbient: false,
542+
unverified: false,
543+
failedAliasResolution: undefined,
544+
};
545+
}
513546
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////*end*/switch (null) {
4+
//// [|/*start*/case|] null: break;
5+
////}
6+
7+
verify.goToDefinition("start", "end");
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////*end*/switch (null) {
4+
//// [|/*start*/default|]: break;
5+
////}
6+
7+
verify.goToDefinition("start", "end");
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////*end1*/switch (null) {
4+
//// [|/*start1*/default|]: {
5+
//// /*end2*/switch (null) {
6+
//// [|/*start2*/default|]: break;
7+
//// }
8+
//// };
9+
////}
10+
11+
verify.goToDefinition("start1", "end1");
12+
verify.goToDefinition("start2", "end2");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
//// switch (null) {
4+
//// case null: break;
5+
//// }
6+
////
7+
//// /*end*/switch (null) {
8+
//// [|/*start*/case|] null: break;
9+
//// }
10+
11+
verify.goToDefinition("start", "end");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////*end*/export [|/*start*/default|] {}
4+
5+
verify.goToDefinition("start", "end");
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////*d*/export default { [|/*a*/case|] };
4+
////[|/*b*/default|];
5+
////[|/*c*/case|] 42;
6+
7+
verify.goToDefinition("a", "a");
8+
verify.goToDefinition("b", "d");
9+
verify.goToDefinition("c", []);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////switch (null) {
4+
//// case null:
5+
//// /*end*/export [|/*start*/default|] 123;
6+
7+
verify.goToDefinition("start", "end");

0 commit comments

Comments
 (0)