Skip to content

Commit

Permalink
Add containerName to CallHierarchyItem (#38997)
Browse files Browse the repository at this point in the history
* Add containerName to CallHierarchyItem

* Update public APIs

* Update test to demonstrate nested namespace working
  • Loading branch information
andrewbranch authored Jun 10, 2020
1 parent 0d6ae00 commit 852e7a0
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@ namespace ts {
(isFunctionExpression(declaration) || isClassExpression(declaration) ? getAssignedName(declaration) : undefined);
}

function getAssignedName(node: Node): DeclarationName | undefined {
/*@internal*/
export function getAssignedName(node: Node): DeclarationName | undefined {
if (!node.parent) {
return undefined;
}
Expand Down
3 changes: 3 additions & 0 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3440,6 +3440,9 @@ namespace FourSlash {
let text = "";
text += `${prefix}╭ name: ${callHierarchyItem.name}\n`;
text += `${prefix}├ kind: ${callHierarchyItem.kind}\n`;
if (callHierarchyItem.containerName) {
text += `${prefix}├ containerName: ${callHierarchyItem.containerName}\n`;
}
text += `${prefix}├ file: ${callHierarchyItem.file}\n`;
text += `${prefix}├ span:\n`;
text += this.formatCallHierarchyItemSpan(file, callHierarchyItem.span, `${prefix}│ `);
Expand Down
1 change: 1 addition & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3069,6 +3069,7 @@ namespace ts.server.protocol {
file: string;
span: TextSpan;
selectionSpan: TextSpan;
containerName?: string;
}

export interface CallHierarchyIncomingCall {
Expand Down
30 changes: 28 additions & 2 deletions src/services/callHierarchy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,31 @@ namespace ts.CallHierarchy {
return { text, pos: declName.getStart(), end: declName.getEnd() };
}

function getCallHierarchItemContainerName(node: CallHierarchyDeclaration): string | undefined {
if (isConstNamedExpression(node)) {
if (isModuleBlock(node.parent.parent.parent.parent) && isIdentifier(node.parent.parent.parent.parent.parent.name)) {
return node.parent.parent.parent.parent.parent.name.getText();
}
return;
}

switch (node.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration:
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
return getAssignedName(node.parent)?.getText();
}
return getNameOfDeclaration(node.parent)?.getText();
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ModuleDeclaration:
if (isModuleBlock(node.parent) && isIdentifier(node.parent.parent.name)) {
return node.parent.parent.name.getText();
}
}
}

/** Finds the implementation of a function-like declaration, if one exists. */
function findImplementation(typeChecker: TypeChecker, node: Extract<CallHierarchyDeclaration, FunctionLikeDeclaration>): Extract<CallHierarchyDeclaration, FunctionLikeDeclaration> | undefined;
function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclaration): FunctionLikeDeclaration | undefined;
Expand Down Expand Up @@ -245,10 +270,11 @@ namespace ts.CallHierarchy {
export function createCallHierarchyItem(program: Program, node: CallHierarchyDeclaration): CallHierarchyItem {
const sourceFile = node.getSourceFile();
const name = getCallHierarchyItemName(program, node);
const containerName = getCallHierarchItemContainerName(node);
const kind = getNodeKind(node);
const span = createTextSpanFromBounds(skipTrivia(sourceFile.text, node.getFullStart(), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), node.getEnd());
const selectionSpan = createTextSpanFromBounds(name.pos, name.end);
return { file: sourceFile.fileName, kind, name: name.text, span, selectionSpan };
return { file: sourceFile.fileName, kind, name: name.text, containerName, span, selectionSpan };
}

function isDefined<T>(x: T): x is NonNullable<T> {
Expand Down Expand Up @@ -484,4 +510,4 @@ namespace ts.CallHierarchy {
}
return group(collectCallSites(program, declaration), getCallSiteGroupKey, entries => convertCallSiteGroupToOutgoingCall(program, entries));
}
}
}
1 change: 1 addition & 0 deletions src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ namespace ts {
file: string;
span: TextSpan;
selectionSpan: TextSpan;
containerName?: string;
}

export interface CallHierarchyIncomingCall {
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5431,6 +5431,7 @@ declare namespace ts {
file: string;
span: TextSpan;
selectionSpan: TextSpan;
containerName?: string;
}
interface CallHierarchyIncomingCall {
from: CallHierarchyItem;
Expand Down Expand Up @@ -8590,6 +8591,7 @@ declare namespace ts.server.protocol {
file: string;
span: TextSpan;
selectionSpan: TextSpan;
containerName?: string;
}
interface CallHierarchyIncomingCall {
from: CallHierarchyItem;
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5431,6 +5431,7 @@ declare namespace ts {
file: string;
span: TextSpan;
selectionSpan: TextSpan;
containerName?: string;
}
interface CallHierarchyIncomingCall {
from: CallHierarchyItem;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
╭ name: bar
├ kind: getter
├ containerName: C
├ file: /tests/cases/fourslash/callHierarchyAccessor.ts
├ span:
│ ╭ /tests/cases/fourslash/callHierarchyAccessor.ts:6:5-8:6
Expand Down
165 changes: 165 additions & 0 deletions tests/baselines/reference/callHierarchyContainerName.callHierarchy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
╭ name: f
├ kind: function
├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
├ span:
│ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:1:1-1:16
│ │ 1: function f() {}
│ │ ^^^^^^^^^^^^^^^
│ ╰
├ selectionSpan:
│ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:1:10-1:11
│ │ 1: function f() {}
│ │ ^
│ ╰
├ incoming:
│ ╭ from:
│ │ ╭ name: sameName
│ │ ├ kind: method
│ │ ├ containerName: A
│ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ ├ span:
│ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:4:3-6:4
│ │ │ │ 4: static sameName() {
│ │ │ │ ^^^^^^^^^^^^^^^^^^^
│ │ │ │ 5: f();
│ │ │ │ ^^^^^^^^
│ │ │ │ 6: }
│ │ │ │ ^^^
│ │ │ ╰
│ │ ├ selectionSpan:
│ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:4:10-4:18
│ │ │ │ 4: static sameName() {
│ │ │ │ ^^^^^^^^
│ │ │ ╰
│ │ ├ incoming:
│ │ │ ╭ from:
│ │ │ │ ╭ name: sameName
│ │ │ │ ├ kind: method
│ │ │ │ ├ containerName: B
│ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ │ │ ├ span:
│ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:10:3-12:4
│ │ │ │ │ │ 10: sameName() {
│ │ │ │ │ │ ^^^^^^^^^^^^
│ │ │ │ │ │ 11: A.sameName();
│ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ 12: }
│ │ │ │ │ │ ^^^
│ │ │ │ │ ╰
│ │ │ │ ├ selectionSpan:
│ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:10:3-10:11
│ │ │ │ │ │ 10: sameName() {
│ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ ╰
│ │ │ │ ├ incoming:
│ │ │ │ │ ╭ from:
│ │ │ │ │ │ ╭ name: sameName
│ │ │ │ │ │ ├ kind: getter
│ │ │ │ │ │ ├ containerName: Obj
│ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ │ │ │ │ ├ span:
│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:16:3-18:4
│ │ │ │ │ │ │ │ 16: get sameName() {
│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ 17: return new B().sameName;
│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ 18: }
│ │ │ │ │ │ │ │ ^^^
│ │ │ │ │ │ │ ╰
│ │ │ │ │ │ ├ selectionSpan:
│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:16:7-16:15
│ │ │ │ │ │ │ │ 16: get sameName() {
│ │ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ │ │ ╰
│ │ │ │ │ │ ├ incoming:
│ │ │ │ │ │ │ ╭ from:
│ │ │ │ │ │ │ │ ╭ name: sameName
│ │ │ │ │ │ │ │ ├ kind: function
│ │ │ │ │ │ │ │ ├ containerName: Foo
│ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ │ │ │ │ │ │ ├ span:
│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:22:3-24:4
│ │ │ │ │ │ │ │ │ │ 22: function sameName() {
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ 23: return Obj.sameName;
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ 24: }
│ │ │ │ │ │ │ │ │ │ ^^^
│ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ ├ selectionSpan:
│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:22:12-22:20
│ │ │ │ │ │ │ │ │ │ 22: function sameName() {
│ │ │ │ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ ├ incoming:
│ │ │ │ │ │ │ │ │ ╭ from:
│ │ │ │ │ │ │ │ │ │ ╭ name: C
│ │ │ │ │ │ │ │ │ │ ├ kind: class
│ │ │ │ │ │ │ │ │ │ ├ containerName: Foo
│ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ │ │ │ │ │ │ │ │ ├ span:
│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:26:3-30:4
│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C {
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ 27: constructor() {
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ 28: sameName();
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ 29: }
│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ 30: }
│ │ │ │ │ │ │ │ │ │ │ │ ^^^
│ │ │ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ │ │ ├ selectionSpan:
│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:26:16-26:17
│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C {
│ │ │ │ │ │ │ │ │ │ │ │ ^
│ │ │ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ │ │ ├ incoming:
│ │ │ │ │ │ │ │ │ │ │ ╭ from:
│ │ │ │ │ │ │ │ │ │ │ │ ╭ name: sameName
│ │ │ │ │ │ │ │ │ │ │ │ ├ kind: function
│ │ │ │ │ │ │ │ │ │ │ │ ├ containerName: Bar
│ │ │ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/callHierarchyContainerName.ts
│ │ │ │ │ │ │ │ │ │ │ │ ├ span:
│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:20-34:37
│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ │ │ │ │ ├ selectionSpan:
│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:9-34:17
│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ │ │ │ │ │ │ │ │ ╰
│ │ │ │ │ │ │ │ │ │ │ │ ╰ incoming: none
│ │ │ │ │ │ │ │ │ │ │ ├ fromSpans:
│ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:34:34-34:35
│ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C();
│ │ │ │ │ │ │ │ │ │ │ │ │ ^
│ │ │ │ │ │ │ │ │ │ ╰ ╰ ╰
│ │ │ │ │ │ │ │ │ ├ fromSpans:
│ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:28:7-28:15
│ │ │ │ │ │ │ │ │ │ │ 28: sameName();
│ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ │ │ │ ╰ ╰ ╰
│ │ │ │ │ │ │ ├ fromSpans:
│ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:23:16-23:24
│ │ │ │ │ │ │ │ │ 23: return Obj.sameName;
│ │ │ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ │ │ ╰ ╰ ╰
│ │ │ │ │ ├ fromSpans:
│ │ │ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:17:20-17:28
│ │ │ │ │ │ │ 17: return new B().sameName;
│ │ │ │ │ │ │ ^^^^^^^^
│ │ │ │ ╰ ╰ ╰
│ │ │ ├ fromSpans:
│ │ │ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:11:7-11:15
│ │ │ │ │ 11: A.sameName();
│ │ │ │ │ ^^^^^^^^
│ │ ╰ ╰ ╰
│ ├ fromSpans:
│ │ ╭ /tests/cases/fourslash/callHierarchyContainerName.ts:5:5-5:6
│ │ │ 5: f();
│ │ │ ^
│ ╰ ╰
╰ outgoing: none
40 changes: 40 additions & 0 deletions tests/cases/fourslash/callHierarchyContainerName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/// <reference path="fourslash.ts" />

////function /**/f() {}
////
////class A {
//// static sameName() {
//// f();
//// }
////}
////
////class B {
//// sameName() {
//// A.sameName();
//// }
////}
////
////const Obj = {
//// get sameName() {
//// return new B().sameName;
//// }
////};
////
////namespace Foo {
//// function sameName() {
//// return Obj.sameName;
//// }
////
//// export class C {
//// constructor() {
//// sameName();
//// }
//// }
////}
////
////module Foo.Bar {
//// const sameName = () => new Foo.C();
////}

goTo.marker();
verify.baselineCallHierarchy();

0 comments on commit 852e7a0

Please sign in to comment.