diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 6d132f2dad7..660c3a22477 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -15,13 +15,14 @@ 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 } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, WorkspaceEditDto, ResourceEditDto, CodeActionDto } 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'; import { IModeService } from 'vs/editor/common/services/modeService'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters'; +import URI from 'vs/base/common/uri'; @extHostNamedCustomer(MainContext.MainThreadLanguageFeatures) export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape { @@ -56,12 +57,63 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha return undefined; } + //#region --- revive functions + + private static _reviveLocationDto(data: LocationDto): modes.Location; + private static _reviveLocationDto(data: LocationDto[]): modes.Location[]; + private static _reviveLocationDto(data: LocationDto | LocationDto[]): modes.Location | modes.Location[] { + if (!data) { + return data; + } else if (Array.isArray(data)) { + data.forEach(l => MainThreadLanguageFeatures._reviveLocationDto(l)); + return data; + } else { + data.uri = URI.revive(data.uri); + return data; + } + } + + private static _reviveSymbolInformationDto(data: SymbolInformationDto): modes.SymbolInformation; + private static _reviveSymbolInformationDto(data: SymbolInformationDto[]): modes.SymbolInformation[]; + private static _reviveSymbolInformationDto(data: SymbolInformationDto | SymbolInformationDto[]): modes.SymbolInformation | modes.SymbolInformation[] { + if (!data) { + return data; + } else if (Array.isArray(data)) { + data.forEach(MainThreadLanguageFeatures._reviveSymbolInformationDto); + return data; + } else { + data.location = MainThreadLanguageFeatures._reviveLocationDto(data.location); + return data; + } + } + + private static _reviveResourceEditDto(data: ResourceEditDto): modes.IResourceEdit { + data.resource = URI.revive(data.resource); + return data; + } + + private static _reviveWorkspaceEditDto(data: WorkspaceEditDto): modes.WorkspaceEdit { + if (data && data.edits) { + data.edits.forEach(MainThreadLanguageFeatures._reviveResourceEditDto); + } + return data; + } + + private static _reviveCodeActionDto(data: CodeActionDto[]): modes.CodeAction[] { + if (data) { + data.forEach(code => MainThreadLanguageFeatures._reviveWorkspaceEditDto(code.edits)); + } + return data; + } + + //#endregion + // --- outline $registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(toLanguageSelector(selector), { provideDocumentSymbols: (model: IReadOnlyModel, token: CancellationToken): Thenable => { - return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)); + return wireCancellationToken(token, this._proxy.$provideDocumentSymbols(handle, model.uri)).then(MainThreadLanguageFeatures._reviveSymbolInformationDto); } }); return undefined; @@ -103,7 +155,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.DefinitionProviderRegistry.register(toLanguageSelector(selector), { provideDefinition: (model, position, token): Thenable => { - return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)); + return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); } }); return undefined; @@ -112,7 +164,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.ImplementationProviderRegistry.register(toLanguageSelector(selector), { provideImplementation: (model, position, token): Thenable => { - return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)); + return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); } }); return undefined; @@ -121,7 +173,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(toLanguageSelector(selector), { provideTypeDefinition: (model, position, token): Thenable => { - return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)); + return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); } }); return undefined; @@ -154,7 +206,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.ReferenceProviderRegistry.register(toLanguageSelector(selector), { provideReferences: (model: IReadOnlyModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable => { - return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context)); + return wireCancellationToken(token, this._proxy.$provideReferences(handle, model.uri, position, context)).then(MainThreadLanguageFeatures._reviveLocationDto); } }); return undefined; @@ -165,7 +217,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.CodeActionProviderRegistry.register(toLanguageSelector(selector), { provideCodeActions: (model: IReadOnlyModel, range: EditorRange, token: CancellationToken): Thenable => { - return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range))); + return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range))).then(MainThreadLanguageFeatures._reviveCodeActionDto); } }); return undefined; @@ -209,17 +261,16 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha let lastResultId: number; this._registrations[handle] = 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 result.symbols; + return MainThreadLanguageFeatures._reviveSymbolInformationDto(result.symbols); }); }, resolveWorkspaceSymbol: (item: modes.SymbolInformation): TPromise => { - return this._proxy.$resolveWorkspaceSymbol(handle, item); + return this._proxy.$resolveWorkspaceSymbol(handle, item).then(i => MainThreadLanguageFeatures._reviveSymbolInformationDto(i)); } }); return undefined; @@ -230,7 +281,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.RenameProviderRegistry.register(toLanguageSelector(selector), { provideRenameEdits: (model: IReadOnlyModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable => { - return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)); + return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)).then(MainThreadLanguageFeatures._reviveWorkspaceEditDto); } }); return undefined; @@ -239,7 +290,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- suggest $registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): TPromise { - this._registrations[handle] = modes.SuggestRegistry.register(toLanguageSelector(selector), { triggerCharacters, provideCompletionItems: (model: IReadOnlyModel, position: EditorPosition, context: modes.SuggestContext, token: CancellationToken): Thenable => { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 37ec91f5ea4..0b7b069eab5 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -580,51 +580,78 @@ export interface IRawColorInfo { range: IRange; } -export interface IExtHostSuggestion extends modes.ISuggestion { - _id: number; - _parentId: number; -} - -export interface IExtHostSuggestResult { - _id: number; - suggestions: IExtHostSuggestion[]; - incomplete?: boolean; -} - -export interface IdObject { - _id: number; -} - -export namespace IdObject { - let n = 0; - export function mixin(object: T): T & IdObject { - (object)._id = n++; +export class IdObject { + _id?: number; + private static _n = 0; + static mixin(object: T): T & IdObject { + (object)._id = IdObject._n++; return object; } } -export type IWorkspaceSymbol = IdObject & modes.SymbolInformation; -export interface IWorkspaceSymbols extends IdObject { symbols: IWorkspaceSymbol[]; } +export interface SuggestionDto extends modes.ISuggestion { + _id: number; + _parentId: number; +} + +export interface SuggestResultDto extends IdObject { + suggestions: SuggestionDto[]; + incomplete?: boolean; +} + +export interface LocationDto { + uri: UriComponents; + range: IRange; +} + +export interface SymbolInformationDto extends IdObject { + name: string; + containerName?: string; + kind: modes.SymbolKind; + location: LocationDto; +} + +export interface WorkspaceSymbolsDto extends IdObject { + symbols: SymbolInformationDto[]; +} + +export interface ResourceEditDto { + resource: UriComponents; + range: IRange; + newText: string; +} + +export interface WorkspaceEditDto { + edits: ResourceEditDto[]; + rejectReason?: string; +} + +export interface CodeActionDto { + title: string; + edits?: WorkspaceEditDto; + diagnostics?: IMarkerData[]; + command?: modes.Command; +} 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; - $provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise; - $provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; + $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; + $provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise; + $provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise; - $provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise; - $provideCodeActions(handle: number, resource: UriComponents, range: IRange): TPromise; + $provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise; + $provideCodeActions(handle: number, resource: UriComponents, range: IRange): TPromise; $provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise; $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: modes.SymbolInformation): TPromise; + $provideWorkspaceSymbols(handle: number, search: string): TPromise; + $resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise; $releaseWorkspaceSymbols(handle: number, id: number): void; - $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise; - $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise; + $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise; + $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise; $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise; $releaseCompletionItems(handle: number, id: number): void; $provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition): TPromise; @@ -748,7 +775,7 @@ export const ExtHostContext = { ExtHostFileSystem: createExtId('ExtHostFileSystem'), ExtHostFileSystemEventService: createExtId('ExtHostFileSystemEventService'), ExtHostHeapService: createExtId('ExtHostHeapMonitor'), - ExtHostLanguageFeatures: createExtId('ExtHostLanguageFeatures', ProxyType.CustomMarshaller), + ExtHostLanguageFeatures: createExtId('ExtHostLanguageFeatures'), ExtHostQuickOpen: createExtId('ExtHostQuickOpen'), ExtHostExtensionService: createExtId('ExtHostExtensionService'), ExtHostTerminalService: createExtId('ExtHostTerminalService'), diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 1713aaa154a..2425ca991c8 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, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics'; import { asWinJsPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration } from './extHost.protocol'; +import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto } 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'; @@ -35,11 +35,11 @@ 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 (Array.isArray(value)) { - return value.map(TypeConverters.fromSymbolInformation); + return value.map(symbol => IdObject.mixin(TypeConverters.fromSymbolInformation(symbol))); } return undefined; }); @@ -413,8 +413,8 @@ class NavigateTypeAdapter { this._provider = provider; } - provideWorkspaceSymbols(search: string): TPromise { - const result: IWorkspaceSymbols = IdObject.mixin({ symbols: [] }); + provideWorkspaceSymbols(search: string): TPromise { + const result: WorkspaceSymbolsDto = IdObject.mixin({ symbols: [] }); return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => { if (!isFalsyOrEmpty(value)) { for (const item of value) { @@ -439,7 +439,7 @@ class NavigateTypeAdapter { }); } - resolveWorkspaceSymbol(symbol: IWorkspaceSymbol): TPromise { + resolveWorkspaceSymbol(symbol: SymbolInformationDto): TPromise { if (typeof this._provider.resolveWorkspaceSymbol !== 'function') { return TPromise.as(symbol); @@ -524,7 +524,7 @@ class SuggestAdapter { this._provider = provider; } - provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise { + provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise { const doc = this._documents.getDocumentData(resource).document; const pos = TypeConverters.toPosition(position); @@ -535,7 +535,7 @@ class SuggestAdapter { const _id = this._idPool++; - const result: IExtHostSuggestResult = { + const result: SuggestResultDto = { _id, suggestions: [], }; @@ -577,7 +577,7 @@ class SuggestAdapter { return TPromise.as(suggestion); } - const { _parentId, _id } = (suggestion); + const { _parentId, _id } = (suggestion); const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id]; if (!item) { return TPromise.as(suggestion); @@ -605,13 +605,13 @@ class SuggestAdapter { this._cache.delete(id); } - private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): IExtHostSuggestion { + private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto { if (typeof item.label !== 'string' || item.label.length === 0) { console.warn('INVALID text edit -> must have at least a label'); return undefined; } - const result: IExtHostSuggestion = { + const result: SuggestionDto = { // _id, _parentId, @@ -835,7 +835,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))); } @@ -996,11 +996,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideWorkspaceSymbols(handle: number, search: string): TPromise { + $provideWorkspaceSymbols(handle: number, search: string): TPromise { return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search)); } - $resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise { + $resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise { return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol)); } @@ -1030,7 +1030,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise { + $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise { return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context)); }