Skip to content

Commit 1cec34b

Browse files
committed
Proposal for call hierarchy
add new `textDocument/calls` request. LSP issue: language-server-protocol#468 Signed-off-by: Alex Tugarev <alex.tugarev@typefox.io>
1 parent d168533 commit 1cec34b

File tree

5 files changed

+302
-0
lines changed

5 files changed

+302
-0
lines changed

client/src/calls.proposed.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* --------------------------------------------------------------------------------------------
2+
* Copyright (c) TypeFox. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
* ------------------------------------------------------------------------------------------ */
5+
'use strict';
6+
7+
import { Disposable } from 'vscode';
8+
import {
9+
TextDocumentRegistrationOptions, ClientCapabilities, ServerCapabilities, DocumentSelector, Proposed
10+
} from 'vscode-languageserver-protocol';
11+
12+
import * as UUID from './utils/uuid';
13+
import * as Is from './utils/is';
14+
import { TextDocumentFeature, BaseLanguageClient } from './client';
15+
16+
export class CallsFeature extends TextDocumentFeature<TextDocumentRegistrationOptions> {
17+
18+
constructor(client: BaseLanguageClient) {
19+
super(client, Proposed.CallsRequest.type);
20+
}
21+
22+
fillClientCapabilities(capabilities: ClientCapabilities): void {
23+
if (!!capabilities.textDocument) {
24+
capabilities.textDocument = {};
25+
}
26+
let callsClientCapabilities = capabilities as Proposed.CallsClientCapabilities;
27+
callsClientCapabilities.textDocument!.calls = {
28+
dynamicRegistration: true
29+
};
30+
}
31+
32+
initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void {
33+
let callsServerCapabilities = capabilities as Proposed.CallsServerCapabilities;
34+
if (!callsServerCapabilities.callsProvider) {
35+
return;
36+
}
37+
if (callsServerCapabilities.callsProvider === true) {
38+
if (!documentSelector) {
39+
return;
40+
}
41+
this.register(this.messages, {
42+
id: UUID.generateUuid(),
43+
registerOptions: Object.assign({}, { documentSelector: documentSelector })
44+
});
45+
} else {
46+
const implCapabilities = callsServerCapabilities.callsProvider;
47+
const id = Is.string(implCapabilities.id) && implCapabilities.id.length > 0 ? implCapabilities.id : UUID.generateUuid();
48+
const selector = implCapabilities.documentSelector || documentSelector;
49+
if (selector) {
50+
this.register(this.messages, {
51+
id,
52+
registerOptions: Object.assign({}, { documentSelector: selector })
53+
});
54+
}
55+
}
56+
}
57+
58+
protected registerLanguageProvider(_options: TextDocumentRegistrationOptions): Disposable {
59+
return new Disposable(() => { });
60+
}
61+
62+
}

client/src/main.ts

