diff --git a/newtests/lsp/code-action-disabled/test.js b/newtests/lsp/code-action-disabled/test.js index ee9807265c1..a105e777bd6 100644 --- a/newtests/lsp/code-action-disabled/test.js +++ b/newtests/lsp/code-action-disabled/test.js @@ -15,16 +15,6 @@ export default suite( addFile, lspIgnoreStatusAndCancellation, }) => [ - test('initialize', [ - lspStart({needsFlowServer: false}), - lspRequestAndWaitUntilResponse( - 'initialize', - lspInitializeParams, - ).verifyAllLSPMessagesInStep( - ['initialize{"codeActionProvider":false}'], - [...lspIgnoreStatusAndCancellation], - ), - ]), test('textDocument/codeAction #0', [ addFile('error1.js.ignored', 'error1.js'), lspStartAndConnect(), diff --git a/newtests/lsp/code-action/test.js b/newtests/lsp/code-action/test.js index be4e5241f7a..a061aee9d2e 100644 --- a/newtests/lsp/code-action/test.js +++ b/newtests/lsp/code-action/test.js @@ -15,13 +15,29 @@ export default suite( addFile, lspIgnoreStatusAndCancellation, }) => [ - test('initialize', [ + test('initialize with quickfix support', [ lspStart({needsFlowServer: false}), lspRequestAndWaitUntilResponse( 'initialize', lspInitializeParams, ).verifyAllLSPMessagesInStep( - ['initialize{"codeActionProvider":true}'], + ['initialize{"codeActionProvider":{"codeActionKinds":["quickfix"]}}'], + [...lspIgnoreStatusAndCancellation], + ), + ]), + test('initialize without quickfix support', [ + lspStart({needsFlowServer: false}), + lspRequestAndWaitUntilResponse('initialize', { + ...lspInitializeParams, + capabilities: { + ...lspInitializeParams.capabilities, + textDocument: { + ...lspInitializeParams.capabilities.textDocument, + codeAction: {}, + }, + }, + }).verifyAllLSPMessagesInStep( + ['initialize{"codeActionProvider":false}'], [...lspIgnoreStatusAndCancellation], ), ]), diff --git a/packages/flow-dev-tools/src/test/TestStep.js b/packages/flow-dev-tools/src/test/TestStep.js index 74a6cc0972f..c554c93ab76 100644 --- a/packages/flow-dev-tools/src/test/TestStep.js +++ b/packages/flow-dev-tools/src/test/TestStep.js @@ -318,6 +318,13 @@ export class TestStepFirstStage extends TestStepFirstOrSecondStage { completion: {}, hover: {}, definition: {}, + codeAction: { + codeActionLiteralSupport: { + codeActionKind: { + valueSet: ['quickfix'], + }, + }, + }, }, window: {status: {}, progress: {}, actionRequired: {}}, telemetry: {connectionStatus: {}}, diff --git a/src/hack_forked/utils/lsp/lsp_fmt.ml b/src/hack_forked/utils/lsp/lsp_fmt.ml index 79c5d0c6f56..aa790495510 100644 --- a/src/hack_forked/utils/lsp/lsp_fmt.ml +++ b/src/hack_forked/utils/lsp/lsp_fmt.ml @@ -913,6 +913,8 @@ let parse_initialize (params : json option) : Initialize.params = Jget.obj_opt json "codeActionLiteralSupport" |> parse_codeActionLiteralSupport; } and parse_codeActionLiteralSupport json = + Jget.obj_opt json "codeActionKind" |> parse_codeActionKind + and parse_codeActionKind json = Base.Option.( Jget.array_opt json "valueSet" >>= fun ls -> Some { codeAction_valueSet = parse_kinds ls }) and parse_window json = diff --git a/src/lsp/flowLsp.ml b/src/lsp/flowLsp.ml index eff2297a7ca..748eee8aa4c 100644 --- a/src/lsp/flowLsp.ml +++ b/src/lsp/flowLsp.ml @@ -471,43 +471,52 @@ let send_lsp_to_server (cenv : connected_env) (metadata : LspProt.metadata) (mes (************************************************************************) -let do_initialize flowconfig : Initialize.result = - let code_action_provider = Initialize.CodeActionBool (FlowConfig.autofix_exports flowconfig) in - Initialize. - { - server_capabilities = - { - textDocumentSync = - { - want_openClose = true; - want_change = IncrementalSync; - want_willSave = false; - want_willSaveWaitUntil = false; - want_didSave = Some { includeText = false }; - }; - hoverProvider = true; - completionProvider = - Some { resolveProvider = false; completion_triggerCharacters = ["."; " "] }; - signatureHelpProvider = Some { sighelp_triggerCharacters = ["("; ","] }; - definitionProvider = true; - typeDefinitionProvider = false; - referencesProvider = true; - documentHighlightProvider = true; - documentSymbolProvider = true; - workspaceSymbolProvider = false; - codeActionProvider = code_action_provider; - codeLensProvider = None; - documentFormattingProvider = false; - documentRangeFormattingProvider = false; - documentOnTypeFormattingProvider = None; - renameProvider = true; - documentLinkProvider = None; - executeCommandProvider = None; - implementationProvider = false; - typeCoverageProvider = true; - rageProvider = true; - }; - } +let do_initialize params : Initialize.result = + let open Initialize in + let codeActionProvider = + (* currently the only code actions we provide are quickfixes which use CodeAction literals *) + match params.client_capabilities.textDocument.codeAction.codeActionLiteralSupport with + | Some { codeAction_valueSet } + when List.exists ~f:(( = ) CodeActionKind.quickfix) codeAction_valueSet -> + CodeActionOptions { codeActionKinds = [CodeActionKind.quickfix] } + | Some _ + | None -> + CodeActionBool false + in + { + server_capabilities = + { + textDocumentSync = + { + want_openClose = true; + want_change = IncrementalSync; + want_willSave = false; + want_willSaveWaitUntil = false; + want_didSave = Some { includeText = false }; + }; + hoverProvider = true; + completionProvider = + Some { resolveProvider = false; completion_triggerCharacters = ["."; " "] }; + signatureHelpProvider = Some { sighelp_triggerCharacters = ["("; ","] }; + definitionProvider = true; + typeDefinitionProvider = false; + referencesProvider = true; + documentHighlightProvider = true; + documentSymbolProvider = true; + workspaceSymbolProvider = false; + codeActionProvider; + codeLensProvider = None; + documentFormattingProvider = false; + documentRangeFormattingProvider = false; + documentOnTypeFormattingProvider = None; + renameProvider = true; + documentLinkProvider = None; + executeCommandProvider = None; + implementationProvider = false; + typeCoverageProvider = true; + rageProvider = true; + }; + } let show_connected (env : connected_env) : state = (* report that we're connected to telemetry/connectionStatus *) @@ -1648,7 +1657,7 @@ and main_handle_unsafe flowconfig_name (state : state) (event : event) : | Ok () -> () | Error msg -> raise (Error.ServerErrorStart (msg, { Initialize.retry = false })) end; - let response = ResponseMessage (id, InitializeResult (do_initialize flowconfig)) in + let response = ResponseMessage (id, InitializeResult (do_initialize i_initialize_params)) in let json = Lsp_fmt.print_lsp response in to_stdout json; let env = { d_ienv; d_autostart = true; d_server_status = None } in