manually track workspace symbols for later resolving, #36941

This commit is contained in:
Johannes Rieken
2017-10-26 11:38:10 +02:00
parent bcebe2af23
commit 1df5c0240f
3 changed files with 67 additions and 29 deletions

View File

@@ -552,6 +552,21 @@ export interface IExtHostSuggestResult {
incomplete?: boolean;
}
export interface IdObject {
_id: number;
}
export namespace IdObject {
let n = 0;
export function mixin<T extends object>(object: T): T & IdObject {
(<any>object)._id = n++;
return <any>object;
}
}
export type IWorkspaceSymbol = IdObject & modes.SymbolInformation;
export interface IWorkspaceSymbols extends IdObject { symbols: IWorkspaceSymbol[]; };
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]>;
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]>;
@@ -566,8 +581,9 @@ export interface ExtHostLanguageFeaturesShape {
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]>;
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation>;
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols>;
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<IWorkspaceSymbol>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit>;
$provideCompletionItems(handle: number, resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult>;
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;

View File

@@ -16,9 +16,8 @@ import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion } from './extHost.protocol';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
@@ -368,45 +367,56 @@ class OnTypeFormattingAdapter {
}
}
class NavigateTypeAdapter {
class NavigateTypeAdapter implements IWorkspaceSymbolProvider {
private readonly _symbolCache: { [id: number]: vscode.SymbolInformation } = Object.create(null);
private readonly _resultCache: { [id: number]: [number, number] } = Object.create(null);
private readonly _provider: vscode.WorkspaceSymbolProvider;
private _provider: vscode.WorkspaceSymbolProvider;
private _heapService: ExtHostHeapService;
constructor(provider: vscode.WorkspaceSymbolProvider, heapService: ExtHostHeapService) {
constructor(provider: vscode.WorkspaceSymbolProvider) {
this._provider = provider;
this._heapService = heapService;
}
provideWorkspaceSymbols(search: string): TPromise<modes.SymbolInformation[]> {
provideWorkspaceSymbols(search: string): TPromise<IWorkspaceSymbols> {
const result: IWorkspaceSymbols = IdObject.mixin({ symbols: [] });
return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
if (Array.isArray(value)) {
return value.map(item => {
const id = this._heapService.keep(item);
const result = TypeConverters.fromSymbolInformation(item);
return ObjectIdentifier.mixin(result, id);
});
if (!isFalsyOrEmpty(value)) {
for (const item of value) {
const symbol = IdObject.mixin(TypeConverters.fromSymbolInformation(item));
this._symbolCache[symbol._id] = item;
result.symbols.push(symbol);
}
}
return undefined;
}).then(() => {
this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
return result;
});
}
resolveWorkspaceSymbol(item: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
resolveWorkspaceSymbol(symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
return TPromise.as(item);
return TPromise.as(symbol);
}
const symbolInfo = this._heapService.get<vscode.SymbolInformation>(ObjectIdentifier.of(item));
if (symbolInfo) {
return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(symbolInfo, token)).then(value => {
return value && TypeConverters.fromSymbolInformation(value);
const item = this._symbolCache[symbol._id];
if (item) {
return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
return value && mixin(symbol, TypeConverters.fromSymbolInformation(value), true);
});
}
return undefined;
}
releaseWorkspaceSymbols(id: number): any {
const range = this._resultCache[id];
if (range) {
for (let [from, to] = range; from <= to; from++) {
delete this._symbolCache[from];
}
delete this._resultCache[id];
}
}
}
class RenameAdapter {
@@ -946,19 +956,23 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new NavigateTypeAdapter(provider, this._heapService));
this._adapter.set(handle, new NavigateTypeAdapter(provider));
this._proxy.$registerNavigateTypeSupport(handle);
return this._createDisposable(handle);
}
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> {
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
}
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
}
$releaseWorkspaceSymbols(handle: number, id: number) {
this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id));
}
// --- rename
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {