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

add type hierarchy provider #128667

Merged
merged 6 commits into from
Jul 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2914,4 +2914,95 @@ declare module 'vscode' {
export type DetailedCoverage = StatementCoverage | FunctionCoverage;

//#endregion


//#region https://github.com/microsoft/vscode/issues/15533 --- Type hierarchy --- @eskibear
export class TypeHierarchyItem {
/**
* The name of this item.
*/
name: string;
/**
* The kind of this item.
*/
kind: SymbolKind;
/**
* Tags for this item.
*/
tags?: ReadonlyArray<SymbolTag>;
/**
* More detail for this item, e.g. the signature of a function.
*/
detail?: string;
/**
* The resource identifier of this item.
*/
uri: Uri;
/**
* The range enclosing this symbol not including leading/trailing whitespace
* but everything else, e.g. comments and code.
*/
range: Range;
/**
* The range that should be selected and revealed when this symbol is being
* picked, e.g. the name of a function. Must be contained by the
* [`range`](#TypeHierarchyItem.range).
*/
selectionRange: Range;

constructor(kind: SymbolKind, name: string, detail: string, uri: Uri, range: Range, selectionRange: Range);
}

export interface TypeHierarchyProvider {

/**
* Bootstraps type hierarchy by returning the item that is denoted by the given document
* and position. This item will be used as entry into the type graph. Providers should
* return `undefined` or `null` when there is no item at the given location.
*
* @param document The document in which the command was invoked.
* @param position The position at which the command was invoked.
* @param token A cancellation token.
* @returns A type hierarchy item or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
prepareTypeHierarchy(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<TypeHierarchyItem[]>;

/**
* Provide all supertypes for an item, e.g all types from which a type is derived/inherited. In graph terms this describes directed
* and annotated edges inside the type graph, e.g the given item is the starting node and the result is the nodes
* that can be reached.
*
* @param item The hierarchy item for which super types should be computed.
* @param token A cancellation token.
* @returns A set of supertypes or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideTypeHierarchySupertypes(item: TypeHierarchyItem, token: CancellationToken): ProviderResult<TypeHierarchyItem[]>;

/**
* Provide all subtypes for an item, e.g all types which are derived/inherited from the given item. In
* graph terms this describes directed and annotated edges inside the type graph, e.g the given item is the starting
* node and the result is the nodes that can be reached.
*
* @param item The hierarchy item for which subtypes should be computed.
* @param token A cancellation token.
* @returns A set of subtypes or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideTypeHierarchySubtypes(item: TypeHierarchyItem, token: CancellationToken): ProviderResult<TypeHierarchyItem[]>;
}

export namespace languages {
/**
* Register a type hierarchy provider.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider A type hierarchy provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerTypeHierarchyProvider(selector: DocumentSelector, provider: TypeHierarchyProvider): Disposable;
}
//#endregion

}
47 changes: 46 additions & 1 deletion 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, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion } from '../common/extHost.protocol';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion, ITypeHierarchyItemDto } 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 All @@ -20,6 +20,7 @@ import { URI } from 'vs/base/common/uri';
import { Selection } from 'vs/editor/common/core/selection';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { mixin } from 'vs/base/common/objects';
import { decodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';

Expand Down Expand Up @@ -147,6 +148,13 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return data as callh.CallHierarchyItem;
}

private static _reviveTypeHierarchyItemDto(data: ITypeHierarchyItemDto | undefined): typeh.TypeHierarchyItem {
if (data) {
data.uri = URI.revive(data.uri);
}
return data as typeh.TypeHierarchyItem;
}

//#endregion

// --- outline
Expand Down Expand Up @@ -773,6 +781,43 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
}

// --- type hierarchy

$registerTypeHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void {
this._registrations.set(handle, typeh.TypeHierarchyProviderRegistry.register(selector, {

prepareTypeHierarchy: async (document, position, token) => {
const items = await this._proxy.$prepareTypeHierarchy(handle, document.uri, position, token);
if (!items) {
return undefined;
}
return {
dispose: () => {
for (const item of items) {
this._proxy.$releaseTypeHierarchy(handle, item._sessionId);
}
},
roots: items.map(MainThreadLanguageFeatures._reviveTypeHierarchyItemDto)
};
},

provideSupertypes: async (item, token) => {
const supertypes = await this._proxy.$provideTypeHierarchySupertypes(handle, item._sessionId, item._itemId, token);
if (!supertypes) {
return supertypes;
}
return supertypes.map(MainThreadLanguageFeatures._reviveTypeHierarchyItemDto);
},
provideSubtypes: async (item, token) => {
const subtypes = await this._proxy.$provideTypeHierarchySubtypes(handle, item._sessionId, item._itemId, token);
if (!subtypes) {
return subtypes;
}
return subtypes.map(MainThreadLanguageFeatures._reviveTypeHierarchyItemDto);
}
}));
}

}

export class MainThreadDocumentSemanticTokensProvider implements modes.DocumentSemanticTokensProvider {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerInlayHintsProvider(selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {
checkProposedApiEnabled(extension);
return extHostLanguageFeatures.registerInlayHintsProvider(extension, selector, provider);
},
registerTypeHierarchyProvider(selector: vscode.DocumentSelector, provider: vscode.TypeHierarchyProvider): vscode.Disposable {
checkProposedApiEnabled(extension);
return extHostLanguageFeatures.registerTypeHierarchyProvider(extension, selector, provider);
Eskibear marked this conversation as resolved.
Show resolved Hide resolved
}
};

Expand Down Expand Up @@ -1232,6 +1236,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
ThemeIcon: extHostTypes.ThemeIcon,
TreeItem: extHostTypes.TreeItem,
TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
TypeHierarchyItem: extHostTypes.TypeHierarchyItem,
UIKind: UIKind,
Uri: URI,
ViewColumn: extHostTypes.ViewColumn,
Expand Down
8 changes: 8 additions & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/que
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForControllerRequest, RunTestsRequest, ITestIdWithSrc, TestsDiff, IFileCoverage, CoverageDetails } from 'vs/workbench/contrib/testing/common/testCollection';
import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { ActivationKind, ExtensionHostKind, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions';
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
Expand Down Expand Up @@ -413,6 +414,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$emitFoldingRangeEvent(eventHandle: number, event?: any): void;
$registerSelectionRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerCallHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerTypeHierarchyProvider(handle: number, selector: IDocumentFilterDto[]): void;
$setLanguageConfiguration(handle: number, languageId: string, configuration: ILanguageConfigurationDto): void;
}

Expand Down Expand Up @@ -1627,6 +1629,8 @@ export interface IInlineValueContextDto {
stoppedLocation: IRange;
}

export type ITypeHierarchyItemDto = Dto<TypeHierarchyItem>;

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 @@ -1677,6 +1681,10 @@ export interface ExtHostLanguageFeaturesShape {
$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<IOutgoingCallDto[] | undefined>;
$releaseCallHierarchy(handle: number, sessionId: string): void;
$setWordDefinitions(wordDefinitions: ILanguageWordDefinitionDto[]): void;
$prepareTypeHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
$releaseTypeHierarchy(handle: number, sessionId: string): void;
}

export interface ExtHostQuickOpenShape {
Expand Down
18 changes: 17 additions & 1 deletion src/vs/workbench/api/common/extHostApiCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri';
import type * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import * as types from 'vs/workbench/api/common/extHostTypes';
import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallDto, IOutgoingCallDto } from 'vs/workbench/api/common/extHost.protocol';
import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallDto, IOutgoingCallDto, ITypeHierarchyItemDto } from 'vs/workbench/api/common/extHost.protocol';
import * as modes from 'vs/editor/common/modes';
import * as search from 'vs/workbench/contrib/search/common/search';
import { ApiCommand, ApiCommandArgument, ApiCommandResult, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
Expand Down Expand Up @@ -406,6 +406,22 @@ const newCommands: ApiCommand[] = [
],
ApiCommandResult.Void
),
// --- type hierarchy
new ApiCommand(
'vscode.prepareTypeHierarchy', '_executePrepareTypeHierarchy', 'Prepare type hierarchy at a position inside a document',
Eskibear marked this conversation as resolved.
Show resolved Hide resolved
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
),
new ApiCommand(
'vscode.provideSupertypes', '_executeProvideSupertypes', 'Compute supertypes for an item',
[ApiCommandArgument.TypeHierarchyItem],
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
),
new ApiCommand(
'vscode.provideSubtypes', '_executeProvideSubtypes', 'Compute subtypes for an item',
[ApiCommandArgument.TypeHierarchyItem],
new ApiCommandResult<ITypeHierarchyItemDto[], types.TypeHierarchyItem[]>('A TypeHierarchyItem or undefined', v => v.map(typeConverters.TypeHierarchyItem.to))
),
];

//#endregion
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHostCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ export class ApiCommandArgument<V, O = V> {
static readonly String = new ApiCommandArgument<string>('string', '', v => typeof v === 'string', v => v);

static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof extHostTypes.CallHierarchyItem, extHostTypeConverter.CallHierarchyItem.to);
static readonly TypeHierarchyItem = new ApiCommandArgument('item', 'A type hierarchy item', v => v instanceof extHostTypes.TypeHierarchyItem, extHostTypeConverter.TypeHierarchyItem.to);

constructor(
readonly name: string,
Expand Down
Loading