diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 363d9f9c4fb..7355baae8ac 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -363,14 +363,8 @@ export interface IQuickFix { command: ICommand; score: number; } - -export interface IQuickFixResult { - edits?: IResourceEdit[]; - message?: string; -} - -export interface IQuickFixSupport { - getQuickFixes(resource: URI, range: editorCommon.IRange): TPromise; +export interface CodeActionProvider { + provideCodeActions(model:editorCommon.IReadOnlyModel, range:editorCommon.IEditorRange, token: CancellationToken): IQuickFix[] | Thenable; } @@ -802,7 +796,7 @@ export const DefinitionProviderRegistry = new LanguageFeatureRegistry(); -export const QuickFixRegistry = new LanguageFeatureRegistry(); +export const CodeActionProviderRegistry = new LanguageFeatureRegistry(); export const FormatRegistry = new LanguageFeatureRegistry(); diff --git a/src/vs/editor/contrib/gotoError/browser/gotoError.ts b/src/vs/editor/contrib/gotoError/browser/gotoError.ts index 9e48de50718..7acec51bc07 100644 --- a/src/vs/editor/contrib/gotoError/browser/gotoError.ts +++ b/src/vs/editor/contrib/gotoError/browser/gotoError.ts @@ -29,7 +29,7 @@ import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/edito import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IOptions, ZoneWidget} from 'vs/editor/contrib/zoneWidget/browser/zoneWidget'; -import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {getCodeActions} from 'vs/editor/contrib/quickFix/common/quickFix'; class MarkerModel { @@ -294,7 +294,7 @@ class MarkerNavigationWidget extends ZoneWidget { this._element.appendChild(renderHtml(marker.message)); this._quickFixSection.style.display = 'none'; - getQuickFixes(this.editor.getModel(), marker).then(result => { + getCodeActions(this.editor.getModel(), Range.lift(marker)).then(result => { dom.clearNode(this._quickFixSection); if (result.length > 0) { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFix.ts b/src/vs/editor/contrib/quickFix/browser/quickFix.ts index fc6bc9ed8b9..dee047d3166 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFix.ts @@ -18,7 +18,7 @@ import {EditorAction} from 'vs/editor/common/editorAction'; import {ICommonCodeEditor, IEditorActionDescriptorData, IEditorContribution, IRange} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {QuickFixRegistry} from 'vs/editor/common/modes'; +import {CodeActionProviderRegistry} from 'vs/editor/common/modes'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import {IQuickFix2} from '../common/quickFix'; import {QuickFixModel} from './quickFixModel'; @@ -128,7 +128,7 @@ export class QuickFixAction extends EditorAction { public isSupported(): boolean { var model = this.editor.getModel(); - return QuickFixRegistry.has(model) && !this.editor.getConfiguration().readOnly; + return CodeActionProviderRegistry.has(model) && !this.editor.getConfiguration().readOnly; } public run():TPromise { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts index b1cce864412..1efbf89aacb 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts @@ -16,8 +16,8 @@ import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers'; import {Range} from 'vs/editor/common/core/range'; import {EventType, ICursorPositionChangedEvent, IPosition, IRange} from 'vs/editor/common/editorCommon'; import {ICodeEditor} from 'vs/editor/browser/editorBrowser'; -import {QuickFixRegistry} from 'vs/editor/common/modes'; -import {IQuickFix2, getQuickFixes} from '../common/quickFix'; +import {CodeActionProviderRegistry} from 'vs/editor/common/modes'; +import {IQuickFix2, getCodeActions} from '../common/quickFix'; import {LightBulpWidget} from './lightBulpWidget'; enum QuickFixSuggestState { @@ -80,7 +80,7 @@ export class QuickFixModel extends EventEmitter { this.toDispose.push(this.editor.addListener2(EventType.ModelChanged, () => this.onModelChanged())); this.toDispose.push(this.editor.addListener2(EventType.ModelModeChanged, () => this.onModelChanged())); - this.toDispose.push(QuickFixRegistry.onDidChange(this.onModelChanged, this)); + this.toDispose.push(CodeActionProviderRegistry.onDidChange(this.onModelChanged, this)); } private onModelChanged(): void { @@ -91,7 +91,7 @@ export class QuickFixModel extends EventEmitter { this.markers = null; this.updateScheduler = null; - if (!QuickFixRegistry.has(this.editor.getModel()) || this.editor.getConfiguration().readOnly) { + if (!CodeActionProviderRegistry.has(this.editor.getModel()) || this.editor.getConfiguration().readOnly) { this.setDecoration(null); return; } @@ -194,7 +194,7 @@ export class QuickFixModel extends EventEmitter { private computeFixes(range: IMarker | IRange): TPromise { let model = this.editor.getModel(); - if (!QuickFixRegistry.has(model)) { + if (!CodeActionProviderRegistry.has(model)) { return TPromise.as(null); } @@ -208,7 +208,7 @@ export class QuickFixModel extends EventEmitter { } this.quickFixRequestPromiseRange = range; - this.quickFixRequestPromise = getQuickFixes(model, range); + this.quickFixRequestPromise = getCodeActions(model, Range.lift(range)); return this.quickFixRequestPromise; } diff --git a/src/vs/editor/contrib/quickFix/common/quickFix.ts b/src/vs/editor/contrib/quickFix/common/quickFix.ts index 0c57721dd8c..d073dad8407 100644 --- a/src/vs/editor/contrib/quickFix/common/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/common/quickFix.ts @@ -10,22 +10,25 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import {IdGenerator} from 'vs/base/common/idGenerator'; import {Range} from 'vs/editor/common/core/range'; -import {IModel, IRange} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, IEditorRange} from 'vs/editor/common/editorCommon'; import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {QuickFixRegistry, IQuickFix, IQuickFixSupport} from 'vs/editor/common/modes'; +import {CodeActionProviderRegistry, IQuickFix, CodeActionProvider} from 'vs/editor/common/modes'; import {IModelService} from 'vs/editor/common/services/modelService'; +import {asWinJsPromise} from 'vs/base/common/async'; export interface IQuickFix2 extends IQuickFix { - support: IQuickFixSupport; + support: CodeActionProvider; id: string; } -export function getQuickFixes(model: IModel, range: IRange): TPromise { +export function getCodeActions(model: IReadOnlyModel, range: IEditorRange): TPromise { const quickFixes: IQuickFix2[] = []; let ids = new IdGenerator('quickfix'); - const promises = QuickFixRegistry.all(model).map(support => { - return support.getQuickFixes(model.getAssociatedResource(), range).then(result => { + const promises = CodeActionProviderRegistry.all(model).map(support => { + return asWinJsPromise((token) => { + return support.provideCodeActions(model, range, token); + }).then(result => { if (!Array.isArray(result)) { return; } @@ -57,5 +60,7 @@ CommonEditorRegistry.registerLanguageCommand('_executeCodeActionProvider', funct throw illegalArgument(); } - return getQuickFixes(model, range); -}); \ No newline at end of file + const editorRange = Range.lift(range); + + return getCodeActions(model, editorRange); +}); diff --git a/src/vs/languages/css/common/css.ts b/src/vs/languages/css/common/css.ts index 68c6b1a7d35..4b77acab0a3 100644 --- a/src/vs/languages/css/common/css.ts +++ b/src/vs/languages/css/common/css.ts @@ -365,7 +365,11 @@ export class CSSMode extends AbstractMode { } }); - modes.QuickFixRegistry.register(this.getId(), this); + modes.CodeActionProviderRegistry.register(this.getId(), { + provideCodeActions: (model, range, token): Thenable => { + return wireCancellationToken(token, this._provideCodeActions(model.getAssociatedResource(), range)); + } + }); } public creationDone(): void { @@ -437,8 +441,8 @@ export class CSSMode extends AbstractMode { return this._worker((w) => w.findColorDeclarations(resource)); } - static getQuickFixes = OneWorkerAttr(CSSMode, CSSMode.prototype.getQuickFixes); - public getQuickFixes(resource: URI, marker: IMarker | editorCommon.IRange): WinJS.TPromise{ - return this._worker((w) => w.getQuickFixes(resource, marker)); + static _provideCodeActions = OneWorkerAttr(CSSMode, CSSMode.prototype._provideCodeActions); + private _provideCodeActions(resource: URI, marker: IMarker | editorCommon.IRange): WinJS.TPromise{ + return this._worker((w) => w.provideCodeActions(resource, marker)); } } diff --git a/src/vs/languages/css/common/cssWorker.ts b/src/vs/languages/css/common/cssWorker.ts index bd8ffd1c97f..c746451ce0a 100644 --- a/src/vs/languages/css/common/cssWorker.ts +++ b/src/vs/languages/css/common/cssWorker.ts @@ -434,7 +434,7 @@ export class CSSWorker { } } - public getQuickFixes(resource: URI, range: editorCommon.IRange): winjs.TPromise { + public provideCodeActions(resource: URI, range: editorCommon.IRange): winjs.TPromise { return this.languageService.join().then(() => { const result: modes.IQuickFix[] = []; diff --git a/src/vs/languages/css/test/common/css-worker.test.ts b/src/vs/languages/css/test/common/css-worker.test.ts index 4242ade01fa..43ec70606e6 100644 --- a/src/vs/languages/css/test/common/css-worker.test.ts +++ b/src/vs/languages/css/test/common/css-worker.test.ts @@ -105,7 +105,7 @@ suite('Validation - CSS', () => { var markers = env.markers.filter((m) => m.startColumn === pos.column && m.startLineNumber === pos.lineNumber); assert.equal(1, markers.length, 'No marker at pos: ' + JSON.stringify({ pos: pos, markers: env.markers })); - return env.worker.getQuickFixes(url, markers[0]).then((fixes) => { return { fixes: fixes, model: env.model}; }); + return env.worker.provideCodeActions(url, markers[0]).then((fixes) => { return { fixes: fixes, model: env.model}; }); }; var assertSuggestion= function(completion:Modes.ISuggestResult, label:string, type?:string) { diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 5d90fc405cf..e6f5bf4244b 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -11,7 +11,7 @@ import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; import * as vscode from 'vscode'; import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters'; import {Range, Disposable, SignatureHelp, CompletionList} from 'vs/workbench/api/node/extHostTypes'; -import {IReadOnlyModel, IEditorPosition, IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import {IReadOnlyModel, IEditorPosition, IPosition, IEditorRange, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import * as modes from 'vs/editor/common/modes'; import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments'; import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands'; @@ -275,7 +275,7 @@ class ReferenceAdapter { } } -class QuickFixAdapter implements modes.IQuickFixSupport { +class QuickFixAdapter { private _documents: ExtHostModelService; private _commands: ExtHostCommands; @@ -291,7 +291,7 @@ class QuickFixAdapter implements modes.IQuickFixSupport { this._provider = provider; } - getQuickFixes(resource: URI, range: IRange): TPromise { + provideCodeActions(resource: URI, range: IRange): TPromise { const doc = this._documents.getDocumentData(resource).document; const ran = TypeConverters.toRange(range); @@ -321,11 +321,6 @@ class QuickFixAdapter implements modes.IQuickFixSupport { }); }); } - - runQuickFixAction(resource: URI, range: IRange, quickFix: modes.IQuickFix): any { - let command = TypeConverters.Command.to(quickFix.command); - return this._commands.executeCommand(command.command, ...command.arguments); - } } class DocumentFormattingAdapter implements modes.IFormattingSupport { @@ -725,12 +720,8 @@ export class ExtHostLanguageFeatures { return this._createDisposable(handle); } - $getQuickFixes(handle: number, resource: URI, range: IRange): TPromise { - return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.getQuickFixes(resource, range)); - } - - $runQuickFixAction(handle: number, resource: URI, range: IRange, quickFix: modes.IQuickFix): any { - return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.runQuickFixAction(resource, range, quickFix)); + $provideCodeActions(handle: number, resource: URI, range: IRange): TPromise { + return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range)); } // --- formatting @@ -916,12 +907,9 @@ export class MainThreadLanguageFeatures { // --- quick fix $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise { - this._registrations[handle] = modes.QuickFixRegistry.register(selector, { - getQuickFixes: (resource: URI, range: IRange): TPromise => { - return this._proxy.$getQuickFixes(handle, resource, range); - }, - runQuickFixAction: (resource: URI, range: IRange, quickFix: modes.IQuickFix) => { - return this._proxy.$runQuickFixAction(handle, resource, range, quickFix); + this._registrations[handle] = modes.CodeActionProviderRegistry.register(selector, { + provideCodeActions: (model:IReadOnlyModel, range:IEditorRange, token: CancellationToken): Thenable => { + return wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.getAssociatedResource(), range)); } }); return undefined; diff --git a/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts index 64dbe370642..9b236130c73 100644 --- a/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts @@ -28,7 +28,7 @@ import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/commo import {provideHover} from 'vs/editor/contrib/hover/common/hover'; import {getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; import {provideReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; -import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {getCodeActions} from 'vs/editor/contrib/quickFix/common/quickFix'; import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; import {rename} from 'vs/editor/contrib/rename/common/rename'; import {provideSignatureHelp} from 'vs/editor/contrib/parameterHints/common/parameterHints'; @@ -587,7 +587,7 @@ suite('ExtHostLanguageFeatures', function() { })); return threadService.sync().then(() => { - return getQuickFixes(model, model.getFullModelRange()).then(value => { + return getCodeActions(model, model.getFullModelRange()).then(value => { assert.equal(value.length, 2); let [first, second] = value; @@ -613,7 +613,7 @@ suite('ExtHostLanguageFeatures', function() { })); return threadService.sync().then(() => { - return getQuickFixes(model, model.getFullModelRange()).then(value => { + return getCodeActions(model, model.getFullModelRange()).then(value => { assert.equal(value.length, 1); }); });