diff --git a/src/server/command_handler/commandHandler.ml b/src/server/command_handler/commandHandler.ml index 1ce7b8fe91c..be8b9797834 100644 --- a/src/server/command_handler/commandHandler.ml +++ b/src/server/command_handler/commandHandler.ml @@ -1715,6 +1715,62 @@ let handle_persistent_document_highlight Lwt.return ((), LspProt.LspFromServer (Some response), metadata) | Error reason -> mk_lsp_error_response ~ret:() ~id:(Some id) ~reason metadata +(* This tries to simulate the logic from elsewhere which determines whether we would report + * errors for a given file. The criteria are + * + * 1) The file must be either implicitly included (be in the same dir structure as .flowconfig) + * or explicitly included + * 2) The file must not be ignored + * 3) The file path must be a Flow file (e.g foo.js and not foo.php or foo/) + * 4) The file must either have `// @flow` or all=true must be set in the .flowconfig or CLI + *) +let check_that_we_care_about_this_file = + let check_file_not_ignored ~file_options ~env ~file_path () = + if Files.wanted ~options:file_options env.ServerEnv.libs file_path then + Ok () + else + Error "File is ignored" + in + let check_file_included ~options ~file_options ~file_path () = + let file_is_implicitly_included = + let root_str = spf "%s%s" (Path.to_string (Options.root options)) Filename.dir_sep in + String_utils.string_starts_with file_path root_str + in + if file_is_implicitly_included then + Ok () + else if Files.is_included file_options file_path then + Ok () + else + Error "File is not implicitly or explicitly included" + in + let check_is_flow_file ~file_options ~file_path () = + if Files.is_flow_file ~options:file_options file_path then + Ok () + else + Error "File is not a Flow file" + in + let check_flow_pragma ~options ~content ~file_path () = + if Options.all options then + Ok () + else + let (_, docblock) = + Parsing_service_js.( + parse_docblock docblock_max_tokens (File_key.SourceFile file_path) content) + in + if Docblock.is_flow docblock then + Ok () + else + Error "File is missing @flow pragma and `all` is not set to `true`" + in + fun ~options ~env ~file_path ~content -> + let file_path = Files.imaginary_realpath file_path in + let file_options = Options.file_options options in + Ok () + >>= check_file_not_ignored ~file_options ~env ~file_path + >>= check_file_included ~options ~file_options ~file_path + >>= check_is_flow_file ~file_options ~file_path + >>= check_flow_pragma ~options ~content ~file_path + let handle_persistent_coverage ~options ~id ~params ~file ~metadata ~client ~profiling ~env = let textDocument = params.TypeCoverage.textDocument in let file = @@ -1726,20 +1782,23 @@ let handle_persistent_coverage ~options ~id ~params ~file ~metadata ~client ~pro Flow_lsp_conversions.lsp_DocumentIdentifier_to_flow textDocument ~client in (* if it isn't a flow file (i.e. lacks a @flow directive) then we won't do anything *) - let fkey = File_key.SourceFile (File_input.filename_of_file_input file) in let content = File_input.content_of_file_input file in + let file_path = File_input.filename_of_file_input file in let is_flow = match content with | Ok content -> - let (_, docblock) = Parsing_service_js.(parse_docblock docblock_max_tokens fkey content) in - Docblock.is_flow docblock + begin + match check_that_we_care_about_this_file ~options ~env ~file_path ~content with + | Ok () -> true + | Error _ -> false + end | Error _ -> false in let%lwt result = if is_flow then - let force = false in - let type_contents_cache = Some (Persistent_connection.type_contents_cache client) in (* 'true' makes it report "unknown" for all exprs in non-flow files *) + let force = Options.all options in + let type_contents_cache = Some (Persistent_connection.type_contents_cache client) in coverage ~options ~env ~profiling ~type_contents_cache ~force ~trust:false file else Lwt.return (Ok []) @@ -1955,62 +2014,6 @@ let handle_persistent_unsupported ?id ~unhandled ~metadata ~client:_ ~profiling: let reason = Printf.sprintf "not implemented: %s" (Lsp_fmt.message_name_to_string unhandled) in mk_lsp_error_response ~ret:() ~id ~reason metadata -(* This tries to simulate the logic from elsewhere which determines whether we would report - * errors for a given file. The criteria are - * - * 1) The file must be either implicitly included (be in the same dir structure as .flowconfig) - * or explicitly included - * 2) The file must not be ignored - * 3) The file path must be a Flow file (e.g foo.js and not foo.php or foo/) - * 4) The file must either have `// @flow` or all=true must be set in the .flowconfig or CLI - *) -let check_that_we_care_about_this_file = - let check_file_not_ignored ~file_options ~env ~file_path () = - if Files.wanted ~options:file_options env.ServerEnv.libs file_path then - Ok () - else - Error "File is ignored" - in - let check_file_included ~options ~file_options ~file_path () = - let file_is_implicitly_included = - let root_str = spf "%s%s" (Path.to_string (Options.root options)) Filename.dir_sep in - String_utils.string_starts_with file_path root_str - in - if file_is_implicitly_included then - Ok () - else if Files.is_included file_options file_path then - Ok () - else - Error "File is not implicitly or explicitly included" - in - let check_is_flow_file ~file_options ~file_path () = - if Files.is_flow_file ~options:file_options file_path then - Ok () - else - Error "File is not a Flow file" - in - let check_flow_pragma ~options ~content ~file_path () = - if Options.all options then - Ok () - else - let (_, docblock) = - Parsing_service_js.( - parse_docblock docblock_max_tokens (File_key.SourceFile file_path) content) - in - if Docblock.is_flow docblock then - Ok () - else - Error "File is missing @flow pragma and `all` is not set to `true`" - in - fun ~options ~env ~file_path ~content -> - let file_path = Files.imaginary_realpath file_path in - let file_options = Options.file_options options in - Ok () - >>= check_file_not_ignored ~file_options ~env ~file_path - >>= check_file_included ~options ~file_options ~file_path - >>= check_is_flow_file ~file_options ~file_path - >>= check_flow_pragma ~options ~content ~file_path - (* What should we do if we get multiple requests for the same URI? Each request wants the most * up-to-date live errors, so if we have 10 pending requests then we would want to send the same * response to each. And we could do that, but it might have some weird side effects: