提交 3c18886a 编写于 作者: B Benjamin Pasero

quick access - some cleanup in symbols support

上级 d9d90a0d
......@@ -18,7 +18,7 @@ import { trim, format } from 'vs/base/common/strings';
import { fuzzyScore, FuzzyScore, createMatches } from 'vs/base/common/filters';
import { assign } from 'vs/base/common/objects';
interface IGotoSymbolQuickPickItem extends IQuickPickItem {
export interface IGotoSymbolQuickPickItem extends IQuickPickItem {
kind: SymbolKind,
index: number,
score?: FuzzyScore;
......@@ -90,7 +90,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return disposables;
}
private async waitForLanguageSymbolRegistry(model: ITextModel, disposables: DisposableStore): Promise<boolean> {
protected async waitForLanguageSymbolRegistry(model: ITextModel, disposables: DisposableStore): Promise<boolean> {
if (DocumentSymbolProviderRegistry.has(model)) {
return true;
}
......@@ -194,7 +194,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return disposables;
}
private async doGetSymbolPicks(symbolsPromise: Promise<DocumentSymbol[]>, filter: string, token: CancellationToken): Promise<Array<IGotoSymbolQuickPickItem | IQuickPickSeparator>> {
protected async doGetSymbolPicks(symbolsPromise: Promise<DocumentSymbol[]>, filter: string, token: CancellationToken): Promise<Array<IGotoSymbolQuickPickItem | IQuickPickSeparator>> {
const symbols = await symbolsPromise;
if (token.isCancellationRequested) {
return [];
......@@ -367,7 +367,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return result;
}
private async getDocumentSymbols(document: ITextModel, flatten: boolean, token: CancellationToken): Promise<DocumentSymbol[]> {
protected async getDocumentSymbols(document: ITextModel, flatten: boolean, token: CancellationToken): Promise<DocumentSymbol[]> {
const model = await OutlineModel.create(document, token);
if (token.isCancellationRequested) {
return [];
......@@ -411,32 +411,6 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
}
}
}
//#region public methods to use this picker from other pickers
async getSymbolPicks(model: ITextModel, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IGotoSymbolQuickPickItem | IQuickPickSeparator>> {
// If the registry does not know the model, we wait for as long as
// the registry knows it. This helps in cases where a language
// registry was not activated yet for providing any symbols.
const result = await this.waitForLanguageSymbolRegistry(model, disposables);
if (!result || token.isCancellationRequested) {
return [];
}
return this.doGetSymbolPicks(this.getDocumentSymbols(model, true, token), filter, token);
}
addDecorations(editor: IEditor, range: IRange): void {
super.addDecorations(editor, range);
}
clearDecorations(editor: IEditor): void {
super.clearDecorations(editor);
}
//#endregion
}
// #region NLS Helpers
......
......@@ -4,15 +4,19 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { IKeyMods } from 'vs/platform/quickinput/common/quickInput';
import { IKeyMods, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IEditor } from 'vs/editor/common/editorCommon';
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IRange } from 'vs/editor/common/core/range';
import { Registry } from 'vs/platform/registry/common/platform';
import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess';
import { AbstractGotoSymbolQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoSymbolQuickAccess';
import { AbstractGotoSymbolQuickAccessProvider, IGotoSymbolQuickPickItem } from 'vs/editor/contrib/quickAccess/gotoSymbolQuickAccess';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';
import { ITextModel } from 'vs/editor/common/model';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider {
......@@ -56,6 +60,39 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
super.gotoLocation(editor, options);
}
}
//#region public methods to use this picker from other pickers
private static readonly SYMBOL_PICKS_TIMEOUT = 8000;
async getSymbolPicks(model: ITextModel, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IGotoSymbolQuickPickItem | IQuickPickSeparator>> {
// If the registry does not know the model, we wait for as long as
// the registry knows it. This helps in cases where a language
// registry was not activated yet for providing any symbols.
// To not wait forever, we eventually timeout though.
const result = await Promise.race([
this.waitForLanguageSymbolRegistry(model, disposables),
timeout(GotoSymbolQuickAccessProvider.SYMBOL_PICKS_TIMEOUT)
]);
if (!result || token.isCancellationRequested) {
return [];
}
return this.doGetSymbolPicks(this.getDocumentSymbols(model, true, token), filter, token);
}
addDecorations(editor: IEditor, range: IRange): void {
super.addDecorations(editor, range);
}
clearDecorations(editor: IEditor): void {
super.clearDecorations(editor);
}
//#endregion
}
Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({
......
......@@ -171,7 +171,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
// Add new decoration if editor symbol is active
const [item] = picker.activeItems;
if (isEditorSymbolQuickPickItem(item)) {
editorDecorationsDisposable.value = this.decorateActiveEditorWithEditorSymbolRange(item);
editorDecorationsDisposable.value = this.decorateAndRevealSymbolRange(item);
}
}));
......@@ -181,7 +181,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return disposables;
}
private decorateActiveEditorWithEditorSymbolRange(pick: IEditorSymbolAnythingQuickPickItem): IDisposable {
private decorateAndRevealSymbolRange(pick: IEditorSymbolAnythingQuickPickItem): IDisposable {
const activeEditor = this.editorService.activeEditor;
if (!isEqual(pick.resource, activeEditor?.resource)) {
return Disposable.None; // active editor needs to be for resource
......@@ -236,6 +236,10 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
this.pickState.lastActiveGlobalPick = activePick;
}
return this.doGetPicks(filter, disposables, token);
}
private doGetPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | FastAndSlowPicksType<IAnythingQuickPickItem> | null {
const query = prepareQuery(filter);
// Return early if we have editor symbol picks. We support this by:
......@@ -610,27 +614,35 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> {
// Obtain model from resource
let model = this.modelService.getModel(activeGlobalResource);
if (!model) {
const modelReference = disposables.add(await this.textModelService.createModelReference(activeGlobalResource));
if (token.isCancellationRequested) {
return [];
}
model = modelReference.object.textEditorModel;
}
// Bring the editor to front to review symbols to go to
await this.editorService.openEditor({
resource: activeGlobalResource,
options: { preserveFocus: true, revealIfOpened: true }
});
try {
await this.editorService.openEditor({
resource: activeGlobalResource,
options: { preserveFocus: true, revealIfOpened: true, ignoreError: true }
});
} catch (error) {
return []; // return if resource cannot be opened
}
if (token.isCancellationRequested) {
return [];
}
// Obtain model from resource
let model = this.modelService.getModel(activeGlobalResource);
if (!model) {
try {
const modelReference = disposables.add(await this.textModelService.createModelReference(activeGlobalResource));
if (token.isCancellationRequested) {
return [];
}
model = modelReference.object.textEditorModel;
} catch (error) {
return []; // return if model cannot be resolved
}
}
// Ask provider for editor symbols
const editorSymbolPicks = (await this.editorSymbolsQuickAccess.getSymbolPicks(model, filter, disposables, token));
if (token.isCancellationRequested) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册