+5
Original file line numberDiff line numberDiff line change
@@ -504,9 +504,14 @@ export class SettingMonitor {
504504

505505
// Exporting proposed protocol.
506506

507+
import * as calls from './calls.proposed';
508+
507509
export namespace ProposedFeatures {
510+
export const CallsFeature = calls.CallsFeature;
511+
508512
export function createAll(_client: BaseLanguageClient): (StaticFeature | DynamicFeature<any>)[] {
509513
let result: (StaticFeature | DynamicFeature<any>)[] = [];
514+
result.push(new CallsFeature(_client));
510515
return result;
511516
}
512517
}

protocol/src/main.ts

+14
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,21 @@ export * from './protocol';
3535

3636
export { FoldingRangeParams as FoldingRangeRequestParam } from './protocol'; // for backward compatibility
3737

38+
import * as calls from './protocol.calls.proposed';
39+
3840
export namespace Proposed {
41+
export type CallsClientCapabilities = calls.CallsClientCapabilities;
42+
export type CallsServerCapabilities = calls.CallsServerCapabilities;
43+
44+
export namespace CallsRequest {
45+
export const type = calls.CallsRequest.type;
46+
export type HandlerSignature = calls.CallsRequest.HandlerSignature;
47+
}
48+
49+
export type CallsParams = calls.CallsParams;
50+
export type CallDirection = calls.CallDirection;
51+
export type CallsResult = calls.CallsResult;
52+
export type Call = calls.Call;
3953
}
4054

4155
export interface ProtocolConnection {
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
2+
#### Calls
3+
4+
The LSP provides retrieving the call hierachy information with the following request.
5+
6+
_Client Capabilities_:
7+
8+
```ts
9+
CallsClientCapabilities {
10+
/**
11+
* The text document client capabilities
12+
*/
13+
textDocument?: {
14+
/**
15+
* Capabilities specific to the `textDocument/calls`
16+
*/
17+
calls?: {
18+
/**
19+
* Whether implementation supports dynamic registration. If this is set to `true`
20+
* the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
21+
* return value for the corresponding server capability as well.
22+
*/
23+
dynamicRegistration?: boolean;
24+
};
25+
}
26+
```
27+
28+
_Server Capabilities_:
29+
30+
```ts
31+
CallsServerCapabilities {
32+
/**
33+
* The server provides Call Hierarchy support.
34+
*/
35+
callsProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
36+
}
37+
```
38+
39+
##### Calls Request
40+
41+
_Request_:
42+
43+
The `textDocument/calls` request is sent from the client to the server to resolve the callers or callees of a symbol at a given text document position. Returns the callers or callees corresponding to the requested direction.
44+
45+
* method: ‘textDocument/calls’
46+
* params: `CallsParams` defined as follows:
47+
48+
```ts
49+
export interface CallsParams extends TextDocumentPositionParams {
50+
/**
51+
* Outgoing direction for callees.
52+
* The default is incoming for callers.
53+
*/
54+
direction?: CallDirection;
55+
}
56+
57+
export enum CallDirection {
58+
/**
59+
* Incoming calls aka. callers
60+
*/
61+
Incoming = "incoming",
62+
/**
63+
* Outgoing calls aka. callees
64+
*/
65+
Outgoing = "outgoing",
66+
}
67+
```
68+
69+
_Response_:
70+
71+
The server will send a `CallsResult` object containing a `symbol` of a definition which it finds for given text document position. The symbol will be undefined, if no such definition is found.
72+
73+
The result object contains a list of `Call`s which include more information about the call site. It also contains a symbol location of the caller or collee which can be used by clients to make a request for the next level of the call hierarchy.
74+
75+
* result: `CallsResult` defined as follows:
76+
77+
```ts
78+
export interface CallsResult {
79+
/**
80+
* The symbol of a definition for which the request was made.
81+
*
82+
* If no definition is found at a given text document position, the symbol is undefined.
83+
*/
84+
symbol?: DocumentSymbol;
85+
/**
86+
* List of calls.
87+
*/
88+
calls: Call[];
89+
}
90+
91+
export interface Call {
92+
/**
93+
* Direction of the call.
94+
*/
95+
direction: CallDirection;
96+
/**
97+
* Actual location of a call to a definition.
98+
*/
99+
callLocation: Location;
100+
/**
101+
* Symbol refered to by this call. For outgoing calls this is a callee,
102+
* otherwise a caller.
103+
*/
104+
symbol: DocumentSymbol;
105+
/**
106+
* Location of the symbol, which can be used for a follow-up request to obtain the next level of calls.
107+
*/
108+
symbolLocation: Location;
109+
}
110+
```
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* --------------------------------------------------------------------------------------------
2+
* Copyright (c) TypeFox and others. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
* ------------------------------------------------------------------------------------------ */
5+
'use strict';
6+
7+
import { RequestType, RequestHandler } from 'vscode-jsonrpc';
8+
import { DocumentSymbol, Location } from 'vscode-languageserver-types';
9+
import { TextDocumentRegistrationOptions, StaticRegistrationOptions, TextDocumentPositionParams } from './protocol';
10+
11+
export interface CallsClientCapabilities {
12+
/**
13+
* The text document client capabilities
14+
*/
15+
textDocument?: {
16+
/**
17+
* Capabilities specific to the `textDocument/calls`
18+
*/
19+
calls?: {
20+
/**
21+
* Whether implementation supports dynamic registration. If this is set to `true`
22+
* the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
23+
* return value for the corresponding server capability as well.
24+
*/
25+
dynamicRegistration?: boolean;
26+
};
27+
}
28+
}
29+
30+
export interface CallsServerCapabilities {
31+
/**
32+
* The server provides Call Hierarchy support.
33+
*/
34+
callsProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
35+
}
36+
37+
/**
38+
* A request to resolve all calls at a given text document position of a symbol definition or a call the same.
39+
* The request's parameter is of type [CallsParams](#CallsParams), the response is of type [CallsResult](#CallsResult) or a
40+
* Thenable that resolves to such.
41+
*
42+
*
43+
*/
44+
export namespace CallsRequest {
45+
export const type = new RequestType<CallsParams, CallsResult, void, TextDocumentRegistrationOptions>('textDocument/calls');
46+
export type HandlerSignature = RequestHandler<CallsParams, CallsResult | null, void>;
47+
}
48+
49+
/**
50+
* The parameters of a `textDocument/calls` request.
51+
*/
52+
export interface CallsParams extends TextDocumentPositionParams {
53+
/**
54+
* Outgoing direction for callees.
55+
* The default is incoming for callers.
56+
*/
57+
direction?: CallDirection;
58+
}
59+
60+
/**
61+
* Enum of call direction kinds
62+
*/
63+
export enum CallDirection {
64+
/**
65+
* Incoming calls aka. callers
66+
*/
67+
Incoming = "incoming",
68+
/**
69+
* Outgoing calls aka. callees
70+
*/
71+
Outgoing = "outgoing",
72+
}
73+
74+
/**
75+
* The result of a `textDocument/calls` request.
76+
*/
77+
export interface CallsResult {
78+
/**
79+
* The symbol of a definition for which the request was made.
80+
*
81+
* If no definition is found at a given text document position, the symbol is undefined.
82+
*/
83+
symbol?: DocumentSymbol;
84+
/**
85+
* List of calls.
86+
*/
87+
calls: Call[];
88+
}
89+
90+
/**
91+
* Represents a directed call.
92+
*/
93+
export interface Call {
94+
/**
95+
* Direction of the call.
96+
*/
97+
direction: CallDirection;
98+
/**
99+
* Actual location of a call to a definition.
100+
*/
101+
callLocation: Location;
102+
/**
103+
* Symbol refered to by this call. For outgoing calls this is a callee,
104+
* otherwise a caller.
105+
*/
106+
symbol: DocumentSymbol;
107+
/**
108+
* Location of the symbol, which can be used for a follow-up request to obtain the next level of calls.
109+
*/
110+
symbolLocation: Location;
111+
}

0 commit comments

Comments
 (0)