From b4ccd4e93b55a8ff5821be213153c335d871453d Mon Sep 17 00:00:00 2001 From: Svyatoslav Zaytsev Date: Thu, 20 Oct 2022 10:48:06 +0300 Subject: [PATCH] fix(51225): Go-to-definition on case or default should jump to the containing switch statement if available. --- src/services/goToDefinition.ts | 25 +++++++++++++++++++ .../cases/fourslash/goToDefinitionSwitch1.ts | 7 ++++++ .../cases/fourslash/goToDefinitionSwitch2.ts | 7 ++++++ .../cases/fourslash/goToDefinitionSwitch3.ts | 12 +++++++++ .../cases/fourslash/goToDefinitionSwitch4.ts | 11 ++++++++ .../cases/fourslash/goToDefinitionSwitch5.ts | 5 ++++ .../cases/fourslash/goToDefinitionSwitch6.ts | 9 +++++++ 7 files changed, 76 insertions(+) create mode 100644 tests/cases/fourslash/goToDefinitionSwitch1.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitch2.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitch3.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitch4.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitch5.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitch6.ts diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 0ed8284b5df62..376a886e65942 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -32,6 +32,13 @@ namespace ts.GoToDefinition { return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; } + if ([SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword].indexOf(node.kind) !== -1) { + const switchStatement = findAncestor(node.parent, n => n.kind === SyntaxKind.SwitchStatement) as SwitchStatement | undefined; + if (switchStatement) { + return [createDefinitionInfoFromSwitchStatement(switchStatement)]; + } + } + if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { const classDecl = node.parent.parent; const { symbol, failedAliasResolution } = getSymbol(classDecl, typeChecker, stopAtAlias); @@ -510,4 +517,22 @@ namespace ts.GoToDefinition { return false; } } + + function createDefinitionInfoFromSwitchStatement(statement: SwitchStatement): DefinitionInfo { + const switchKeyword = find(statement.getChildren(), n => n.kind === SyntaxKind.SwitchKeyword); + const sourceFile = statement.getSourceFile(); + return { + fileName: sourceFile.fileName, + textSpan: createTextSpanFromNode(switchKeyword!), + kind: ScriptElementKind.label, + name: 'switch', + containerKind: ScriptElementKind.unknown, + containerName: '', + contextSpan: createTextSpanFromNode(statement), + isLocal: false, + isAmbient: false, + unverified: false, + failedAliasResolution: undefined, + }; + } } diff --git a/tests/cases/fourslash/goToDefinitionSwitch1.ts b/tests/cases/fourslash/goToDefinitionSwitch1.ts new file mode 100644 index 0000000000000..c88a6dbfd0f8e --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch1.ts @@ -0,0 +1,7 @@ +/// + +/////*end*/switch (null) { +//// [|/*start*/case|] null: break; +////} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitch2.ts b/tests/cases/fourslash/goToDefinitionSwitch2.ts new file mode 100644 index 0000000000000..c156323907eb9 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch2.ts @@ -0,0 +1,7 @@ +/// + +/////*end*/switch (null) { +//// [|/*start*/default|]: break; +////} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitch3.ts b/tests/cases/fourslash/goToDefinitionSwitch3.ts new file mode 100644 index 0000000000000..cefa4ef467531 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch3.ts @@ -0,0 +1,12 @@ +/// + +/////*end1*/switch (null) { +//// [|/*start1*/default|]: { +//// /*end2*/switch (null) { +//// [|/*start2*/default|]: break; +//// } +//// }; +////} + +verify.goToDefinition("start1", "end1"); +verify.goToDefinition("start2", "end2"); diff --git a/tests/cases/fourslash/goToDefinitionSwitch4.ts b/tests/cases/fourslash/goToDefinitionSwitch4.ts new file mode 100644 index 0000000000000..e18ecd98dce12 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch4.ts @@ -0,0 +1,11 @@ +/// + +//// switch (null) { +//// case null: break; +//// } +//// +//// /*end*/switch (null) { +//// [|/*start*/case|] null: break; +//// } + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitch5.ts b/tests/cases/fourslash/goToDefinitionSwitch5.ts new file mode 100644 index 0000000000000..101b180633460 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch5.ts @@ -0,0 +1,5 @@ +/// + +/////*end*/export [|/*start*/default|] {} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitch6.ts b/tests/cases/fourslash/goToDefinitionSwitch6.ts new file mode 100644 index 0000000000000..7db217d26692e --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitch6.ts @@ -0,0 +1,9 @@ +/// + +/////*d*/export default { [|/*a*/case|] }; +////[|/*b*/default|]; +////[|/*c*/case|] 42; + +verify.goToDefinition("a", "a"); +verify.goToDefinition("b", "d"); +verify.goToDefinition("c", []);