From d9558862cc9c98e10cded621caaefa81aaae87fc Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 19 Mar 2019 10:06:19 +0100 Subject: [PATCH] add uri-property to CallHierarchtItem, better wording, better behaviour when switching calls/callers --- src/vs/vscode.proposed.d.ts | 3 +- .../mainThreadLanguageFeatures.ts | 25 +++++++--- src/vs/workbench/api/node/extHost.protocol.ts | 14 +++++- .../api/node/extHostLanguageFeatures.ts | 1 + src/vs/workbench/api/node/extHostTypes.ts | 4 +- .../browser/callHierarchy.contribution.ts | 3 +- .../browser/callHierarchyPeek.ts | 47 ++++++++++++------- .../browser/callHierarchyTree.ts | 2 +- .../callHierarchy/common/callHierarchy.ts | 2 + 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b637c8147dc..2bf7daa2472 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -27,10 +27,11 @@ declare module 'vscode' { kind: SymbolKind; name: string; detail?: string; + uri: Uri; range: Range; selectionRange: Range; - constructor(kind: SymbolKind, name: string, detail: string, range: Range, selectionRange: Range); + constructor(kind: SymbolKind, name: string, detail: string, uri: Uri, range: Range, selectionRange: Range); } export interface CallHierarchyItemProvider { diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index c88aa4c2e46..e5d3ac02ff9 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -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 } from 'vs/editor/common/core/range'; -import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, DefinitionLinkDto, ISerializedSignatureHelpProviderMetadata, CodeInsetDto, LinkDto } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, DefinitionLinkDto, ISerializedSignatureHelpProviderMetadata, CodeInsetDto, LinkDto, CallHierarchyDto } from '../node/extHost.protocol'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { IHeapService } from './mainThreadHeapService'; @@ -22,7 +22,7 @@ import { URI } from 'vs/base/common/uri'; import { Selection } from 'vs/editor/common/core/selection'; import * as codeInset from 'vs/workbench/contrib/codeinset/common/codeInset'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { CallHierarchyProviderRegistry } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'; +import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'; @extHostNamedCustomer(MainContext.MainThreadLanguageFeatures) export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape { @@ -115,6 +115,13 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha return data; } + private static _reviveCallHierarchyItemDto(data: CallHierarchyDto | undefined): callh.CallHierarchyItem { + if (data) { + data.uri = URI.revive(data.uri); + } + return data as callh.CallHierarchyItem; + } + //#endregion // --- outline @@ -475,16 +482,22 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- call hierarchy $registerCallHierarchyProvider(handle: number, selector: ISerializedDocumentFilter[]): void { - this._registrations[handle] = CallHierarchyProviderRegistry.register(typeConverters.LanguageSelector.from(selector), { + this._registrations[handle] = callh.CallHierarchyProviderRegistry.register(typeConverters.LanguageSelector.from(selector), { provideCallHierarchyItem: (document, position, token) => { - return this._proxy.$provideCallHierarchyItem(handle, document.uri, 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) { - data.forEach(tuple => tuple[1] = tuple[1].map(l => MainThreadLanguageFeatures._reviveLocationDto(l))); + for (let i = 0; i < data.length; i++) { + const [item, locations] = data[i]; + data[i] = [ + MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item), + MainThreadLanguageFeatures._reviveLocationDto(locations) + ]; + } } - return data; + return data as [callh.CallHierarchyItem, modes.Location[]][]; }); } }); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 9abd44b1371..797326a8f7d 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -920,6 +920,16 @@ export interface CodeLensDto extends ObjectIdentifier { export type CodeInsetDto = ObjectIdentifier & codeInset.ICodeInsetSymbol; +export interface CallHierarchyDto { + _id: number; + kind: modes.SymbolKind; + name: string; + detail?: string; + uri: UriComponents; + range: IRange; + selectionRange: IRange; +} + export interface ExtHostLanguageFeaturesShape { $provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise; $provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise; @@ -952,8 +962,8 @@ export interface ExtHostLanguageFeaturesShape { $provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise; $provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise; $provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise; - $provideCallHierarchyItem(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; - $resolveCallHierarchyItem(handle: number, item: callHierarchy.CallHierarchyItem, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<[callHierarchy.CallHierarchyItem, modes.Location[]][]>; + $provideCallHierarchyItem(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; + $resolveCallHierarchyItem(handle: number, item: callHierarchy.CallHierarchyItem, direction: callHierarchy.CallHierarchyDirection, token: CancellationToken): Promise<[CallHierarchyDto, modes.Location[]][]>; } export interface ExtHostQuickOpenShape { diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 923d8403541..b509dba344b 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -1011,6 +1011,7 @@ class CallHierarchyAdapter { name: item.name, detail: item.detail, kind: typeConvert.SymbolKind.from(item.kind), + uri: item.uri, range: typeConvert.Range.from(item.range), selectionRange: typeConvert.Range.from(item.selectionRange), }; diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 9a694d6638c..3e9ef712e6c 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1120,13 +1120,15 @@ export class CallHierarchyItem { kind: SymbolKind; name: string; detail?: string; + uri: URI; range: Range; selectionRange: Range; - constructor(kind: SymbolKind, name: string, detail: string | undefined = undefined, range: Range, selectionRange: Range) { + constructor(kind: SymbolKind, name: string, detail: string, uri: URI, range: Range, selectionRange: Range) { this.kind = kind; this.name = name; this.detail = detail; + this.uri = uri; this.range = range; this.selectionRange = selectionRange; } diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts index ea9c981599e..e4cd34a95ae 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.ts @@ -72,7 +72,6 @@ class CallHierarchyController extends Disposable implements IEditorContribution const position = this._editor.getPosition(); const [provider] = CallHierarchyProviderRegistry.ordered(model); if (!provider) { - console.log('no provider'); return; } @@ -99,7 +98,7 @@ class CallHierarchyController extends Disposable implements IEditorContribution return; } if (!item) { - widget.showEmpty(); + widget.showMessage(localize('no.item', "No results")); return; } diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts index 191ba93f760..c4fd9b496f7 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.ts @@ -30,6 +30,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays'; import { IPosition } from 'vs/editor/common/core/position'; import { Action } from 'vs/base/common/actions'; import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import { ILabelService } from 'vs/platform/label/common/label'; registerThemingParticipant((theme, collector) => { const referenceHighlightColor = theme.getColor(peekViewEditorMatchHighlight); @@ -83,6 +84,7 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { private _direction: CallHierarchyDirection, @IEditorService private readonly _editorService: IEditorService, @ITextModelService private readonly _textModelService: ITextModelService, + @ILabelService private readonly _labelService: ILabelService, @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { super(editor, { showFrame: true, showArrow: true, isResizeable: true, isAccessible: true }); @@ -205,7 +207,7 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { fullRange = !fullRange ? range : Range.plusRange(range, fullRange); } - this._textModelService.createModelReference(element.locations[0].uri).then(value => { + this._textModelService.createModelReference(element.item.uri).then(value => { this._editor.setModel(value.object.textEditorModel); this._editor.revealRangeInCenter(fullRange!, ScrollType.Smooth); this._editor.revealLine(element.item.range.startLineNumber, ScrollType.Smooth); @@ -227,7 +229,7 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { } this.dispose(); this._editorService.openEditor({ - resource: focus.locations[0].uri, + resource: focus.item.uri, options: { selection: target.range! } }); @@ -237,7 +239,7 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { if (e.element && isNonEmptyArray(e.element.locations)) { this.dispose(); this._editorService.openEditor({ - resource: e.element.locations[0].uri, + resource: e.element.item.uri, options: { selection: e.element.locations[0].range } }); } @@ -249,7 +251,7 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { if (element && !(e.browserEvent instanceof MouseEvent)) { this.dispose(); this._editorService.openEditor({ - resource: element.locations[0].uri, + resource: element.item.uri, options: { selection: element.locations[0].range } }); } @@ -262,27 +264,38 @@ export class CallHierarchyTreePeekWidget extends PeekViewWidget { this._show(); } - showEmpty(): void { + showMessage(message: string): void { this._parent.dataset['state'] = State.Message; this.setTitle(''); - this._message.innerText = localize('empty', "No results"); + this.setMetaTitle(''); + this._message.innerText = message; this._show(); } showItem(item: CallHierarchyItem) { this._parent.dataset['state'] = State.Data; - this._editor.setModel(undefined); - this._tree.setInput(item).then(() => { - this._tree.domFocus(); - this._tree.focusFirst(); - this.setTitle( - localize('title', "Call Hierarchy"), - this._direction === CallHierarchyDirection.CallsFrom - ? localize('title.from', "calls from '{0}'", item.name) - : localize('title.to', "calls to '{0}'", item.name) - ); - }); + this._show(); + this._tree.setInput(item).then(() => { + + if (!this._tree.getFirstElementChild(item)) { + // + this.showMessage(this._direction === CallHierarchyDirection.CallsFrom + ? localize('empt.callsFrom', "No calls from '{0}'", item.name) + : localize('empt.callsTo', "No calls to '{0}'", item.name)); + + } else { + this._tree.domFocus(); + this._tree.focusFirst(); + this.setTitle( + item.name, + item.detail || this._labelService.getUriLabel(item.uri, { relative: true }), + ); + this.setMetaTitle(this._direction === CallHierarchyDirection.CallsFrom + ? localize('title.from', " – calls from '{0}'", item.name) + : localize('title.to', " – calls to '{0}'", item.name)); + } + }); if (!this._toggleDirection) { this._toggleDirection = new ToggleHierarchyDirectionAction( diff --git a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts index aab891624cb..1c7a043ab63 100644 --- a/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts +++ b/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.ts @@ -67,7 +67,7 @@ export class CallRenderer implements ITreeRenderer, _index: number, template: CallRenderingTemplate): void { const { element, filterData } = node; - const detail = element.item.detail || this._labelService.getUriLabel(element.locations[0].uri, { relative: true }); + const detail = element.item.detail || this._labelService.getUriLabel(element.item.uri, { relative: true }); template.iconLabel.setLabel( element.item.name, diff --git a/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts b/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts index cd7816bd146..95876374639 100644 --- a/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts +++ b/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts @@ -9,6 +9,7 @@ import { SymbolKind, ProviderResult, Location } from 'vs/editor/common/modes'; import { ITextModel } from 'vs/editor/common/model'; import { CancellationToken } from 'vs/base/common/cancellation'; import { LanguageFeatureRegistry } from 'vs/editor/common/modes/languageFeatureRegistry'; +import { URI } from 'vs/base/common/uri'; export const enum CallHierarchyDirection { CallsFrom = 1, @@ -20,6 +21,7 @@ export interface CallHierarchyItem { kind: SymbolKind; name: string; detail?: string; + uri: URI; range: IRange; selectionRange: IRange; }