diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 5f3eb986565..b2325c6f772 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -198,6 +198,7 @@ import { nodeSeenTracker, NumericLiteral, ObjectLiteralExpression, + or, ParameterDeclaration, ParenthesizedExpression, Path, @@ -2177,9 +2178,9 @@ export namespace Core { } // Check if the node is within an extends or implements clause - const containingClass = getContainingClassIfInHeritageClause(refNode); - if (containingClass) { - addReference(containingClass); + const containingNode = getContainingNodeIfInHeritageClause(refNode); + if (containingNode) { + addReference(containingNode); return; } @@ -2212,9 +2213,9 @@ export namespace Core { } } - function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined { - return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) - : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, isClassLike) : undefined; + function getContainingNodeIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined { + return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingNodeIfInHeritageClause(node.parent) + : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, or(isClassLike, isInterfaceDeclaration)) : undefined; } /** diff --git a/tests/baselines/reference/goToImplementationInterface_00.baseline.jsonc b/tests/baselines/reference/goToImplementationInterface_00.baseline.jsonc index 32215cfece3..5a57fa9d459 100644 --- a/tests/baselines/reference/goToImplementationInterface_00.baseline.jsonc +++ b/tests/baselines/reference/goToImplementationInterface_00.baseline.jsonc @@ -4,49 +4,44 @@ // hello: () => void // } // -// interface Baz extends Foo {} +// <|interface [|{| defId: 0 |}Baz|] extends Foo {}|> // -// var bar: Foo = [|{| defId: 0 |}{ hello: helloImpl /**0*/ }|]; -// var baz: Foo[] = [|{| defId: 1 |}[{ hello: helloImpl /**4*/ }]|]; +// var bar: Foo = [|{| defId: 1 |}{ hello: helloImpl /**0*/ }|]; +// var baz: Foo[] = [|{| defId: 2 |}[{ hello: helloImpl /**4*/ }]|]; // // function helloImpl () {} // -// function whatever(x: Foo = [|{| defId: 2 |}{ hello() {/**1*/} }|] ) { +// function whatever(x: Foo = [|{| defId: 3 |}{ hello() {/**1*/} }|] ) { // } // // class Bar { -// x: Foo = [|{| defId: 3 |}{ hello() {} }|] +// x: Foo = [|{| defId: 4 |}{ hello() {} }|] // -// constructor(public f: Foo = [|{| defId: 4 |}{ hello() {/**3*/} }|] ) {} +// constructor(public f: Foo = [|{| defId: 5 |}{ hello() {/**3*/} }|] ) {} // } // === Details === [ { "defId": 0, - "kind": "interface", "displayParts": [ { - "text": "(", - "kind": "punctuation" + "text": "interface", + "kind": "keyword" }, { - "text": "object literal", - "kind": "text" + "text": " ", + "kind": "space" }, { - "text": ")", - "kind": "punctuation" + "text": "Baz", + "kind": "interfaceName" } - ] + ], + "kind": "interface" }, { "defId": 1, - "kind": "", - "displayParts": [] - }, - { - "defId": 2, "kind": "interface", "displayParts": [ { @@ -63,6 +58,11 @@ } ] }, + { + "defId": 2, + "kind": "", + "displayParts": [] + }, { "defId": 3, "kind": "interface", @@ -98,5 +98,23 @@ "kind": "punctuation" } ] + }, + { + "defId": 5, + "kind": "interface", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "object literal", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + } + ] } ] \ No newline at end of file diff --git a/tests/baselines/reference/goToImplementationInterface_10.baseline.jsonc b/tests/baselines/reference/goToImplementationInterface_10.baseline.jsonc new file mode 100644 index 00000000000..1fffdcfa609 --- /dev/null +++ b/tests/baselines/reference/goToImplementationInterface_10.baseline.jsonc @@ -0,0 +1,71 @@ +// === goToImplementation === +// === /a.ts === +// interface /*GOTO IMPL*/A { +// foo: boolean; +// } +// <|interface [|{| defId: 0 |}B|] extends A { +// bar: boolean; +// }|> +// <|export class [|{| defId: 1 |}C|] implements B { +// foo = true; +// bar = true; +// }|> +// <|export class [|{| defId: 2 |}D|] extends C { }|> + + // === Details === + [ + { + "defId": 0, + "displayParts": [ + { + "text": "interface", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "B", + "kind": "interfaceName" + } + ], + "kind": "interface" + }, + { + "defId": 1, + "displayParts": [ + { + "text": "class", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "C", + "kind": "className" + } + ], + "kind": "class" + }, + { + "defId": 2, + "displayParts": [ + { + "text": "class", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "D", + "kind": "className" + } + ], + "kind": "class" + } + ] \ No newline at end of file diff --git a/tests/cases/fourslash/goToImplementationInterface_10.ts b/tests/cases/fourslash/goToImplementationInterface_10.ts new file mode 100644 index 00000000000..4db9f5ce276 --- /dev/null +++ b/tests/cases/fourslash/goToImplementationInterface_10.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /a.ts +////interface /*def*/A { +//// foo: boolean; +////} +////interface [|B|] extends A { +//// bar: boolean; +////} +////export class [|C|] implements B { +//// foo = true; +//// bar = true; +////} +////export class [|D|] extends C { } + +verify.baselineGoToImplementation("def");