src/commands/getImportsCommand.ml (137 lines of code) (raw):

(* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) (***********************************************************************) (* flow get imports command *) (***********************************************************************) open CommandUtils let spec = { CommandSpec.name = "get-imports"; doc = "Get names of all modules imported by one or more given modules"; usage = Printf.sprintf "Usage: %s get-requirements [OPTION]... [FILE]...\n\nGet names of all modules imported by one or more given modules\n\nExample usage:\n\t%s get-imports FirstModule SecondModule\n" CommandUtils.exe_name CommandUtils.exe_name; args = CommandSpec.ArgSpec.( empty |> base_flags |> connect_and_json_flags |> root_flag |> strip_root_flag |> from_flag |> wait_for_recheck_flag |> anon "modules" (required (list_of string)) ); } let main base_flags option_values json pretty root strip_root wait_for_recheck modules () = let flowconfig_name = base_flags.Base_flags.flowconfig_name in let root = guess_root flowconfig_name root in let request = ServerProt.Request.GET_IMPORTS { module_names = modules; wait_for_recheck } in let (requirements_map, non_flow) = match connect_and_make_request flowconfig_name option_values root request with | ServerProt.Response.GET_IMPORTS response -> response | response -> failwith_bad_response ~request ~response in let requirements_map = SMap.fold begin fun module_name reqlocs map -> let requirements = Modulename.Map.fold (fun req loc assoc -> let req = match req with | Modulename.String s -> s | Modulename.Filename f -> let f = File_key.to_string f in if strip_root then Files.relative_path (Path.to_string root) f else f in (req, loc) :: assoc) reqlocs [] in SMap.add module_name requirements map end requirements_map SMap.empty in let strip_root = if strip_root then Some root else None in if json || pretty then Hh_json.( let json_non_flow = SSet.fold (fun module_name acc -> let json = JSON_Object [("not_flow", JSON_Bool true); ("requirements", JSON_Array [])] in (module_name, json) :: acc) non_flow [] in let json_imports = SMap.fold (fun module_name assoc acc -> let requirements = List.fold_left (fun acc (req, locs) -> Nel.fold_left (fun acc loc -> JSON_Object (("import", JSON_String req) :: ("loc", json_of_loc_with_offset ~strip_root loc) :: Errors.deprecated_json_props_of_loc ~strip_root loc ) :: acc) acc locs) [] assoc in let json = JSON_Object [("not_flow", JSON_Bool false); ("requirements", JSON_Array requirements)] in (module_name, json) :: acc) requirements_map [] in let json = JSON_Object (List.append json_non_flow json_imports) in print_json_endline ~pretty json ) else let print_imports module_name = if SMap.mem module_name requirements_map then ( let requirements = SMap.find module_name requirements_map in Printf.printf "Imports for module '%s':\n" module_name; List.iter (fun (req, locs) -> Nel.iter (fun loc -> let loc_str = range_string_of_loc ~strip_root loc in Printf.printf "\t%s@%s\n" req loc_str) locs) requirements ) else if SSet.mem module_name non_flow then Printf.printf "Cannot obtain imports for module '%s' because is not\ marked for processing by flow!\n" module_name else Printf.printf "Module '%s' could not be found!\n" module_name in List.iter print_imports modules; flush stdout let command = CommandSpec.command spec main