Skip to content

Commit

Permalink
Initialize as a codeActionProvider when the client supports quickfixes
Browse files Browse the repository at this point in the history
Summary:
Telling the LSP client that we're a codeActionProvider means that it'll ask us for codeActions when the user hovers over errors. This'll let us provide quickfixes corresponding to type errors; specifically, the "Did you mean?" type error.

The codeActions we'll provide (both the existing "autofix exports" actions and the "did you mean?" actions being added in D20003667) will be quickfix CodeAction literals, so we initialize as a provider of quickfixes iff the client supports quickfix CodeAction literals.

Fixes #8277

Reviewed By: nmote

Differential Revision: D19919160

fbshipit-source-id: 4b204227d6425cd7de217810bbe469662f2d37d8
  • Loading branch information
Vijay Ramamurthy authored and facebook-github-bot committed Feb 28, 2020
1 parent 7642a1b commit db6ab74
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 50 deletions.
10 changes: 0 additions & 10 deletions newtests/lsp/code-action-disabled/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
20 changes: 18 additions & 2 deletions newtests/lsp/code-action/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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],
),
]),
Expand Down
7 changes: 7 additions & 0 deletions packages/flow-dev-tools/src/test/TestStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,13 @@ export class TestStepFirstStage extends TestStepFirstOrSecondStage {
completion: {},
hover: {},
definition: {},
codeAction: {
codeActionLiteralSupport: {
codeActionKind: {
valueSet: ['quickfix'],
},
},
},
},
window: {status: {}, progress: {}, actionRequired: {}},
telemetry: {connectionStatus: {}},
Expand Down
2 changes: 2 additions & 0 deletions src/hack_forked/utils/lsp/lsp_fmt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
85 changes: 47 additions & 38 deletions src/lsp/flowLsp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 *)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit db6ab74

Please sign in to comment.