Skip to content

Commit 6c413e0

Browse files
authored
Add support for Call Hierarchies in language server (#35176)
* Add support for Call Hierarchies in language server * Use baselines for callHierarchy tests * Clean up commented code * Support multiple hierarchy items when an implementation can't be found * Use optional chaining in a few places * Use getFileAndProject
1 parent 114dad7 commit 6c413e0

File tree

55 files changed

+2712
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2712
-55
lines changed

src/compiler/core.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,18 @@ namespace ts {
630630
return [...array1, ...array2];
631631
}
632632

633+
function selectIndex(_: unknown, i: number) {
634+
return i;
635+
}
636+
637+
export function indicesOf(array: readonly unknown[]): number[] {
638+
return array.map(selectIndex);
639+
}
640+
633641
function deduplicateRelational<T>(array: readonly T[], equalityComparer: EqualityComparer<T>, comparer: Comparer<T>) {
634642
// Perform a stable sort of the array. This ensures the first entry in a list of
635643
// duplicates remains the first entry in the result.
636-
const indices = array.map((_, i) => i);
644+
const indices = indicesOf(array);
637645
stableSortIndices(array, indices, comparer);
638646

639647
let last = array[indices[0]];
@@ -939,7 +947,7 @@ namespace ts {
939947
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
940948
*/
941949
export function stableSort<T>(array: readonly T[], comparer: Comparer<T>): SortedReadonlyArray<T> {
942-
const indices = array.map((_, i) => i);
950+
const indices = indicesOf(array);
943951
stableSortIndices(array, indices, comparer);
944952
return indices.map(i => array[i]) as SortedArray<T> as SortedReadonlyArray<T>;
945953
}
@@ -1245,8 +1253,10 @@ namespace ts {
12451253
return result;
12461254
}
12471255

1248-
export function group<T>(values: readonly T[], getGroupId: (value: T) => string): readonly (readonly T[])[] {
1249-
return arrayFrom(arrayToMultiMap(values, getGroupId).values());
1256+
export function group<T>(values: readonly T[], getGroupId: (value: T) => string): readonly (readonly T[])[];
1257+
export function group<T, R>(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[];
1258+
export function group<T>(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] {
1259+
return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector);
12501260
}
12511261

12521262
export function clone<T>(object: T): T {

src/harness/client.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,51 @@ namespace ts.server {
743743
return notImplemented();
744744
}
745745

746+
private convertCallHierarchyItem(item: protocol.CallHierarchyItem): CallHierarchyItem {
747+
return {
748+
file: item.file,
749+
name: item.name,
750+
kind: item.kind,
751+
span: this.decodeSpan(item.span, item.file),
752+
selectionSpan: this.decodeSpan(item.selectionSpan, item.file)
753+
};
754+
}
755+
756+
prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined {
757+
const args = this.createFileLocationRequestArgs(fileName, position);
758+
const request = this.processRequest<protocol.PrepareCallHierarchyRequest>(CommandNames.PrepareCallHierarchy, args);
759+
const response = this.processResponse<protocol.PrepareCallHierarchyResponse>(request);
760+
return response.body && mapOneOrMany(response.body, item => this.convertCallHierarchyItem(item));
761+
}
762+
763+
private convertCallHierarchyIncomingCall(item: protocol.CallHierarchyIncomingCall): CallHierarchyIncomingCall {
764+
return {
765+
from: this.convertCallHierarchyItem(item.from),
766+
fromSpans: item.fromSpans.map(span => this.decodeSpan(span, item.from.file))
767+
};
768+
}
769+
770+
provideCallHierarchyIncomingCalls(fileName: string, position: number) {
771+
const args = this.createFileLocationRequestArgs(fileName, position);
772+
const request = this.processRequest<protocol.ProvideCallHierarchyIncomingCallsRequest>(CommandNames.PrepareCallHierarchy, args);
773+
const response = this.processResponse<protocol.ProvideCallHierarchyIncomingCallsResponse>(request);
774+
return response.body.map(item => this.convertCallHierarchyIncomingCall(item));
775+
}
776+
777+
private convertCallHierarchyOutgoingCall(file: string, item: protocol.CallHierarchyOutgoingCall): CallHierarchyOutgoingCall {
778+
return {
779+
to: this.convertCallHierarchyItem(item.to),
780+
fromSpans: item.fromSpans.map(span => this.decodeSpan(span, file))
781+
};
782+
}
783+
784+
provideCallHierarchyOutgoingCalls(fileName: string, position: number) {
785+
const args = this.createFileLocationRequestArgs(fileName, position);
786+
const request = this.processRequest<protocol.ProvideCallHierarchyOutgoingCallsRequest>(CommandNames.PrepareCallHierarchy, args);
787+
const response = this.processResponse<protocol.ProvideCallHierarchyOutgoingCallsResponse>(request);
788+
return response.body.map(item => this.convertCallHierarchyOutgoingCall(fileName, item));
789+
}
790+
746791
getProgram(): Program {
747792
throw new Error("SourceFile objects are not serializable through the server protocol.");
748793
}

0 commit comments

Comments
 (0)