Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

call hierarchy api #80112

Closed
wants to merge 12 commits into from
75 changes: 53 additions & 22 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,29 @@ declare module 'vscode' {

//#region Joh - call hierarchy

/**
* The call hierarchy direction represents to mode in which call hierarchy works.
*/
export enum CallHierarchyDirection {

/**
* Denotes outgoing calls *from* a symbol, e.g all functions called by a function.
*/
CallsFrom = 1,

/**
* Denotes incoming calls *to* a symbol, e.g. all functions calling a function.
*/
CallsTo = 2,
}

/**
* Represents programming constructs like function, methods etc. that appear in call hierarchies. Call hierarchy
* symbols are edges inside a call hierarchy graph and are connected by [`call hierarchy items`](#CallHierarchyItem).
*/
export class CallHierarchyItem {
kind: SymbolKind;
tags?: ReadonlyArray<SymbolTag>;
name: string;
detail?: string;
uri: Uri;
Expand All @@ -34,36 +50,51 @@ declare module 'vscode' {
constructor(kind: SymbolKind, name: string, detail: string, uri: Uri, range: Range, selectionRange: Range);
}

export interface CallHierarchyItemProvider {
/**
* Represents a directed edge inside a call graph. The `source` is a symbol making a call
* at `sourceRange` (`sourceRange` is contained inside the full range of source) to the
* `target` symbol.
*/
export class CallHierarchyCall {
source: CallHierarchyItem;
souceRange: Range;
target: CallHierarchyItem;

/**
* Given a document and position compute a call hierarchy item. This is justed as
* anchor for call hierarchy and then `resolveCallHierarchyItem` is being called.
*/
provideCallHierarchyItem(
document: TextDocument,
position: Position,
token: CancellationToken
): ProviderResult<CallHierarchyItem>;
constructor(source: CallHierarchyItem, sourceRange: Range, target: CallHierarchyItem);
}

/**
* The call hierarchy provider interface defines the contract between extensions and the
* 'call hierarchy'-feature.
*/
export interface CallHierarchyItemProvider {

/**
* Resolve a call hierarchy item, e.g. compute all calls from or to a function.
* The result is an array of item/location-tuples. The location in the returned tuples
* is always relative to the "caller" with the caller either being the provided item or
* the returned item.
* Provide a set of call hierarchy items for the given position and document.
*
* @param item A call hierarchy item previously returned from `provideCallHierarchyItem` or `resolveCallHierarchyItem`
* @param direction Resolve calls from a function or calls to a function
* @param token A cancellation token
* @param document The document in which the command was invoked.
* @param position The position at which the command was invoked.
* @param direction The call hierarchy direction, e.g if outgoing calls from a symbol or incoming call to a symbol are requested.
* @param token A cancellation token.
* @return An array of call hierarchy items or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined`, `null`, or an empty array.
*/
resolveCallHierarchyItem(
item: CallHierarchyItem,
direction: CallHierarchyDirection,
token: CancellationToken
): ProviderResult<[CallHierarchyItem, Location[]][]>;
provideCallHierarchyItems(document: TextDocument, position: Position, direction: CallHierarchyDirection, token: CancellationToken): ProviderResult<CallHierarchyCall[]>;
}

export namespace languages {

/**
* Register a call hierarchy provider.
*
* Multiple providers can be registered for a language. In that case providers are sorted
* by their [score](#languages.match) and the best-matching provider is used. Failure
* of the selected provider will cause a failure of the whole operation.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider A call hierarchy provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerCallHierarchyProvider(selector: DocumentSelector, provider: CallHierarchyItemProvider): Disposable;
}

Expand Down
38 changes: 17 additions & 21 deletions src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Position as EditorPosition } from 'vs/editor/common/core/position';
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyDto, ISuggestDataDto, ICodeActionDto } from '../common/extHost.protocol';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ISuggestDataDto, ICodeActionDto, ICallHierarchyGraphDto } from '../common/extHost.protocol';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { IModeService } from 'vs/editor/common/services/modeService';
Expand Down Expand Up @@ -111,11 +111,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return <modes.ILink>data;
}

private static _reviveCallHierarchyItemDto(data: ICallHierarchyDto | undefined): callh.CallHierarchyItem {
if (data) {
data.uri = URI.revive(data.uri);
private static _reviveCallHierarchyItemDto(data: ICallHierarchyGraphDto | undefined): callh.CallHierarchyCall[] {
if (!data) {
return [];
}
return data as callh.CallHierarchyItem;

// Revive all uris, inplace without create new objects
data.nodes.forEach(value => value.uri = URI.revive(value.uri));

return data.edges.map(edge => {
return {
source: <callh.CallHierarchySymbol>data.nodes[edge.source],
sourceRange: edge.sourceRange,
target: <callh.CallHierarchySymbol>data.nodes[edge.target],
};
});
}

//#endregion
Expand Down Expand Up @@ -494,22 +504,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha

$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void {
this._registrations.set(handle, callh.CallHierarchyProviderRegistry.register(selector, {
provideCallHierarchyItem: (document, position, token) => {
return this._proxy.$provideCallHierarchyItem(handle, document.uri, position, token).then(MainThreadLanguageFeatures._reviveCallHierarchyItemDto);
},
resolveCallHierarchyItem: (item, direction, token) => {
return this._proxy.$resolveCallHierarchyItem(handle, item, direction, token).then(data => {
if (data) {
for (let i = 0; i < data.length; i++) {
const [item, locations] = data[i];
data[i] = [
MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item),
MainThreadLanguageFeatures._reviveLocationDto(locations)
];
}
}
return data as [callh.CallHierarchyItem, modes.Location[]][];
});
provideCallHierarchyItems: (model, position, direction, token) => {
return this._proxy.$provideCallHierarchyItems(handle, model.uri, position, direction, token).then(MainThreadLanguageFeatures._reviveCallHierarchyItemDto);
}
}));
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// proposed
CallHierarchyDirection: extHostTypes.CallHierarchyDirection,
CallHierarchyItem: extHostTypes.CallHierarchyItem,
CallHierarchyCall: extHostTypes.CallHierarchyCall,
Decoration: extHostTypes.Decoration
};
};
Expand Down
12 changes: 8 additions & 4 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,8 +1063,8 @@ export interface ICodeLensDto {
command?: ICommandDto;
}

export interface ICallHierarchyDto {
_id: number;
export interface ICallHierarchySymbolDto {
id: string;
kind: modes.SymbolKind;
name: string;
detail?: string;
Expand All @@ -1073,6 +1073,11 @@ export interface ICallHierarchyDto {
selectionRange: IRange;
}

export interface ICallHierarchyGraphDto {
nodes: ICallHierarchySymbolDto[];
edges: { source: number, sourceRange: IRange, target: number }[];
}

export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
Expand Down Expand Up @@ -1107,8 +1112,7 @@ export interface ExtHostLanguageFeaturesShape {
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[] | undefined>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[] | undefined>;
$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]>;
$provideCallHierarchyItem(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ICallHierarchyDto | undefined>;
$resolveCallHierarchyItem(handle: number, item: callHierarchy.CallHierarchyItem, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<[ICallHierarchyDto, modes.Location[]][]>;
$provideCallHierarchyItems(handle: number, resource: UriComponents, position: IPosition, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<ICallHierarchyGraphDto | undefined>;
}

export interface ExtHostQuickOpenShape {
Expand Down
Loading