diff --git a/extensions/typescript/src/features/refactorProvider.ts b/extensions/typescript/src/features/refactorProvider.ts index 1b9062998b5dd..d9c7c4ec583a3 100644 --- a/extensions/typescript/src/features/refactorProvider.ts +++ b/extensions/typescript/src/features/refactorProvider.ts @@ -5,7 +5,7 @@ 'use strict'; -import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands, workspace, WorkspaceEdit, window, QuickPickItem, Selection, Position } from 'vscode'; +import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands, workspace, WorkspaceEdit, window, QuickPickItem, Selection, Position, CodeAction } from 'vscode'; import * as Proto from '../protocol'; import { ITypescriptServiceClient } from '../typescriptService'; @@ -56,20 +56,22 @@ export default class TypeScriptRefactorProvider implements CodeActionProvider { return []; } - const actions: Command[] = []; + const actions: CodeAction[] = []; for (const info of response.body) { if (info.inlineable === false) { actions.push({ title: info.description, command: this.selectRefactorCommandId, - arguments: [file, info, range] + arguments: [file, info, range], + dontTriggerLightBulb: true }); } else { for (const action of info.actions) { actions.push({ title: action.description, command: this.doRefactorCommandId, - arguments: [file, info.name, action.name, range] + arguments: [file, info.name, action.name, range], + dontTriggerLightBulb: true }); } } diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index da7802aaecd21..0f8a1d3b1f7c9 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -267,7 +267,7 @@ export interface CodeActionProvider { /** * Provide commands for the given document and range. */ - provideCodeActions(model: editorCommon.IReadOnlyModel, range: Range, token: CancellationToken): Command[] | Thenable; + provideCodeActions(model: editorCommon.IReadOnlyModel, range: Range, token: CancellationToken): CodeAction[] | Thenable; } /** @@ -737,6 +737,11 @@ export interface Command { tooltip?: string; arguments?: any[]; } + +export interface CodeAction extends Command { + dontTriggerLightBulb?: boolean; +} + export interface ICodeLensSymbol { range: IRange; id?: string; diff --git a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts index 3db81fda26cb5..7884595e4c0f1 100644 --- a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts @@ -70,7 +70,7 @@ export class LightBulbWidget implements IDisposable { const { token } = this._futureFixes; e.fixes.done(fixes => { - if (!token.isCancellationRequested && fixes && fixes.length > 0) { + if (!token.isCancellationRequested && fixes && fixes.some(fix => !fix.dontTriggerLightBulb)) { this.show(e); } else { this.hide(); diff --git a/src/vs/editor/contrib/quickFix/browser/quickFix.ts b/src/vs/editor/contrib/quickFix/browser/quickFix.ts index 6f13bbbc48c55..48a120c4304b9 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFix.ts @@ -7,16 +7,16 @@ import URI from 'vs/base/common/uri'; import { IReadOnlyModel } from 'vs/editor/common/editorCommon'; import { Range } from 'vs/editor/common/core/range'; -import { Command, CodeActionProviderRegistry } from 'vs/editor/common/modes'; +import { CodeAction, CodeActionProviderRegistry } from 'vs/editor/common/modes'; import { asWinJsPromise } from 'vs/base/common/async'; import { TPromise } from 'vs/base/common/winjs.base'; import { onUnexpectedExternalError, illegalArgument } from 'vs/base/common/errors'; import { IModelService } from 'vs/editor/common/services/modelService'; import { CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions'; -export function getCodeActions(model: IReadOnlyModel, range: Range): TPromise { +export function getCodeActions(model: IReadOnlyModel, range: Range): TPromise { - const allResults: Command[] = []; + const allResults: CodeAction[] = []; const promises = CodeActionProviderRegistry.all(model).map(support => { return asWinJsPromise(token => support.provideCodeActions(model, range, token)).then(result => { if (Array.isArray(result)) { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts index 9d7a64cb615b3..4d72923c29518 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixModel.ts @@ -11,7 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IMarkerService } from 'vs/platform/markers/common/markers'; import { Range } from 'vs/editor/common/core/range'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; -import { CodeActionProviderRegistry, Command } from 'vs/editor/common/modes'; +import { CodeActionProviderRegistry, CodeAction } from 'vs/editor/common/modes'; import { getCodeActions } from './quickFix'; import { Position } from 'vs/editor/common/core/position'; @@ -116,7 +116,7 @@ export interface QuickFixComputeEvent { type: 'auto' | 'manual'; range: Range; position: Position; - fixes: TPromise; + fixes: TPromise; } export class QuickFixModel { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixWidget.ts b/src/vs/editor/contrib/quickFix/browser/quickFixWidget.ts index 6cd9f41c1b72b..593ab5602ea89 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixWidget.ts @@ -10,7 +10,7 @@ import { always } from 'vs/base/common/async'; import { getDomNodePagePosition } from 'vs/base/browser/dom'; import { Position } from 'vs/editor/common/core/position'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { Command } from 'vs/editor/common/modes'; +import { CodeAction } from 'vs/editor/common/modes'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { Action } from 'vs/base/common/actions'; @@ -32,7 +32,7 @@ export class QuickFixContextMenu { this._commandService = commandService; } - show(fixes: TPromise, at: { x: number; y: number } | Position) { + show(fixes: TPromise, at: { x: number; y: number } | Position) { const actions = fixes.then(value => { return value.map(command => { diff --git a/src/vs/editor/contrib/quickFix/test/browser/quickFixModel.test.ts b/src/vs/editor/contrib/quickFix/test/browser/quickFixModel.test.ts index 6ec07062d99ad..5dbe40cea08cf 100644 --- a/src/vs/editor/contrib/quickFix/test/browser/quickFixModel.test.ts +++ b/src/vs/editor/contrib/quickFix/test/browser/quickFixModel.test.ts @@ -12,7 +12,7 @@ import { Model } from 'vs/editor/common/model/model'; import { mockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; import { MarkerService } from 'vs/platform/markers/common/markerService'; import { QuickFixOracle } from 'vs/editor/contrib/quickFix/browser/quickFixModel'; -import { CodeActionProviderRegistry, LanguageIdentifier } from 'vs/editor/common/modes'; +import { CodeActionProviderRegistry, LanguageIdentifier, CodeAction } from 'vs/editor/common/modes'; import { IDisposable } from 'vs/base/common/lifecycle'; import Event from 'vs/base/common/event'; import { Range } from 'vs/editor/common/core/range'; @@ -248,5 +248,4 @@ suite('QuickFix', () => { reg.dispose(); }); - }); diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 894e651ba1932..c1a2656905f24 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -329,7 +329,7 @@ export function registerCodeLensProvider(languageId: string, provider: modes.Cod */ export function registerCodeActionProvider(languageId: string, provider: CodeActionProvider): IDisposable { return modes.CodeActionProviderRegistry.register(languageId, { - provideCodeActions: (model: editorCommon.IReadOnlyModel, range: Range, token: CancellationToken): modes.Command[] | Thenable => { + provideCodeActions: (model: editorCommon.IReadOnlyModel, range: Range, token: CancellationToken): modes.CodeAction[] | Thenable => { let markers = StaticServices.markerService.get().read({ resource: model.uri }).filter(m => { return Range.areIntersectingOrTouching(m, range); }); @@ -411,7 +411,7 @@ export interface CodeActionProvider { /** * Provide commands for the given document and range. */ - provideCodeActions(model: editorCommon.IReadOnlyModel, range: Range, context: CodeActionContext, token: CancellationToken): modes.Command[] | Thenable; + provideCodeActions(model: editorCommon.IReadOnlyModel, range: Range, context: CodeActionContext, token: CancellationToken): modes.CodeAction[] | Thenable; } /** @@ -738,6 +738,6 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { DocumentHighlightKind: modes.DocumentHighlightKind, CompletionItemKind: CompletionItemKind, SymbolKind: modes.SymbolKind, - IndentAction: IndentAction, + IndentAction: IndentAction }; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 397272d85078e..5a6819f6346a3 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -4065,7 +4065,7 @@ declare module monaco.languages { /** * Provide commands for the given document and range. */ - provideCodeActions(model: editor.IReadOnlyModel, range: Range, context: CodeActionContext, token: CancellationToken): Command[] | Thenable; + provideCodeActions(model: editor.IReadOnlyModel, range: Range, context: CodeActionContext, token: CancellationToken): CodeAction[] | Thenable; } /** @@ -4859,6 +4859,10 @@ declare module monaco.languages { arguments?: any[]; } + export interface CodeAction extends Command { + dontTriggerLightBulb?: boolean; + } + export interface ICodeLensSymbol { range: IRange; id?: string; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index aa14e43602b37..01bf18521d560 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1664,6 +1664,16 @@ declare module 'vscode' { readonly diagnostics: Diagnostic[]; } + /** + * A code action for the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. + */ + export interface CodeAction extends Command { + /** + * Should the lightbulb automatically be shown in the UI? + */ + dontTriggerLightBulb?: boolean; + } + /** * The code action interface defines the contract between extensions and * the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. @@ -1682,7 +1692,7 @@ declare module 'vscode' { * @return An array of commands or a thenable of such. The lack of a result can be * signaled by returning `undefined`, `null`, or an empty array. */ - provideCodeActions(document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): ProviderResult; + provideCodeActions(document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): ProviderResult; } /** diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 258bd4449e815..835c070e81b8a 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -166,7 +166,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise { this._registrations[handle] = modes.CodeActionProviderRegistry.register(selector, { - provideCodeActions: (model: IReadOnlyModel, range: EditorRange, token: CancellationToken): Thenable => { + provideCodeActions: (model: IReadOnlyModel, range: EditorRange, token: CancellationToken): Thenable => { return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range))); } }); diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 3291bc7ef5ff5..8b0d1b1b0f4d5 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -499,7 +499,7 @@ export interface ExtHostLanguageFeaturesShape { $provideHover(handle: number, resource: URI, position: IPosition): TPromise; $provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise; $provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise; - $provideCodeActions(handle: number, resource: URI, range: IRange): TPromise; + $provideCodeActions(handle: number, resource: URI, range: IRange): TPromise; $provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise; $provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise; $provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise; diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 3e295379597e5..f176d9db9aa9f 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -280,7 +280,7 @@ class QuickFixAdapter { this._provider = provider; } - provideCodeActions(resource: URI, range: IRange): TPromise { + provideCodeActions(resource: URI, range: IRange): TPromise { const doc = this._documents.getDocumentData(resource).document; const ran = TypeConverters.toRange(range); @@ -296,11 +296,15 @@ class QuickFixAdapter { } }); - return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => { - if (!Array.isArray(commands)) { + return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(actions => { + if (!Array.isArray(actions)) { return undefined; } - return commands.map(command => this._commands.toInternal(command)); + return actions.map(action => { + const a: modes.CodeAction = this._commands.toInternal(action as vscode.Command); + a.dontTriggerLightBulb = action.dontTriggerLightBulb; + return a; + }); }); } } @@ -921,7 +925,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideCodeActions(handle: number, resource: URI, range: IRange): TPromise { + $provideCodeActions(handle: number, resource: URI, range: IRange): TPromise { return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range)); }