diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 76d49745eff..e1e99e987df 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -643,44 +643,15 @@ export const symbolKindToCssClass = (function () { }; })(); -/** - * @internal - */ -export interface IOutline { - entries: SymbolInformation[]; -} -/** - * Represents information about programming constructs like variables, classes, - * interfaces etc. - */ -export interface SymbolInformation { - /** - * The name of this symbol. - */ +export interface DocumentSymbol { name: string; - /** - * The detail of this symbol. - */ - detail?: string; - /** - * The name of the symbol containing this symbol. - */ - containerName?: string; - /** - * The kind of this symbol. - */ kind: SymbolKind; - /** - * The location of this symbol. - */ - location: Location; - /** - * The defining range of this symbol. - */ - definingRange: IRange; - - children?: SymbolInformation[]; + containerName?: string; + fullRange: IRange; + identifierRange: IRange; + children?: DocumentSymbol[]; } + /** * The document symbol provider interface defines the contract between extensions and * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_goto-symbol)-feature. @@ -692,7 +663,7 @@ export interface DocumentSymbolProvider { /** * Provide symbol information for the given document. */ - provideDocumentSymbols(model: model.ITextModel, token: CancellationToken): SymbolInformation[] | Thenable; + provideDocumentSymbols(model: model.ITextModel, token: CancellationToken): DocumentSymbol[] | Thenable; } export interface TextEdit { diff --git a/src/vs/editor/contrib/quickOpen/quickOpen.ts b/src/vs/editor/contrib/quickOpen/quickOpen.ts index 05c2680d57c..c75aa9e8fc0 100644 --- a/src/vs/editor/contrib/quickOpen/quickOpen.ts +++ b/src/vs/editor/contrib/quickOpen/quickOpen.ts @@ -11,13 +11,13 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions'; -import { SymbolInformation, DocumentSymbolProviderRegistry, IOutline } from 'vs/editor/common/modes'; +import { DocumentSymbol, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; import { IModelService } from 'vs/editor/common/services/modelService'; import { asWinJsPromise } from 'vs/base/common/async'; -export function getDocumentSymbols(model: ITextModel): TPromise { +export function getDocumentSymbols(model: ITextModel): TPromise { - let roots: SymbolInformation[] = []; + let roots: DocumentSymbol[] = []; let promises = DocumentSymbolProviderRegistry.all(model).map(support => { @@ -31,29 +31,25 @@ export function getDocumentSymbols(model: ITextModel): TPromise { }); return TPromise.join(promises).then(() => { - let flatEntries: SymbolInformation[] = []; + let flatEntries: DocumentSymbol[] = []; flatten(flatEntries, roots, ''); flatEntries.sort(compareEntriesUsingStart); - - return { - entries: flatEntries, - }; + return flatEntries; }); } -function compareEntriesUsingStart(a: SymbolInformation, b: SymbolInformation): number { - return Range.compareRangesUsingStarts(a.location.range, b.location.range); +function compareEntriesUsingStart(a: DocumentSymbol, b: DocumentSymbol): number { + return Range.compareRangesUsingStarts(a.fullRange, b.fullRange); } -function flatten(bucket: SymbolInformation[], entries: SymbolInformation[], overrideContainerLabel: string): void { +function flatten(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideContainerLabel: string): void { for (let entry of entries) { bucket.push({ kind: entry.kind, name: entry.name, - detail: entry.detail, containerName: entry.containerName || overrideContainerLabel, - location: entry.location, - definingRange: entry.definingRange, + fullRange: entry.fullRange, + identifierRange: entry.identifierRange, children: undefined, // we flatten it... }); if (entry.children) { diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index a09d76a25d5..48383314a19 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -15,12 +15,12 @@ import { IContext, IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/ba import { IAutoFocus, Mode } from 'vs/base/parts/quickopen/common/quickOpen'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { SymbolInformation, DocumentSymbolProviderRegistry, symbolKindToCssClass, IOutline, Location } from 'vs/editor/common/modes'; +import { DocumentSymbol, DocumentSymbolProviderRegistry, symbolKindToCssClass } from 'vs/editor/common/modes'; import { BaseEditorQuickOpenAction, IDecorator } from './editorQuickOpen'; import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen'; import { registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { Range } from 'vs/editor/common/core/range'; +import { Range, IRange } from 'vs/editor/common/core/range'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; let SCOPE_PREFIX = ':'; @@ -138,16 +138,16 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { } // Resolve outline - return getDocumentSymbols(model).then((result: IOutline) => { - if (result.entries.length === 0) { + return getDocumentSymbols(model).then((result: DocumentSymbol[]) => { + if (result.length === 0) { return; } - this._run(editor, result.entries); + this._run(editor, result); }); } - private _run(editor: ICodeEditor, result: SymbolInformation[]): void { + private _run(editor: ICodeEditor, result: DocumentSymbol[]): void { this._show(this.getController(editor), { getModel: (value: string): QuickOpenModel => { return new QuickOpenModel(this.toQuickOpenEntries(editor, result, value)); @@ -167,11 +167,11 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { }); } - private symbolEntry(name: string, type: string, description: string, location: Location, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator): SymbolEntry { - return new SymbolEntry(name, type, description, Range.lift(location.range), highlights, editor, decorator); + private symbolEntry(name: string, type: string, description: string, range: IRange, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator): SymbolEntry { + return new SymbolEntry(name, type, description, Range.lift(range), highlights, editor, decorator); } - private toQuickOpenEntries(editor: ICodeEditor, flattened: SymbolInformation[], searchValue: string): SymbolEntry[] { + private toQuickOpenEntries(editor: ICodeEditor, flattened: DocumentSymbol[], searchValue: string): SymbolEntry[] { const controller = this.getController(editor); let results: SymbolEntry[] = []; @@ -197,7 +197,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { } // Add - results.push(this.symbolEntry(label, symbolKindToCssClass(element.kind), description, element.location, highlights, editor, controller)); + results.push(this.symbolEntry(label, symbolKindToCssClass(element.kind), description, element.fullRange, highlights, editor, controller)); } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index cf3df4c85bf..acd7200170a 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -4866,36 +4866,13 @@ declare namespace monaco.languages { TypeParameter = 25 } - /** - * Represents information about programming constructs like variables, classes, - * interfaces etc. - */ - export interface SymbolInformation { - /** - * The name of this symbol. - */ + export interface DocumentSymbol { name: string; - /** - * The detail of this symbol. - */ - detail?: string; - /** - * The name of the symbol containing this symbol. - */ - containerName?: string; - /** - * The kind of this symbol. - */ kind: SymbolKind; - /** - * The location of this symbol. - */ - location: Location; - /** - * The defining range of this symbol. - */ - definingRange: IRange; - children?: SymbolInformation[]; + containerName?: string; + fullRange: IRange; + identifierRange: IRange; + children?: DocumentSymbol[]; } /** @@ -4907,7 +4884,7 @@ declare namespace monaco.languages { /** * Provide symbol information for the given document. */ - provideDocumentSymbols(model: editor.ITextModel, token: CancellationToken): SymbolInformation[] | Thenable; + provideDocumentSymbols(model: editor.ITextModel, token: CancellationToken): DocumentSymbol[] | Thenable; } export interface TextEdit { diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index f627075683c..1125227d0b2 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -9,12 +9,12 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { ITextModel, ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; -import { WorkspaceSymbolProviderRegistry, IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search'; +import * as search from 'vs/workbench/parts/search/common/search'; import { wireCancellationToken } from 'vs/base/common/async'; 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, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter } 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'; @@ -72,20 +72,17 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } } - private static _reviveSymbolInformationDto(data: SymbolInformationDto): modes.SymbolInformation; - private static _reviveSymbolInformationDto(data: SymbolInformationDto[]): modes.SymbolInformation[]; - private static _reviveSymbolInformationDto(data: SymbolInformationDto | SymbolInformationDto[]): modes.SymbolInformation | modes.SymbolInformation[] { + private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto): search.IWorkspaceSymbol; + private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto[]): search.IWorkspaceSymbol[]; + private static _reviveWorkspaceSymbolDto(data: WorkspaceSymbolDto | WorkspaceSymbolDto[]): search.IWorkspaceSymbol | search.IWorkspaceSymbol[] { if (!data) { - return data; + return data; } else if (Array.isArray(data)) { - data.forEach(MainThreadLanguageFeatures._reviveSymbolInformationDto); - return data; + data.forEach(MainThreadLanguageFeatures._reviveWorkspaceSymbolDto); + return data; } else { data.location = MainThreadLanguageFeatures._reviveLocationDto(data.location); - if (data.children) { - data.children.forEach(MainThreadLanguageFeatures._reviveSymbolInformationDto); - } - return data; + return data; } } @@ -103,8 +100,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[], extensionId: string): void { this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(typeConverters.LanguageSelector.from(selector), { extensionId, - provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable => { - return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)).then(MainThreadLanguageFeatures._reviveSymbolInformationDto); + provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable => { + return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)); } }); } @@ -238,18 +235,18 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerNavigateTypeSupport(handle: number): void { let lastResultId: number; - this._registrations[handle] = WorkspaceSymbolProviderRegistry.register({ - provideWorkspaceSymbols: (search: string): TPromise => { + this._registrations[handle] = search.WorkspaceSymbolProviderRegistry.register({ + provideWorkspaceSymbols: (search: string): TPromise => { return this._proxy.$provideWorkspaceSymbols(handle, search).then(result => { if (lastResultId !== undefined) { this._proxy.$releaseWorkspaceSymbols(handle, lastResultId); } lastResultId = result._id; - return MainThreadLanguageFeatures._reviveSymbolInformationDto(result.symbols); + return MainThreadLanguageFeatures._reviveWorkspaceSymbolDto(result.symbols); }); }, - resolveWorkspaceSymbol: (item: modes.SymbolInformation): TPromise => { - return this._proxy.$resolveWorkspaceSymbol(handle, item).then(i => MainThreadLanguageFeatures._reviveSymbolInformationDto(i)); + resolveWorkspaceSymbol: (item: search.IWorkspaceSymbol): TPromise => { + return this._proxy.$resolveWorkspaceSymbol(handle, item).then(i => MainThreadLanguageFeatures._reviveWorkspaceSymbolDto(i)); } }); } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 5b9cbdc684f..ffc44405fb0 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -672,17 +672,15 @@ export interface LocationDto { range: IRange; } -export interface SymbolInformationDto extends IdObject { +export interface WorkspaceSymbolDto extends IdObject { name: string; containerName?: string; kind: modes.SymbolKind; location: LocationDto; - definingRange: IRange; - children?: SymbolInformationDto[]; } export interface WorkspaceSymbolsDto extends IdObject { - symbols: SymbolInformationDto[]; + symbols: WorkspaceSymbolDto[]; } export interface ResourceFileEditDto { @@ -726,7 +724,7 @@ export interface CodeActionDto { } export interface ExtHostLanguageFeaturesShape { - $provideDocumentSymbols(handle: number, resource: UriComponents): TPromise; + $provideDocumentSymbols(handle: number, resource: UriComponents): TPromise; $provideCodeLenses(handle: number, resource: UriComponents): TPromise; $resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise; $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; @@ -740,7 +738,7 @@ export interface ExtHostLanguageFeaturesShape { $provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions): TPromise; $provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise; $provideWorkspaceSymbols(handle: number, search: string): TPromise; - $resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise; + $resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto): TPromise; $releaseWorkspaceSymbols(handle: number, id: number): void; $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise; $resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise; diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index 0227c874623..73899b8f066 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -11,12 +11,11 @@ import * as vscode from 'vscode'; import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters'; import * as types from 'vs/workbench/api/node/extHostTypes'; import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol'; - import { ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; +import * as search from 'vs/workbench/parts/search/common/search'; import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands'; import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; -import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search'; import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures'; import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand } from './apiCommands'; @@ -266,11 +265,11 @@ export class ExtHostApiCommands { * @return A promise that resolves to an array of symbol information. */ private _executeWorkspaceSymbolProvider(query: string): Thenable { - return this._commands.executeCommand<[IWorkspaceSymbolProvider, modes.SymbolInformation[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => { + return this._commands.executeCommand<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => { const result: types.SymbolInformation[] = []; if (Array.isArray(value)) { for (let tuple of value) { - result.push(...tuple[1].map(typeConverters.SymbolInformation.to)); + result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to)); } } return result; @@ -404,13 +403,13 @@ export class ExtHostApiCommands { }); } - private _executeDocumentSymbolProvider(resource: URI): Thenable { + private _executeDocumentSymbolProvider(resource: URI): Thenable { const args = { resource }; - return this._commands.executeCommand('_executeDocumentSymbolProvider', args).then(value => { - if (value && Array.isArray(value.entries)) { - return value.entries.map(typeConverters.SymbolInformation.to); + return this._commands.executeCommand('_executeDocumentSymbolProvider', args).then(value => { + if (value && Array.isArray(value)) { + return value.map(typeConverters.DocumentSymbol.to); } return undefined; }); diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index d79065d2a00..08ac7552855 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -17,7 +17,7 @@ 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 { asWinJsPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } from './extHost.protocol'; +import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } 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'; @@ -37,7 +37,7 @@ class OutlineAdapter { this._provider = provider; } - provideDocumentSymbols(resource: URI): TPromise { + provideDocumentSymbols(resource: URI): TPromise { let doc = this._documents.getDocumentData(resource).document; return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => { if (isFalsyOrEmpty(value)) { @@ -47,7 +47,7 @@ class OutlineAdapter { if (!(probe instanceof SymbolInformation2)) { value = OutlineAdapter._asSymbolHierarchy(resource, value); } - return (value).map(typeConvert.SymbolInformation2.from); + return (value).map(typeConvert.DocumentSymbol.from); }); } @@ -429,7 +429,7 @@ class NavigateTypeAdapter { console.warn('INVALID SymbolInformation, lacks name', item); continue; } - const symbol = IdObject.mixin(typeConvert.SymbolInformation.from(item)); + const symbol = IdObject.mixin(typeConvert.WorkspaceSymbol.from(item)); this._symbolCache[symbol._id] = item; result.symbols.push(symbol); } @@ -442,7 +442,7 @@ class NavigateTypeAdapter { }); } - resolveWorkspaceSymbol(symbol: SymbolInformationDto): TPromise { + resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto): TPromise { if (typeof this._provider.resolveWorkspaceSymbol !== 'function') { return TPromise.as(symbol); @@ -451,7 +451,7 @@ class NavigateTypeAdapter { const item = this._symbolCache[symbol._id]; if (item) { return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(item, token)).then(value => { - return value && mixin(symbol, typeConvert.SymbolInformation.from(value), true); + return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true); }); } return undefined; @@ -931,7 +931,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideDocumentSymbols(handle: number, resource: UriComponents): TPromise { + $provideDocumentSymbols(handle: number, resource: UriComponents): TPromise { return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource))); } @@ -1086,7 +1086,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search)); } - $resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise { + $resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto): TPromise { return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol)); } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index 285aa9152e0..0a62f953867 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -6,6 +6,7 @@ import * as modes from 'vs/editor/common/modes'; import * as types from './extHostTypes'; +import * as search from 'vs/workbench/parts/search/common/search'; import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { EditorViewColumn } from 'vs/workbench/api/shared/editor'; import { IDecorationOptions } from 'vs/editor/common/editorCommon'; @@ -355,16 +356,16 @@ export namespace SymbolKind { } } -export namespace SymbolInformation { - export function from(info: vscode.SymbolInformation): modes.SymbolInformation { - return { +export namespace WorkspaceSymbol { + export function from(info: vscode.SymbolInformation): search.IWorkspaceSymbol { + return { name: info.name, kind: SymbolKind.from(info.kind), containerName: info.containerName, location: location.from(info.location) }; } - export function to(info: modes.SymbolInformation): types.SymbolInformation { + export function to(info: search.IWorkspaceSymbol): types.SymbolInformation { return new types.SymbolInformation( info.name, SymbolKind.to(info.kind), @@ -374,13 +375,12 @@ export namespace SymbolInformation { } } -export namespace SymbolInformation2 { - export function from(info: vscode.SymbolInformation2): modes.SymbolInformation { - let result: modes.SymbolInformation = { +export namespace DocumentSymbol { + export function from(info: vscode.SymbolInformation2): modes.DocumentSymbol { + let result: modes.DocumentSymbol = { name: info.name, - detail: undefined, - location: location.from(info.location), - definingRange: Range.from(info.definingRange), + fullRange: Range.from(info.definingRange), + identifierRange: Range.from(info.location.range), kind: SymbolKind.from(info.kind), containerName: info.containerName }; @@ -389,12 +389,12 @@ export namespace SymbolInformation2 { } return result; } - export function to(info: modes.SymbolInformation): vscode.SymbolInformation2 { + export function to(info: modes.DocumentSymbol): vscode.SymbolInformation2 { let result = new types.SymbolInformation2( info.name, SymbolKind.to(info.kind), info.containerName, - location.to(info.location), + new types.Location(undefined, Range.to(info.identifierRange)) ); if (info.children) { result.children = info.children.map(to) as any; diff --git a/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts b/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts index f532e2c7f06..9777c929734 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { DocumentSymbolProviderRegistry, SymbolInformation, DocumentSymbolProvider } from 'vs/editor/common/modes'; +import { DocumentSymbolProviderRegistry, DocumentSymbolProvider, DocumentSymbol } from 'vs/editor/common/modes'; import { ITextModel } from 'vs/editor/common/model'; import { asWinJsPromise } from 'vs/base/common/async'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -22,7 +22,7 @@ export abstract class TreeElement { abstract children: { [id: string]: TreeElement }; abstract parent: TreeElement | any; - static findId(candidate: SymbolInformation | string, container: TreeElement): string { + static findId(candidate: DocumentSymbol | string, container: TreeElement): string { // complex id-computation which contains the origin/extension, // the parent path, and some dedupe logic when names collide let candidateId: string; @@ -31,7 +31,7 @@ export abstract class TreeElement { } else { candidateId = `${container.id}/${candidate.name}`; if (container.children[candidateId] !== void 0) { - candidateId = `${container.id}/${candidate.name}_${candidate.definingRange.startLineNumber}_${candidate.definingRange.startColumn}`; + candidateId = `${container.id}/${candidate.name}_${candidate.fullRange.startLineNumber}_${candidate.fullRange.startColumn}`; } } @@ -81,7 +81,7 @@ export class OutlineElement extends TreeElement { constructor( readonly id: string, public parent: OutlineModel | OutlineGroup | OutlineElement, - readonly symbol: SymbolInformation + readonly symbol: DocumentSymbol ) { super(); } @@ -130,7 +130,7 @@ export class OutlineGroup extends TreeElement { private _getItemEnclosingPosition(position: IPosition, children: { [id: string]: OutlineElement }): OutlineElement { for (let key in children) { let item = children[key]; - if (!Range.containsPosition(item.symbol.definingRange || item.symbol.location.range, position)) { + if (!Range.containsPosition(item.symbol.fullRange, position)) { continue; } return this._getItemEnclosingPosition(position, item.children) || item; @@ -149,11 +149,11 @@ export class OutlineGroup extends TreeElement { item.marker = undefined; // find the proper start index to check for item/marker overlap. - let idx = binarySearch(markers, item.symbol.definingRange, Range.compareRangesUsingStarts); + let idx = binarySearch(markers, item.symbol.fullRange, Range.compareRangesUsingStarts); let start: number; if (idx < 0) { start = ~idx; - if (start > 0 && Range.areIntersecting(markers[start - 1], item.symbol.definingRange)) { + if (start > 0 && Range.areIntersecting(markers[start - 1], item.symbol.fullRange)) { start -= 1; } } else { @@ -163,7 +163,7 @@ export class OutlineGroup extends TreeElement { let myMarkers: IMarker[] = []; let myTopSev: MarkerSeverity; - while (start < markers.length && Range.areIntersecting(markers[start], item.symbol.definingRange)) { + while (start < markers.length && Range.areIntersecting(markers[start], item.symbol.fullRange)) { // remove markers intersecting with this outline element // and store them in a 'private' array. let marker = markers.splice(start, 1)[0]; @@ -244,7 +244,7 @@ export class OutlineModel extends TreeElement { }); } - private static _makeOutlineElement(info: SymbolInformation, container: OutlineGroup | OutlineElement): void { + private static _makeOutlineElement(info: DocumentSymbol, container: OutlineGroup | OutlineElement): void { let id = TreeElement.findId(info, container); let res = new OutlineElement(id, container, info); if (info.children) { @@ -255,6 +255,16 @@ export class OutlineModel extends TreeElement { container.children[res.id] = res; } + static get(element: TreeElement): OutlineModel { + while (element) { + if (element instanceof OutlineModel) { + return element; + } + element = element.parent; + } + return undefined; + } + readonly id = 'root'; readonly parent = undefined; diff --git a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts index bde74b610cb..425a66cb1a3 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts @@ -307,7 +307,7 @@ export class OutlinePanel extends ViewletPanel { this._tree.domFocus(); } else if (event.keyCode === KeyCode.Enter) { let element = this._tree.getFocus(); - this._revealTreeSelection(element, true, false); + this._revealTreeSelection(OutlineModel.get(element), element, true, false); } else if (event.keyCode === KeyCode.Escape) { this._input.value = ''; this._tree.domFocus(); @@ -549,7 +549,7 @@ export class OutlinePanel extends ViewletPanel { aside = !this._tree.useAltAsMultipleSelectionModifier && event.altKey || this._tree.useAltAsMultipleSelectionModifier && (event.ctrlKey || event.metaKey); } } - this._revealTreeSelection(first, focus, aside); + this._revealTreeSelection(model, first, focus, aside); })); // feature: reveal editor selection in outline @@ -606,10 +606,10 @@ export class OutlinePanel extends ViewletPanel { } } - private async _revealTreeSelection(element: OutlineElement, focus: boolean, aside: boolean): TPromise { - let { range, uri } = element.symbol.location; - let input = this._editorService.createInput({ resource: uri }); - await this._editorService.openEditor(input, { preserveFocus: !focus, selection: Range.collapseToStart(range), revealInCenterIfOutsideViewport: true, forceOpen: true }, aside ? SIDE_GROUP : ACTIVE_GROUP); + private async _revealTreeSelection(model: OutlineModel, element: OutlineElement, focus: boolean, aside: boolean): TPromise { + + let input = this._editorService.createInput({ resource: model.textModel.uri }); + await this._editorService.openEditor(input, { preserveFocus: !focus, selection: Range.collapseToStart(element.symbol.identifierRange), revealInCenterIfOutsideViewport: true, forceOpen: true }, aside ? SIDE_GROUP : ACTIVE_GROUP); } private async _revealEditorSelection(model: OutlineModel, selection: Selection): TPromise { diff --git a/src/vs/workbench/parts/outline/electron-browser/outlineTree.ts b/src/vs/workbench/parts/outline/electron-browser/outlineTree.ts index e917e18512b..88da88dd44e 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlineTree.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlineTree.ts @@ -17,7 +17,6 @@ import { Range } from 'vs/editor/common/core/range'; import { symbolKindToCssClass } from 'vs/editor/common/modes'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { OutlineElement, OutlineGroup, OutlineModel, TreeElement } from './outlineModel'; -import { getPathLabel } from 'vs/base/common/labels'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { localize } from 'vs/nls'; @@ -54,7 +53,7 @@ export class OutlineItemComparator implements ISorter { return a.symbol.name.localeCompare(b.symbol.name); case OutlineItemCompareType.ByPosition: default: - return Range.compareRangesUsingStarts(a.symbol.location.range, b.symbol.location.range); + return Range.compareRangesUsingStarts(a.symbol.fullRange, b.symbol.fullRange); } } @@ -166,7 +165,7 @@ export class OutlineRenderer implements IRenderer { renderElement(tree: ITree, element: OutlineGroup | OutlineElement, templateId: string, template: OutlineTemplate): void { if (element instanceof OutlineElement) { template.icon.className = `outline-element-icon symbol-icon ${symbolKindToCssClass(element.symbol.kind)}`; - template.label.set(element.symbol.name, element.score ? createMatches(element.score[1]) : undefined, localize('outline.title', "line {0} in {1}", element.symbol.location.range.startLineNumber, getPathLabel(element.symbol.location.uri, this._contextService, this._environmentService))); + template.label.set(element.symbol.name, element.score ? createMatches(element.score[1]) : undefined); this._renderMarkerInfo(element, template); } diff --git a/src/vs/workbench/parts/outline/test/electron-browser/outlineModel.test.ts b/src/vs/workbench/parts/outline/test/electron-browser/outlineModel.test.ts index aff10baba1e..b01fd933f91 100644 --- a/src/vs/workbench/parts/outline/test/electron-browser/outlineModel.test.ts +++ b/src/vs/workbench/parts/outline/test/electron-browser/outlineModel.test.ts @@ -7,20 +7,19 @@ import * as assert from 'assert'; import { OutlineElement, OutlineGroup } from 'vs/workbench/parts/outline/electron-browser/outlineModel'; -import { SymbolKind, SymbolInformation } from 'vs/editor/common/modes'; +import { SymbolKind, DocumentSymbol } from 'vs/editor/common/modes'; import { Range } from 'vs/editor/common/core/range'; -import URI from 'vs/base/common/uri'; import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers'; suite('OutlineModel', function () { - function fakeSymbolInformation(range: Range, name: string = 'foo'): SymbolInformation { + function fakeSymbolInformation(range: Range, name: string = 'foo'): DocumentSymbol { return { name, kind: SymbolKind.Boolean, - location: { uri: URI.parse('some:uri'), range }, - definingRange: range + identifierRange: range, + fullRange: range }; } diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index 5c9f7406346..0587d703166 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -19,7 +19,7 @@ import { IModelDecorationsChangeAccessor, OverviewRulerLane, IModelDeltaDecorati import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen'; -import { DocumentSymbolProviderRegistry, SymbolInformation, symbolKindToCssClass } from 'vs/editor/common/modes'; +import { DocumentSymbolProviderRegistry, DocumentSymbol, symbolKindToCssClass } from 'vs/editor/common/modes'; import { IRange } from 'vs/editor/common/core/range'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { overviewRulerRangeHighlight } from 'vs/editor/common/view/editorColorRegistry'; @@ -41,13 +41,6 @@ export class GotoSymbolAction extends QuickOpenAction { } class OutlineModel extends QuickOpenModel { - private outline: Outline; - - constructor(outline: Outline, entries: SymbolEntry[]) { - super(entries); - - this.outline = outline; - } public applyFilter(searchValue: string): void { @@ -107,7 +100,7 @@ class OutlineModel extends QuickOpenModel { // Update previous result with count if (currentResult) { - currentResult.setGroupLabel(this.renderGroupLabel(currentType, typeCounter, this.outline)); + currentResult.setGroupLabel(this.renderGroupLabel(currentType, typeCounter)); } currentType = result.getType(); @@ -125,7 +118,7 @@ class OutlineModel extends QuickOpenModel { // Update previous result with count if (currentResult) { - currentResult.setGroupLabel(this.renderGroupLabel(currentType, typeCounter, this.outline)); + currentResult.setGroupLabel(this.renderGroupLabel(currentType, typeCounter)); } } @@ -203,7 +196,7 @@ class OutlineModel extends QuickOpenModel { return elementARange.startLineNumber - elementBRange.startLineNumber; } - private renderGroupLabel(type: string, count: number, outline: Outline): string { + private renderGroupLabel(type: string, count: number): string { const pattern = OutlineModel.getDefaultGroupLabelPatterns()[type]; if (pattern) { @@ -357,10 +350,6 @@ class SymbolEntry extends EditorQuickOpenEntryGroup { } } -interface Outline { - entries: SymbolInformation[]; -} - interface IEditorLineDecoration { groupId: GroupIdentifier; rangeHighlightId: string; @@ -447,7 +436,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { }; } - private toQuickOpenEntries(flattened: SymbolInformation[]): SymbolEntry[] { + private toQuickOpenEntries(flattened: DocumentSymbol[]): SymbolEntry[] { const results: SymbolEntry[] = []; for (let i = 0; i < flattened.length; i++) { @@ -461,7 +450,7 @@ export class GotoSymbolHandler extends QuickOpenHandler { // Add results.push(new SymbolEntry(i, label, icon, description, icon, - element.location.range, null, this.editorService, this + element.fullRange, null, this.editorService, this )); } @@ -492,9 +481,9 @@ export class GotoSymbolHandler extends QuickOpenHandler { return TPromise.as(this.outlineToModelCache[modelId]); } - return getDocumentSymbols(model).then(outline => { + return getDocumentSymbols(model).then(entries => { - const model = new OutlineModel(outline, this.toQuickOpenEntries(outline.entries)); + const model = new OutlineModel(this.toQuickOpenEntries(entries)); this.outlineToModelCache = {}; // Clear cache, only keep 1 outline this.outlineToModelCache[modelId] = model; diff --git a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts index c3a855cb222..b381a1161fa 100644 --- a/src/vs/workbench/parts/search/browser/openSymbolHandler.ts +++ b/src/vs/workbench/parts/search/browser/openSymbolHandler.ts @@ -17,12 +17,12 @@ import * as strings from 'vs/base/common/strings'; import { Range } from 'vs/editor/common/core/range'; import { EditorInput, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import * as labels from 'vs/base/common/labels'; -import { SymbolInformation, symbolKindToCssClass } from 'vs/editor/common/modes'; +import { symbolKindToCssClass } from 'vs/editor/common/modes'; import { IResourceInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceSymbolProvider, getWorkspaceSymbols } from 'vs/workbench/parts/search/common/search'; +import { IWorkspaceSymbolProvider, getWorkspaceSymbols, IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { basename } from 'vs/base/common/paths'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -32,7 +32,7 @@ class SymbolEntry extends EditorQuickOpenEntry { private _bearingResolve: TPromise; constructor( - private _bearing: SymbolInformation, + private _bearing: IWorkspaceSymbol, private _provider: IWorkspaceSymbolProvider, @IConfigurationService private readonly _configurationService: IConfigurationService, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @@ -183,7 +183,7 @@ export class OpenSymbolHandler extends QuickOpenHandler { }); } - private fillInSymbolEntries(bucket: SymbolEntry[], provider: IWorkspaceSymbolProvider, types: SymbolInformation[], searchValue: string): void { + private fillInSymbolEntries(bucket: SymbolEntry[], provider: IWorkspaceSymbolProvider, types: IWorkspaceSymbol[], searchValue: string): void { // Convert to Entries for (let element of types) { diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index c7eb5fd5b87..9cc25782d0b 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -9,15 +9,22 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable } from 'vs/base/common/lifecycle'; import { ISearchConfiguration, ISearchConfigurationProperties } from 'vs/platform/search/common/search'; -import { SymbolInformation } from 'vs/editor/common/modes'; +import { SymbolKind, Location } from 'vs/editor/common/modes'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import URI from 'vs/base/common/uri'; import { toResource } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +export interface IWorkspaceSymbol { + name: string; + containerName?: string; + kind: SymbolKind; + location: Location; +} + export interface IWorkspaceSymbolProvider { - provideWorkspaceSymbols(search: string): TPromise; - resolveWorkspaceSymbol?: (item: SymbolInformation) => TPromise; + provideWorkspaceSymbols(search: string): TPromise; + resolveWorkspaceSymbol?: (item: IWorkspaceSymbol) => TPromise; } export namespace WorkspaceSymbolProviderRegistry { @@ -48,9 +55,9 @@ export namespace WorkspaceSymbolProviderRegistry { } } -export function getWorkspaceSymbols(query: string): TPromise<[IWorkspaceSymbolProvider, SymbolInformation[]][]> { +export function getWorkspaceSymbols(query: string): TPromise<[IWorkspaceSymbolProvider, IWorkspaceSymbol[]][]> { - const result: [IWorkspaceSymbolProvider, SymbolInformation[]][] = []; + const result: [IWorkspaceSymbolProvider, IWorkspaceSymbol[]][] = []; const promises = WorkspaceSymbolProviderRegistry.all().map(support => { return support.provideWorkspaceSymbols(query).then(value => { diff --git a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts index 69c4b023ee8..be85d29b38e 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -163,7 +163,7 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDocumentSymbols(model).then(value => { - assert.equal(value.entries.length, 1); + assert.equal(value.length, 1); }); }); }); @@ -178,11 +178,11 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDocumentSymbols(model).then(value => { - assert.equal(value.entries.length, 1); + assert.equal(value.length, 1); - let entry = value.entries[0]; + let entry = value[0]; assert.equal(entry.name, 'test'); - assert.deepEqual(entry.location.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); + assert.deepEqual(entry.fullRange, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); }); }); });