diff --git a/lib/adapters/code-action-adapter.ts b/lib/adapters/code-action-adapter.ts index 2e6c2bc0..fc8c3a94 100644 --- a/lib/adapters/code-action-adapter.ts +++ b/lib/adapters/code-action-adapter.ts @@ -41,7 +41,9 @@ export default class CodeActionAdapter { linterAdapter: LinterPushV2Adapter | IdeDiagnosticAdapter | undefined, editor: TextEditor, range: Range, - linterMessages: linter.Message[] | atomIde.Diagnostic[] + linterMessages: linter.Message[] | atomIde.Diagnostic[], + filterActions: (actions: (Command | CodeAction)[] | null) => (Command | CodeAction)[] | null = (actions) => actions, + onApply: (action: Command | CodeAction) => Promise = () => Promise.resolve(true) ): Promise { if (linterAdapter == null) { return [] @@ -49,19 +51,23 @@ export default class CodeActionAdapter { assert(serverCapabilities.codeActionProvider, "Must have the textDocument/codeAction capability") const params = createCodeActionParams(linterAdapter, editor, range, linterMessages) - const actions = await connection.codeAction(params) + const actions = filterActions(await connection.codeAction(params)) if (actions === null) { return [] } - return actions.map((action) => CodeActionAdapter.createCodeAction(action, connection)) + return actions.map((action) => CodeActionAdapter.createCodeAction(action, connection, onApply)) } private static createCodeAction( action: Command | CodeAction, - connection: LanguageClientConnection + connection: LanguageClientConnection, + onApply: (action: Command | CodeAction) => Promise ): atomIde.CodeAction { return { async apply() { + if ((await onApply(action)) === false) { + return + } if (CodeAction.is(action)) { CodeActionAdapter.applyWorkspaceEdit(action.edit) await CodeActionAdapter.executeCommand(action.command, connection) diff --git a/lib/auto-languageclient.ts b/lib/auto-languageclient.ts index d5cd70ff..926e4dd1 100644 --- a/lib/auto-languageclient.ts +++ b/lib/auto-languageclient.ts @@ -219,6 +219,11 @@ export default class AutoLanguageClient { }, codeAction: { dynamicRegistration: false, + codeActionLiteralSupport: { + codeActionKind: { + valueSet: [""], // TODO explicitly support more? + }, + }, }, codeLens: { dynamicRegistration: false, @@ -939,10 +944,25 @@ export default class AutoLanguageClient { this.getServerAdapter(server, "linterPushV2"), editor, range, - diagnostics + diagnostics, + this.filterCodeActions.bind(this), + this.onApplyCodeActions.bind(this) ) } + /** Optionally filter code action before they're displayed */ + protected filterCodeActions(actions: (ls.Command | ls.CodeAction)[] | null): (ls.Command | ls.CodeAction)[] | null { + return actions + } + + /** + * Optionally handle a code action before default handling. Return `false` to prevent default handling, `true` to + * continue with default handling. + */ + protected async onApplyCodeActions(_action: ls.Command | ls.CodeAction): Promise { + return true + } + public provideRefactor(): atomIde.RefactorProvider { return { grammarScopes: this.getGrammarScopes(),