diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index a958e68f6a8..a87e5e38be4 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -292,13 +292,13 @@ export class PluginHostAPIImplementation { return features.workspaceSymbols.register(provider); }, registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { - return features.formatDocument.register(selector, provider); + return languageFeatures.registerDocumentFormattingEditProvider(selector, provider); }, registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { - return features.formatRange.register(selector, provider); + return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider); }, registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable { - return features.formatOnType.register(selector, { triggerCharacters: [firstTriggerCharacter].concat(moreTriggerCharacters), provider }); + return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); }, registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable { return features.signatureHelp.register(selector, { triggerCharacters, provider }); diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 497e9cade19..046d93e0a3c 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -356,7 +356,78 @@ class QuickFixAdapter implements modes.IQuickFixSupport { } } -type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter; +class DocumentFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + formatDocument(resource: URI, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + + return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(doc, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +class RangeFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.DocumentRangeFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.DocumentRangeFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + formatRange(resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + let ran = TypeConverters.toRange(range); + + return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(doc, ran, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +class OnTypeFormattingAdapter implements modes.IFormattingSupport { + + private _documents: PluginHostModelService; + private _provider: vscode.OnTypeFormattingEditProvider; + + constructor(documents: PluginHostModelService, provider: vscode.OnTypeFormattingEditProvider) { + this._documents = documents; + this._provider = provider; + } + + autoFormatTriggerCharacters = []; // not here + + formatAfterKeystroke(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise { + + let doc = this._documents.getDocument(resource); + let pos = TypeConverters.toPosition(position); + + return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(doc, pos, ch, options, token)).then(value => { + if (Array.isArray(value)) { + return value.map(TypeConverters.fromTextEdit); + } + }); + } +} + +type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | ExtraInfoAdapter | OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter + | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter; @Remotable.PluginHostContext('ExtHostLanguageFeatures') export class ExtHostLanguageFeatures { @@ -491,6 +562,42 @@ export class ExtHostLanguageFeatures { $runQuickFixAction(handle: number, resource: URI, range: IRange, id: string): any { return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.runQuickFixAction(resource, range, id)); } + + // --- formatting + + registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new DocumentFormattingAdapter(this._documents, provider); + this._proxy.$registerDocumentFormattingSupport(handle, selector); + return this._createDisposable(handle); + } + + $formatDocument(handle: number, resource: URI, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.formatDocument(resource, options)); + } + + registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new RangeFormattingAdapter(this._documents, provider); + this._proxy.$registerRangeFormattingSupport(handle, selector); + return this._createDisposable(handle); + } + + $formatRange(handle: number, resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.formatRange(resource, range, options)); + } + + registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable { + const handle = this._nextHandle(); + this._adapter[handle] = new OnTypeFormattingAdapter(this._documents, provider); + this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters); + return this._createDisposable(handle); + } + + $formatAfterKeystroke(handle: number, resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise{ + return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.formatAfterKeystroke(resource, position, ch, options)); + } + } @Remotable.MainContext('MainThreadLanguageFeatures') @@ -608,4 +715,36 @@ export class MainThreadLanguageFeatures { }); return undefined; } + + // --- formatting + + $registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = FormatRegistry.register(selector, { + formatDocument: (resource: URI, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatDocument(handle, resource, options); + } + }); + return undefined; + } + + $registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise { + this._registrations[handle] = FormatRegistry.register(selector, { + formatRange: (resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatRange(handle, resource, range, options); + } + }); + return undefined; + } + + $registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise { + this._registrations[handle] = FormatOnTypeRegistry.register(selector, { + + autoFormatTriggerCharacters, + + formatAfterKeystroke: (resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise => { + return this._proxy.$formatAfterKeystroke(handle, resource, position, ch, options); + } + }); + return undefined; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 74f3d9c5d9c..f87fa4d2617 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -8,7 +8,7 @@ import Severity from 'vs/base/common/severity'; import * as objects from 'vs/base/common/objects'; import {Position as EditorPosition} from 'vs/platform/editor/common/editor'; import {Selection, Range, Position, SymbolKind, DiagnosticSeverity, ViewColumn} from './pluginHostTypes'; -import {IPosition, ISelection, IRange, IRangeWithMessage} from 'vs/editor/common/editorCommon'; +import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; export interface PositionLike { @@ -189,3 +189,10 @@ export function fromRangeOrRangeWithMessage(ranges:vscode.Range[]|vscode.Decorat }); } } + +export function fromTextEdit(edit: vscode.TextEdit) { + return { + text: edit.newText, + range: fromRange(edit.range) + } +} \ No newline at end of file