Skip to content

Commit 852e7a0

Browse files
authored
Add containerName to CallHierarchyItem (#38997)
* Add containerName to CallHierarchyItem * Update public APIs * Update test to demonstrate nested namespace working
1 parent 0d6ae00 commit 852e7a0

10 files changed

+244
-3
lines changed

src/compiler/utilitiesPublic.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,8 @@ namespace ts {
589589
(isFunctionExpression(declaration) || isClassExpression(declaration) ? getAssignedName(declaration) : undefined);
590590
}
591591

592-
function getAssignedName(node: Node): DeclarationName | undefined {
592+
/*@internal*/
593+
export function getAssignedName(node: Node): DeclarationName | undefined {
593594
if (!node.parent) {
594595
return undefined;
595596
}

src/harness/fourslashImpl.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,6 +3440,9 @@ namespace FourSlash {
34403440
let text = "";
34413441
text += `${prefix}╭ name: ${callHierarchyItem.name}\n`;
34423442
text += `${prefix}├ kind: ${callHierarchyItem.kind}\n`;
3443+
if (callHierarchyItem.containerName) {
3444+
text += `${prefix}├ containerName: ${callHierarchyItem.containerName}\n`;
3445+
}
34433446
text += `${prefix}├ file: ${callHierarchyItem.file}\n`;
34443447
text += `${prefix}├ span:\n`;
34453448
text += this.formatCallHierarchyItemSpan(file, callHierarchyItem.span, `${prefix}│ `);

src/server/protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,6 +3069,7 @@ namespace ts.server.protocol {
30693069
file: string;
30703070
span: TextSpan;
30713071
selectionSpan: TextSpan;
3072+
containerName?: string;
30723073
}
30733074

30743075
export interface CallHierarchyIncomingCall {

src/services/callHierarchy.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,31 @@ namespace ts.CallHierarchy {
129129
return { text, pos: declName.getStart(), end: declName.getEnd() };
130130
}
131131

132+
function getCallHierarchItemContainerName(node: CallHierarchyDeclaration): string | undefined {
133+
if (isConstNamedExpression(node)) {
134+
if (isModuleBlock(node.parent.parent.parent.parent) && isIdentifier(node.parent.parent.parent.parent.parent.name)) {
135+
return node.parent.parent.parent.parent.parent.name.getText();
136+
}
137+
return;
138+
}
139+
140+
switch (node.kind) {
141+
case SyntaxKind.GetAccessor:
142+
case SyntaxKind.SetAccessor:
143+
case SyntaxKind.MethodDeclaration:
144+
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
145+
return getAssignedName(node.parent)?.getText();
146+
}
147+
return getNameOfDeclaration(node.parent)?.getText();
148+
case SyntaxKind.FunctionDeclaration:
149+
case SyntaxKind.ClassDeclaration:
150+
case SyntaxKind.ModuleDeclaration:
151+
if (isModuleBlock(node.parent) && isIdentifier(node.parent.parent.name)) {
152+
return node.parent.parent.name.getText();
153+
}
154+
}
155+
}
156+
132157
/** Finds the implementation of a function-like declaration, if one exists. */
133158
function findImplementation(typeChecker: TypeChecker, node: Extract<CallHierarchyDeclaration, FunctionLikeDeclaration>): Extract<CallHierarchyDeclaration, FunctionLikeDeclaration> | undefined;
134159
function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclaration): FunctionLikeDeclaration | undefined;
@@ -245,10 +270,11 @@ namespace ts.CallHierarchy {
245270
export function createCallHierarchyItem(program: Program, node: CallHierarchyDeclaration): CallHierarchyItem {
246271
const sourceFile = node.getSourceFile();
247272
const name = getCallHierarchyItemName(program, node);
273+
const containerName = getCallHierarchItemContainerName(node);
248274
const kind = getNodeKind(node);
249275
const span = createTextSpanFromBounds(skipTrivia(sourceFile.text, node.getFullStart(), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), node.getEnd());
250276
const selectionSpan = createTextSpanFromBounds(name.pos, name.end);
251-
return { file: sourceFile.fileName, kind, name: name.text, span, selectionSpan };
277+
return { file: sourceFile.fileName, kind, name: name.text, containerName, span, selectionSpan };
252278
}
253279

254280
function isDefined<T>(x: T): x is NonNullable<T> {
@@ -484,4 +510,4 @@ namespace ts.CallHierarchy {
484510
}
485511
return group(collectCallSites(program, declaration), getCallSiteGroupKey, entries => convertCallSiteGroupToOutgoingCall(program, entries));
486512
}
487-
}
513+
}

src/services/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ namespace ts {
615615
file: string;
616616
span: TextSpan;
617617
selectionSpan: TextSpan;
618+
containerName?: string;
618619
}
619620

620621
export interface CallHierarchyIncomingCall {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,6 +5431,7 @@ declare namespace ts {
54315431
file: string;
54325432
span: TextSpan;
54335433
selectionSpan: TextSpan;
5434+
containerName?: string;
54345435
}
54355436
interface CallHierarchyIncomingCall {
54365437
from: CallHierarchyItem;
@@ -8590,6 +8591,7 @@ declare namespace ts.server.protocol {
85908591
file: string;
85918592
span: TextSpan;
85928593
selectionSpan: TextSpan;
8594+
containerName?: string;
85938595
}
85948596
interface CallHierarchyIncomingCall {
85958597
from: CallHierarchyItem;

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,6 +5431,7 @@ declare namespace ts {
54315431
file: string;
54325432
span: TextSpan;
54335433
selectionSpan: TextSpan;
5434+
containerName?: string;
54345435
}
54355436
interface CallHierarchyIncomingCall {
54365437
from: CallHierarchyItem;

tests/baselines/reference/callHierarchyAccessor.callHierarchy.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
╭ name: bar
22
├ kind: getter
3+
├ containerName: C
34
├ file: /tests/cases/fourslash/callHierarchyAccessor.ts
45
├ span:
56
│ ╭ /tests/cases/fourslash/callHierarchyAccessor.ts:6:5-8:6
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
╭ name: f
2+
├ kind: function
3+
├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
4+
├ span:
5+
│ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:1:1-1:16
6+
│ │ 1: function f() {}
7+
│ │ ^^^^^^^^^^^^^^^
8+
│ ╰
9+
├ selectionSpan:
10+
│ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:1:10-1:11
11+
│ │ 1: function f() {}
12+
│ │ ^
13+
│ ╰
14+
├ incoming:
15+
│ ╭ from:
16+
│ │ ╭ name: sameName
17+
│ │ ├ kind: method
18+
│ │ ├ containerName: A
19+
│ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
20+
│ │ ├ span:
21+
│ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:4:3-6:4
22+
│ │ │ │ 4: static sameName() {
23+
│ │ │ │ ^^^^^^^^^^^^^^^^^^^
24+
│ │ │ │ 5: f();
25+
│ │ │ │ ^^^^^^^^
26+
│ │ │ │ 6: }
27+
│ │ │ │ ^^^
28+
│ │ │ ╰
29+
│ │ ├ selectionSpan:
30+
│ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:4:10-4:18
31+
│ │ │ │ 4: static sameName() {
32+
│ │ │ │ ^^^^^^^^
33+
│ │ │ ╰
34+
│ │ ├ incoming:
35+
│ │ │ ╭ from:
36+
│ │ │ │ ╭ name: sameName
37+
│ │ │ │ ├ kind: method
38+
│ │ │ │ ├ containerName: B
39+
│ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
40+
│ │ │ │ ├ span:
41+
│ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:10:3-12:4
42+
│ │ │ │ │ │ 10: sameName() {
43+
│ │ │ │ │ │ ^^^^^^^^^^^^
44+
│ │ │ │ │ │ 11: A.sameName();
45+
│ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
46+
│ │ │ │ │ │ 12: }
47+
│ │ │ │ │ │ ^^^
48+
│ │ │ │ │ ╰
49+
│ │ │ │ ├ selectionSpan:
50+
│ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:10:3-10:11
51+
│ │ │ │ │ │ 10: sameName() {
52+
│ │ │ │ │ │ ^^^^^^^^
53+
│ │ │ │ │ ╰
54+
│ │ │ │ ├ incoming:
55+
│ │ │ │ │ ╭ from:
56+
│ │ │ │ │ │ ╭ name: sameName
57+
│ │ │ │ │ │ ├ kind: getter
58+
│ │ │ │ │ │ ├ containerName: Obj
59+
│ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
60+
│ │ │ │ │ │ ├ span:
61+
│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:16:3-18:4
62+
│ │ │ │ │ │ │ │ 16: get sameName() {
63+
│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^
64+
│ │ │ │ │ │ │ │ 17: return new B().sameName;
65+
│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66+
│ │ │ │ │ │ │ │ 18: }
67+
│ │ │ │ │ │ │ │ ^^^
68+
│ │ │ │ │ │ │ ╰
69+
│ │ │ │ │ │ ├ selectionSpan:
70+
│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:16:7-16:15
71+
│ │ │ │ │ │ │ │ 16: get sameName() {
72+
│ │ │ │ │ │ │ │ ^^^^^^^^
73+
│ │ │ │ │ │ │ ╰
74+
│ │ │ │ │ │ ├ incoming:
75+
│ │ │ │ │ │ │ ╭ from:
76+
│ │ │ │ │ │ │ │ ╭ name: sameName
77+
│ │ │ │ │ │ │ │ ├ kind: function
78+
│ │ │ │ │ │ │ │ ├ containerName: Foo
79+
│ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
80+
│ │ │ │ │ │ │ │ ├ span:
81+
│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:22:3-24:4
82+
│ │ │ │ │ │ │ │ │ │ 22: function sameName() {
83+
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^
84+
│ │ │ │ │ │ │ │ │ │ 23: return Obj.sameName;
85+
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^
86+
│ │ │ │ │ │ │ │ │ │ 24: }
87+
│ │ │ │ │ │ │ │ │ │ ^^^
88+
│ │ │ │ │ │ │ │ │ ╰
89+
│ │ │ │ │ │ │ │ ├ selectionSpan:
90+
│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:22:12-22:20
91+
│ │ │ │ │ │ │ │ │ │ 22: function sameName() {
92+
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^
93+
│ │ │ │ │ │ │ │ │ ╰
94+
│ │ │ │ │ │ │ │ ├ incoming:
95+
│ │ │ │ │ │ │ │ │ ╭ from:
96+
│ │ │ │ │ │ │ │ │ │ ╭ name: C
97+
│ │ │ │ │ │ │ │ │ │ ├ kind: class
98+
│ │ │ │ │ │ │ │ │ │ ├ containerName: Foo
99+
│ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
100+
│ │ │ │ │ │ │ │ │ │ ├ span:
101+
│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:26:3-30:4
102+
│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C {
103+
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^
104+
│ │ │ │ │ │ │ │ │ │ │ │ 27: constructor() {
105+
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^
106+
│ │ │ │ │ │ │ │ │ │ │ │ 28: sameName();
107+
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
108+
│ │ │ │ │ │ │ │ │ │ │ │ 29: }
109+
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^
110+
│ │ │ │ │ │ │ │ │ │ │ │ 30: }
111+
│ │ │ │ │ │ │ │ │ │ │ │ ^^^
112+
│ │ │ │ │ │ │ │ │ │ │ ╰
113+
│ │ │ │ │ │ │ │ │ │ ├ selectionSpan:
114+
│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:26:16-26:17
115+
│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C {
116+
│ │ │ │ │ │ │ │ │ │ │ │ ^
117+
│ │ │ │ │ │ │ │ │ │ │ ╰
118+
│ │ │ │ │ │ │ │ │ │ ├ incoming:
119+
│ │ │ │ │ │ │ │ │ │ │ ╭ from:
120+
│ │ │ │ │ │ │ │ │ │ │ │ ╭ name: sameName
121+
│ │ │ │ │ │ │ │ │ │ │ │ ├ kind: function
122+
│ │ │ │ │ │ │ │ │ │ │ │ ├ containerName: Bar
123+
│ │ │ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
124+
│ │ │ │ │ │ │ │ │ │ │ │ ├ span:
125+
│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:20-34:37
126+
│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
127+
│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
128+
│ │ │ │ │ │ │ │ │ │ │ │ │ ╰
129+
│ │ │ │ │ │ │ │ │ │ │ │ ├ selectionSpan:
130+
│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:9-34:17
131+
│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
132+
│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^
133+
│ │ │ │ │ │ │ │ │ │ │ │ │ ╰
134+
│ │ │ │ │ │ │ │ │ │ │ │ ╰ incoming: none
135+
│ │ │ │ │ │ │ │ │ │ │ ├ fromSpans:
136+
│ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:34-34:35
137+
│ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
138+
│ │ │ │ │ │ │ │ │ │ │ │ │ ^
139+
│ │ │ │ │ │ │ │ │ │ ╰ ╰ ╰
140+
│ │ │ │ │ │ │ │ │ ├ fromSpans:
141+
│ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:28:7-28:15
142+
│ │ │ │ │ │ │ │ │ │ │ 28: sameName();
143+
│ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^
144+
│ │ │ │ │ │ │ │ ╰ ╰ ╰
145+
│ │ │ │ │ │ │ ├ fromSpans:
146+
│ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:23:16-23:24
147+
│ │ │ │ │ │ │ │ │ 23: return Obj.sameName;
148+
│ │ │ │ │ │ │ │ │ ^^^^^^^^
149+
│ │ │ │ │ │ ╰ ╰ ╰
150+
│ │ │ │ │ ├ fromSpans:
151+
│ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:17:20-17:28
152+
│ │ │ │ │ │ │ 17: return new B().sameName;
153+
│ │ │ │ │ │ │ ^^^^^^^^
154+
│ │ │ │ ╰ ╰ ╰
155+
│ │ │ ├ fromSpans:
156+
│ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:11:7-11:15
157+
│ │ │ │ │ 11: A.sameName();
158+
│ │ │ │ │ ^^^^^^^^
159+
│ │ ╰ ╰ ╰
160+
│ ├ fromSpans:
161+
│ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:5:5-5:6
162+
│ │ │ 5: f();
163+
│ │ │ ^
164+
│ ╰ ╰
165+
╰ outgoing: none
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////function /**/f() {}
4+
////
5+
////class A {
6+
//// static sameName() {
7+
//// f();
8+
//// }
9+
////}
10+
////
11+
////class B {
12+
//// sameName() {
13+
//// A.sameName();
14+
//// }
15+
////}
16+
////
17+
////const Obj = {
18+
//// get sameName() {
19+
//// return new B().sameName;
20+
//// }
21+
////};
22+
////
23+
////namespace Foo {
24+
//// function sameName() {
25+
//// return Obj.sameName;
26+
//// }
27+
////
28+
//// export class C {
29+
//// constructor() {
30+
//// sameName();
31+
//// }
32+
//// }
33+
////}
34+
////
35+
////module Foo.Bar {
36+
//// const sameName = () => new Foo.C();
37+
////}
38+
39+
goTo.marker();
40+
verify.baselineCallHierarchy();

0 commit comments

Comments
 (0)