From 7721e8375bcb4416ca057bac164f089b3c16023e Mon Sep 17 00:00:00 2001 From: Svyatoslav Zaytsev Date: Thu, 20 Oct 2022 10:48:06 +0300 Subject: [PATCH 1/9] fix(51225): Go-to-definition on case or default should jump to the containing switch statement if available. --- src/services/goToDefinition.ts | 41 +++++++++++++++++-- .../fourslash/goToDefinitionSwitchCase1.ts | 7 ++++ .../fourslash/goToDefinitionSwitchCase2.ts | 7 ++++ .../fourslash/goToDefinitionSwitchCase3.ts | 12 ++++++ .../fourslash/goToDefinitionSwitchCase4.ts | 11 +++++ .../fourslash/goToDefinitionSwitchCase5.ts | 5 +++ .../fourslash/goToDefinitionSwitchCase6.ts | 9 ++++ .../fourslash/goToDefinitionSwitchCase7.ts | 7 ++++ 8 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase1.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase2.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase3.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase4.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase5.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase6.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase7.ts diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 0ed8284b5df62..3601262244a68 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -26,10 +26,22 @@ namespace ts.GoToDefinition { return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 } - if (node.kind === SyntaxKind.ReturnKeyword) { - const functionDeclaration = findAncestor(node.parent, n => - isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; - return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + switch (node.kind) { + case SyntaxKind.ReturnKeyword: + const functionDeclaration = findAncestor(node.parent, n => + isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; + return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + case SyntaxKind.DefaultKeyword: + if (!isDefaultClause(node.parent)) { + break; + } + // falls through + case SyntaxKind.CaseKeyword: + const switchStatement = findAncestor(node.parent, isSwitchStatement); + if (switchStatement) { + return [createDefinitionInfoFromStatement(switchStatement, SyntaxKind.SwitchKeyword, sourceFile, "switch")]; + } + break; } if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { @@ -510,4 +522,25 @@ namespace ts.GoToDefinition { return false; } } + + interface StatementWithExpression extends Statement { + readonly expression: Expression + } + + function createDefinitionInfoFromStatement(statement: StatementWithExpression, keywordKind: KeywordSyntaxKind, sourceFile: SourceFile, name: string): DefinitionInfo { + const keyword = find(statement.getChildren(sourceFile), (node) => node.kind === keywordKind)!; + return { + fileName: sourceFile.fileName, + textSpan: createTextSpanFromNode(keyword, sourceFile), + kind: ScriptElementKind.keyword, + name, + containerKind: undefined!, + containerName: "", + contextSpan: createTextSpanFromNode(statement.expression, sourceFile), + isLocal: true, + isAmbient: false, + unverified: false, + failedAliasResolution: undefined, + }; + } } diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts new file mode 100644 index 0000000000000..63a7a3e8c968e --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts @@ -0,0 +1,7 @@ +/// + +/////*end*/switch (null) { +//// [|/*start*/case|] null: break; +////} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase2.ts b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts new file mode 100644 index 0000000000000..613068c15e2f9 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts @@ -0,0 +1,7 @@ +/// + +/////*end*/switch (null) { +//// [|/*start*/default|]: break; +////} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase3.ts b/tests/cases/fourslash/goToDefinitionSwitchCase3.ts new file mode 100644 index 0000000000000..5b99bff7b822f --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase3.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/goToDefinitionSwitchCase4.ts b/tests/cases/fourslash/goToDefinitionSwitchCase4.ts new file mode 100644 index 0000000000000..e1cf068bafa64 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase4.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/goToDefinitionSwitchCase5.ts b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts new file mode 100644 index 0000000000000..cb8ff7ca0a6fa --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts @@ -0,0 +1,5 @@ +/// + +/////*end*/export [|/*start*/default|] {} + +verify.goToDefinition("start", "end"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase6.ts b/tests/cases/fourslash/goToDefinitionSwitchCase6.ts new file mode 100644 index 0000000000000..f7d11e21db7a6 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase6.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", []); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase7.ts b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts new file mode 100644 index 0000000000000..9cc74c641c090 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts @@ -0,0 +1,7 @@ +/// + +////switch (null) { +//// case null: +//// /*end*/export [|/*start*/default|] 123; + +verify.goToDefinition("start", "end"); From 1995f3346b06798ec81fc8c7d9177708e734c0ba Mon Sep 17 00:00:00 2001 From: Svyatoslav Zaytsev Date: Thu, 24 Nov 2022 08:31:29 +0300 Subject: [PATCH 2/9] fix(51225): Fix context span --- src/services/goToDefinition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 012790f3af6ae..f78445f577697 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -664,7 +664,7 @@ function createDefinitionInfoFromStatement( name, containerKind: undefined!, containerName: "", - contextSpan: createTextSpanFromNode(statement.expression, sourceFile), + contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.expression.getEnd()), isLocal: true, isAmbient: false, unverified: false, From 03d4b408102c9a2fa7f03d2f171b864e7ab1e1ef Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:15:46 -0800 Subject: [PATCH 3/9] port tests to baselineGoToDefinition --- src/services/goToDefinition.ts | 3 -- .../goToDefinitionSwitchCase1.baseline.jsonc | 17 +++++++ .../goToDefinitionSwitchCase2.baseline.jsonc | 17 +++++++ .../goToDefinitionSwitchCase3.baseline.jsonc | 45 ++++++++++++++++++ .../goToDefinitionSwitchCase4.baseline.jsonc | 21 +++++++++ .../goToDefinitionSwitchCase5.baseline.jsonc | 16 +++++++ .../goToDefinitionSwitchCase6.baseline.jsonc | 47 +++++++++++++++++++ .../goToDefinitionSwitchCase7.baseline.jsonc | 18 +++++++ .../fourslash/goToDefinitionSwitchCase1.ts | 4 +- .../fourslash/goToDefinitionSwitchCase2.ts | 4 +- .../fourslash/goToDefinitionSwitchCase3.ts | 7 ++- .../fourslash/goToDefinitionSwitchCase4.ts | 4 +- .../fourslash/goToDefinitionSwitchCase5.ts | 4 +- .../fourslash/goToDefinitionSwitchCase6.ts | 6 +-- .../fourslash/goToDefinitionSwitchCase7.ts | 4 +- 15 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 0e08eaffa7d97..09b6bc143529a 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -71,12 +71,9 @@ import { isPropertyName, isRightSideOfPropertyAccess, isStaticModifier, -<<<<<<< HEAD isSwitchStatement, -======= isTypeAliasDeclaration, isTypeReferenceNode, ->>>>>>> main isVariableDeclaration, KeywordSyntaxKind, last, diff --git a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc new file mode 100644 index 0000000000000..7458f3c2d3466 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc @@ -0,0 +1,17 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase1.ts === +// <|[|switch|] (null|>) { +// /*GOTO DEF*/case null: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc new file mode 100644 index 0000000000000..4478b78fcbda2 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc @@ -0,0 +1,17 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase2.ts === +// <|[|switch|] (null|>) { +// /*GOTO DEF*/default: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc new file mode 100644 index 0000000000000..3d02e9f362772 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc @@ -0,0 +1,45 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === +// <|[|switch|] (null|>) { +// /*GOTO DEF*/default: { +// switch (null) { +// default: break; +// } +// }; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === +// switch (null) { +// default: { +// <|[|switch|] (null|>) { +// /*GOTO DEF*/default: break; +// } +// }; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc new file mode 100644 index 0000000000000..f56a5925fffb9 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc @@ -0,0 +1,21 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase4.ts === +// switch (null) { +// case null: break; +// } +// +// <|[|switch|] (null|>) { +// /*GOTO DEF*/case null: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc new file mode 100644 index 0000000000000..1277d0b5dd945 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc @@ -0,0 +1,16 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase5.ts === +// [|export /*GOTO DEF*/default {}|] + + // === Details === + [ + { + "kind": "property", + "name": "default", + "containerName": "\"/tests/cases/fourslash/goToDefinitionSwitchCase5\"", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc new file mode 100644 index 0000000000000..3f6894203dc69 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc @@ -0,0 +1,47 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// export default { /*GOTO DEF*/[|{| textSpan: true |}case|] }; +// default; +// case 42; + + // === Details === + [ + { + "kind": "property", + "name": "case", + "containerName": "__object", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// [|export default { case }; +// /*GOTO DEF*/default; +// case 42;|] + + // === Details === + [ + { + "kind": "module", + "name": "\"/tests/cases/fourslash/goToDefinitionSwitchCase6\"", + "containerName": "", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// export default { case }; +// default; +// /*GOTO DEF*/case 42; \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc new file mode 100644 index 0000000000000..bf6c818dc552e --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc @@ -0,0 +1,18 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase7.ts === +// switch (null) { +// case null: +// [|export /*GOTO DEF*/default 123;|] + + // === Details === + [ + { + "kind": "var", + "name": "default", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts index 63a7a3e8c968e..d2be83a7713ee 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts @@ -1,7 +1,7 @@ /// -/////*end*/switch (null) { +////switch (null) { //// [|/*start*/case|] null: break; ////} -verify.goToDefinition("start", "end"); +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase2.ts b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts index 613068c15e2f9..3d480dd198afb 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase2.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts @@ -1,7 +1,7 @@ /// -/////*end*/switch (null) { +////switch (null) { //// [|/*start*/default|]: break; ////} -verify.goToDefinition("start", "end"); +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase3.ts b/tests/cases/fourslash/goToDefinitionSwitchCase3.ts index 5b99bff7b822f..0dce0e7c153fc 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase3.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase3.ts @@ -1,12 +1,11 @@ /// -/////*end1*/switch (null) { +////switch (null) { //// [|/*start1*/default|]: { -//// /*end2*/switch (null) { +//// switch (null) { //// [|/*start2*/default|]: break; //// } //// }; ////} -verify.goToDefinition("start1", "end1"); -verify.goToDefinition("start2", "end2"); +verify.baselineGoToDefinition("start1", "start2"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase4.ts b/tests/cases/fourslash/goToDefinitionSwitchCase4.ts index e1cf068bafa64..db4b801415dc2 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase4.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase4.ts @@ -4,8 +4,8 @@ //// case null: break; //// } //// -//// /*end*/switch (null) { +//// switch (null) { //// [|/*start*/case|] null: break; //// } -verify.goToDefinition("start", "end"); +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase5.ts b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts index cb8ff7ca0a6fa..83e8f28ad0aab 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase5.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts @@ -1,5 +1,5 @@ /// -/////*end*/export [|/*start*/default|] {} +////export [|/*start*/default|] {} -verify.goToDefinition("start", "end"); +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase6.ts b/tests/cases/fourslash/goToDefinitionSwitchCase6.ts index f7d11e21db7a6..b6ac5daf8f5f8 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase6.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase6.ts @@ -1,9 +1,7 @@ /// -/////*d*/export default { [|/*a*/case|] }; +////export default { [|/*a*/case|] }; ////[|/*b*/default|]; ////[|/*c*/case|] 42; -verify.goToDefinition("a", "a"); -verify.goToDefinition("b", "d"); -verify.goToDefinition("c", []); +verify.baselineGoToDefinition("a", "b", "c"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase7.ts b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts index 9cc74c641c090..244b4b0b6a726 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase7.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts @@ -2,6 +2,6 @@ ////switch (null) { //// case null: -//// /*end*/export [|/*start*/default|] 123; +//// export [|/*start*/default|] 123; -verify.goToDefinition("start", "end"); +verify.baselineGoToDefinition("start"); From d692bbf885c78af5b4b49c51fc8e0754ce2fd691 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:24:05 -0800 Subject: [PATCH 4/9] dprint fmt --- src/services/goToDefinition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 09b6bc143529a..803ced5c66639 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -750,7 +750,7 @@ function createDefinitionInfoFromStatement( sourceFile: SourceFile, name: string, ): DefinitionInfo { - const keyword = find(statement.getChildren(sourceFile), (node) => node.kind === keywordKind)!; + const keyword = find(statement.getChildren(sourceFile), node => node.kind === keywordKind)!; return { fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(keyword, sourceFile), From a97f70407fa2e9f2ece32004e68c320de44601dc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:43:01 -0800 Subject: [PATCH 5/9] Revert context span change Per https://github.com/microsoft/TypeScript/pull/51236#issuecomment-1414291555 --- src/services/goToDefinition.ts | 11 +++-------- .../goToDefinitionSwitchCase1.baseline.jsonc | 2 +- .../goToDefinitionSwitchCase2.baseline.jsonc | 2 +- .../goToDefinitionSwitchCase3.baseline.jsonc | 4 ++-- .../goToDefinitionSwitchCase4.baseline.jsonc | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 803ced5c66639..7e5cc4d235b32 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -15,7 +15,6 @@ import { DefinitionInfoAndBoundSpan, emptyArray, every, - Expression, FileReference, filter, find, @@ -95,7 +94,7 @@ import { skipTrivia, some, SourceFile, - Statement, + SwitchStatement, Symbol, SymbolDisplay, SymbolFlags, @@ -740,12 +739,8 @@ function isConstructorLike(node: Node): boolean { } } -interface StatementWithExpression extends Statement { - readonly expression: Expression; -} - function createDefinitionInfoFromStatement( - statement: StatementWithExpression, + statement: SwitchStatement, keywordKind: KeywordSyntaxKind, sourceFile: SourceFile, name: string, @@ -758,7 +753,7 @@ function createDefinitionInfoFromStatement( name, containerKind: undefined!, containerName: "", - contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.expression.getEnd()), + contextSpan: createTextSpanFromNode(statement.expression, sourceFile), isLocal: true, isAmbient: false, unverified: false, diff --git a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc index 7458f3c2d3466..16cbbeeed8ba3 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase1.ts === -// <|[|switch|] (null|>) { +// [|{| contextId: 0 |}switch|] (<|null|>) { // /*GOTO DEF*/case null: break; // } diff --git a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc index 4478b78fcbda2..bb3486039cf7a 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase2.ts === -// <|[|switch|] (null|>) { +// [|{| contextId: 0 |}switch|] (<|null|>) { // /*GOTO DEF*/default: break; // } diff --git a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc index 3d02e9f362772..d193c375c6093 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === -// <|[|switch|] (null|>) { +// [|{| contextId: 0 |}switch|] (<|null|>) { // /*GOTO DEF*/default: { // switch (null) { // default: break; @@ -26,7 +26,7 @@ // === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === // switch (null) { // default: { -// <|[|switch|] (null|>) { +// [|{| contextId: 0 |}switch|] (<|null|>) { // /*GOTO DEF*/default: break; // } // }; diff --git a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc index f56a5925fffb9..63740074da94d 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc @@ -4,7 +4,7 @@ // case null: break; // } // -// <|[|switch|] (null|>) { +// [|{| contextId: 0 |}switch|] (<|null|>) { // /*GOTO DEF*/case null: break; // } From 77c28cb78b2a73537e153e7e0ebd52c8c002067f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 15 Dec 2023 15:13:03 -0800 Subject: [PATCH 6/9] Revert context span again, add close paren this time --- src/services/goToDefinition.ts | 2 +- .../reference/goToDefinitionSwitchCase1.baseline.jsonc | 2 +- .../reference/goToDefinitionSwitchCase2.baseline.jsonc | 2 +- .../reference/goToDefinitionSwitchCase3.baseline.jsonc | 4 ++-- .../reference/goToDefinitionSwitchCase4.baseline.jsonc | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 7e5cc4d235b32..4e0b7cc429702 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -753,7 +753,7 @@ function createDefinitionInfoFromStatement( name, containerKind: undefined!, containerName: "", - contextSpan: createTextSpanFromNode(statement.expression, sourceFile), + contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.expression.getEnd() + 1), isLocal: true, isAmbient: false, unverified: false, diff --git a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc index 16cbbeeed8ba3..8c10bb97e263b 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase1.ts === -// [|{| contextId: 0 |}switch|] (<|null|>) { +// <|[|switch|] (null)|> { // /*GOTO DEF*/case null: break; // } diff --git a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc index bb3486039cf7a..318e346d9398f 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase2.ts === -// [|{| contextId: 0 |}switch|] (<|null|>) { +// <|[|switch|] (null)|> { // /*GOTO DEF*/default: break; // } diff --git a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc index d193c375c6093..022a654b71cdd 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === -// [|{| contextId: 0 |}switch|] (<|null|>) { +// <|[|switch|] (null)|> { // /*GOTO DEF*/default: { // switch (null) { // default: break; @@ -26,7 +26,7 @@ // === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === // switch (null) { // default: { -// [|{| contextId: 0 |}switch|] (<|null|>) { +// <|[|switch|] (null)|> { // /*GOTO DEF*/default: break; // } // }; diff --git a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc index 63740074da94d..12b7b46563064 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc @@ -4,7 +4,7 @@ // case null: break; // } // -// [|{| contextId: 0 |}switch|] (<|null|>) { +// <|[|switch|] (null)|> { // /*GOTO DEF*/case null: break; // } From e11f00e93d5cb9963d4e11b700524bdf7f42a73d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 15 Dec 2023 15:28:16 -0800 Subject: [PATCH 7/9] Better way of including close paren --- src/services/goToDefinition.ts | 2 +- .../reference/goToDefinitionSwitchCase1.baseline.jsonc | 2 +- tests/cases/fourslash/goToDefinitionSwitchCase1.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 4e0b7cc429702..221ad337b537d 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -753,7 +753,7 @@ function createDefinitionInfoFromStatement( name, containerKind: undefined!, containerName: "", - contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.expression.getEnd() + 1), + contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.caseBlock.getFullStart()), isLocal: true, isAmbient: false, unverified: false, diff --git a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc index 8c10bb97e263b..c92107111f2a0 100644 --- a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc @@ -1,6 +1,6 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionSwitchCase1.ts === -// <|[|switch|] (null)|> { +// <|[|switch|] (null )|> { // /*GOTO DEF*/case null: break; // } diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts index d2be83a7713ee..86a695f1ecf3b 100644 --- a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts +++ b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts @@ -1,6 +1,6 @@ /// -////switch (null) { +////switch (null ) { //// [|/*start*/case|] null: break; ////} From 279ce44c8c225c2aed9606a234e18d9a963bc3c2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:51:50 -0800 Subject: [PATCH 8/9] Move context span calculation to central location --- src/services/findAllReferences.ts | 14 +++++++++++--- src/services/goToDefinition.ts | 28 ++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 06aea522ce9be..826dfe9eb591b 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -234,6 +234,7 @@ import { StringLiteralLike, stripQuotes, SuperContainer, + SwitchStatement, Symbol, SymbolDisplay, SymbolDisplayPart, @@ -406,7 +407,7 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { } /** @internal */ -export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined): ContextNode | undefined { +export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | SwitchStatement | undefined): ContextNode | undefined { if (!node) return undefined; switch (node.kind) { case SyntaxKind.VariableDeclaration: @@ -451,14 +452,18 @@ export function getContextNode(node: NamedDeclaration | BinaryExpression | ForIn findAncestor(node.parent, node => isBinaryExpression(node) || isForInOrOfStatement(node)) as BinaryExpression | ForInOrOfStatement, ) : node; - + case SyntaxKind.SwitchStatement: + return { + start: find(node.getChildren(node.getSourceFile()), node => node.kind === SyntaxKind.SwitchKeyword)!, + end: (node as SwitchStatement).caseBlock, + }; default: return node; } } /** @internal */ -export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context?: ContextNode): { contextSpan: TextSpan; } | undefined { +export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context: ContextNode | undefined): { contextSpan: TextSpan; } | undefined { if (!context) return undefined; const contextSpan = isContextWithStartAndEndNode(context) ? getTextSpan(context.start, sourceFile, context.end) : @@ -874,6 +879,9 @@ function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSp start += 1; end -= 1; } + if (endNode?.kind === SyntaxKind.CaseBlock) { + end = endNode.getFullStart(); + } return createTextSpanFromBounds(start, end); } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 221ad337b537d..be36679b33690 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -74,7 +74,6 @@ import { isTypeAliasDeclaration, isTypeReferenceNode, isVariableDeclaration, - KeywordSyntaxKind, last, map, mapDefined, @@ -109,6 +108,9 @@ import { TypeReference, unescapeLeadingUnderscores, } from "./_namespaces/ts"; +import { + isContextWithStartAndEndNode, +} from "./_namespaces/ts.FindAllReferences"; /** @internal */ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { @@ -154,14 +156,7 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile case SyntaxKind.CaseKeyword: const switchStatement = findAncestor(node.parent, isSwitchStatement); if (switchStatement) { - return [ - createDefinitionInfoFromStatement( - switchStatement, - SyntaxKind.SwitchKeyword, - sourceFile, - "switch", - ), - ]; + return [createDefinitionInfoFromStatement(switchStatement, sourceFile, "switch")]; } break; } @@ -739,24 +734,21 @@ function isConstructorLike(node: Node): boolean { } } -function createDefinitionInfoFromStatement( - statement: SwitchStatement, - keywordKind: KeywordSyntaxKind, - sourceFile: SourceFile, - name: string, -): DefinitionInfo { - const keyword = find(statement.getChildren(sourceFile), node => node.kind === keywordKind)!; +function createDefinitionInfoFromStatement(statement: SwitchStatement, sourceFile: SourceFile, name: string): DefinitionInfo { + const keyword = FindAllReferences.getContextNode(statement)!; + const textSpan = createTextSpanFromNode(isContextWithStartAndEndNode(keyword) ? keyword.start : keyword, sourceFile) return { fileName: sourceFile.fileName, - textSpan: createTextSpanFromNode(keyword, sourceFile), + textSpan, kind: ScriptElementKind.keyword, name, containerKind: undefined!, containerName: "", - contextSpan: createTextSpanFromBounds(keyword.getStart(sourceFile), statement.caseBlock.getFullStart()), + ...FindAllReferences.toContextSpan(textSpan, sourceFile, keyword), isLocal: true, isAmbient: false, unverified: false, failedAliasResolution: undefined, }; } + From dd9d9f1e27be369062faa2723afcfc4a357ad65d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:01:42 -0800 Subject: [PATCH 9/9] move createDefinitionInfoFromStatement closer to others rename back to switch -- there's no point in unused abstraction. --- src/services/goToDefinition.ts | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index be36679b33690..79afa66a4d3a6 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -156,7 +156,7 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile case SyntaxKind.CaseKeyword: const switchStatement = findAncestor(node.parent, isSwitchStatement); if (switchStatement) { - return [createDefinitionInfoFromStatement(switchStatement, sourceFile, "switch")]; + return [createDefinitionInfoFromSwitch(switchStatement, sourceFile)]; } break; } @@ -657,6 +657,24 @@ function createDefinitionInfoFromName(checker: TypeChecker, declaration: Declara }; } +function createDefinitionInfoFromSwitch(statement: SwitchStatement, sourceFile: SourceFile): DefinitionInfo { + const keyword = FindAllReferences.getContextNode(statement)!; + const textSpan = createTextSpanFromNode(isContextWithStartAndEndNode(keyword) ? keyword.start : keyword, sourceFile); + return { + fileName: sourceFile.fileName, + textSpan, + kind: ScriptElementKind.keyword, + name: "switch", + containerKind: undefined!, + containerName: "", + ...FindAllReferences.toContextSpan(textSpan, sourceFile, keyword), + isLocal: true, + isAmbient: false, + unverified: false, + failedAliasResolution: undefined, + }; +} + function isDefinitionVisible(checker: TypeChecker, declaration: Declaration): boolean { if (checker.isDeclarationVisible(declaration)) return true; if (!declaration.parent) return false; @@ -733,22 +751,3 @@ function isConstructorLike(node: Node): boolean { return false; } } - -function createDefinitionInfoFromStatement(statement: SwitchStatement, sourceFile: SourceFile, name: string): DefinitionInfo { - const keyword = FindAllReferences.getContextNode(statement)!; - const textSpan = createTextSpanFromNode(isContextWithStartAndEndNode(keyword) ? keyword.start : keyword, sourceFile) - return { - fileName: sourceFile.fileName, - textSpan, - kind: ScriptElementKind.keyword, - name, - containerKind: undefined!, - containerName: "", - ...FindAllReferences.toContextSpan(textSpan, sourceFile, keyword), - isLocal: true, - isAmbient: false, - unverified: false, - failedAliasResolution: undefined, - }; -} -