From ba5c77b4d9ccfbe014bf529708929b6b6d5e15cb Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Mon, 29 Apr 2024 13:04:54 -0400 Subject: [PATCH 01/11] Revert "First stab at minimal `-H` support. Untested." This reverts commit a2fd8acdf62fdbd31a66bdb816c0fe98d889fce2. --- src/analysis/locate.ml | 8 +- src/frontend/ocamlmerlin/old/old_command.ml | 4 +- src/frontend/query_commands.ml | 8 +- src/kernel/mconfig.ml | 79 +++++-------------- src/kernel/mconfig.mli | 9 +-- src/kernel/mconfig_dot.ml | 19 +---- src/kernel/mconfig_dot.mli | 6 +- src/kernel/mocaml.ml | 4 +- src/kernel/mppx.ml | 4 +- .../config/dot-merlin-reader/quoting.t | 5 +- 10 files changed, 37 insertions(+), 109 deletions(-) diff --git a/src/analysis/locate.ml b/src/analysis/locate.ml index 45e7d05f0..3f2e83ae1 100644 --- a/src/analysis/locate.ml +++ b/src/analysis/locate.ml @@ -423,12 +423,8 @@ module Utils = struct find_file_with_path ~config ?with_fallback file @@ match file with | ML _ | MLI _ | MLL _ -> Mconfig.source_path config - | CMT _ | CMTI _ -> - let Mconfig.{ visible; hidden } = Mconfig.build_path config in - visible @ hidden - | CMS _ | CMSI _ -> - let Mconfig.{ visible; hidden } = Mconfig.build_path config in - visible @ hidden + | CMT _ | CMTI _ -> Mconfig.build_path config + | CMS _ | CMSI _ -> Mconfig.build_path config end let move_to filename artifact = diff --git a/src/frontend/ocamlmerlin/old/old_command.ml b/src/frontend/ocamlmerlin/old/old_command.ml index e8f40423f..ca0751687 100644 --- a/src/frontend/ocamlmerlin/old/old_command.ml +++ b/src/frontend/ocamlmerlin/old/old_command.ml @@ -59,9 +59,7 @@ let customize config = let merlin = config.merlin in let merlin = match var with - | `Build -> {merlin with build_path = - { visible = f merlin.build_path.visible; - hidden = f merlin.build_path.hidden }} + | `Build -> {merlin with build_path = f merlin.build_path} | `Source -> {merlin with source_path = f merlin.source_path} in {config with merlin} diff --git a/src/frontend/query_commands.ml b/src/frontend/query_commands.ml index 70b500b58..b7c73f5e3 100644 --- a/src/frontend/query_commands.ml +++ b/src/frontend/query_commands.ml @@ -181,8 +181,7 @@ let dump pipeline = function | [`String "paths"] -> let paths = Mconfig.build_path (Mpipeline.final_config pipeline) in - `Assoc [ "visible", `List (List.map paths.visible ~f:(fun s -> `String s)); - "hidden", `List (List.map paths.hidden ~f:(fun s -> `String s)) ] + `List (List.map paths ~f:(fun s -> `String s)) | [`String "typedtree"] -> let tree = @@ -798,8 +797,7 @@ let dispatch pipeline (type a) : a Query_protocol.t -> a = try find_in_path_uncap (Mconfig.source_path config) x with Not_found -> try - let Mconfig.{visible; hidden} = Mconfig.build_path config in - find_in_path_uncap (visible @ hidden) x + find_in_path_uncap (Mconfig.build_path config) x with Not_found -> aux xs in @@ -827,7 +825,7 @@ let dispatch pipeline (type a) : a Query_protocol.t -> a = | Path_list `Build -> let config = Mpipeline.final_config pipeline in - Mconfig.(config.merlin.build_path.visible @ config.merlin.build_path.hidden) + Mconfig.(config.merlin.build_path) | Path_list `Source -> let config = Mpipeline.final_config pipeline in diff --git a/src/kernel/mconfig.ml b/src/kernel/mconfig.ml index 1df121db1..64f8a9972 100644 --- a/src/kernel/mconfig.ml +++ b/src/kernel/mconfig.ml @@ -6,7 +6,6 @@ let {Logger. log} = Logger.for_section "Mconfig" type ocaml = { include_dirs : string list; - hidden_include_dirs : string list; no_std_include : bool; unsafe : bool; classic : bool; @@ -34,7 +33,6 @@ let dump_warnings st = let dump_ocaml x = `Assoc [ "include_dirs" , `List (List.map ~f:Json.string x.include_dirs); - "hidden_include_dirs" , `List (List.map ~f:Json.string x.hidden_include_dirs); "no_std_include" , `Bool x.no_std_include; "unsafe" , `Bool x.unsafe; "classic" , `Bool x.classic; @@ -73,12 +71,8 @@ let marg_commandline f = (** {1 Merlin high-level settings} *) -type include_paths = - { visible : string list; - hidden : string list } - type merlin = { - build_path : include_paths; + build_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -109,11 +103,7 @@ let dump_merlin x = dump_with_workdir (Json.list Json.string) flags in `Assoc [ - "build_path" , - `Assoc [ - "visible", `List (List.map ~f:Json.string x.build_path.visible); - "hidden", `List (List.map ~f:Json.string x.build_path.hidden) - ]; + "build_path" , `List (List.map ~f:Json.string x.build_path); "source_path" , `List (List.map ~f:Json.string x.source_path); "cmi_path" , `List (List.map ~f:Json.string x.cmi_path); "cmt_path" , `List (List.map ~f:Json.string x.cmt_path); @@ -242,11 +232,6 @@ let rec normalize t = ) else normalize (normalize_step t) -let merge_build_paths - (dot_bp : Mconfig_dot.include_paths) (merlin_bp : include_paths) = - { visible = dot_bp.visible @ merlin_bp.visible; - hidden = dot_bp.hidden @ merlin_bp.hidden } - let get_external_config path t = let path = Misc.canonicalize_filename path in let directory = Filename.dirname path in @@ -257,7 +242,7 @@ let get_external_config path t = let merlin = t.merlin in let merlin = { merlin with - build_path = merge_build_paths dot.build_path merlin.build_path; + build_path = dot.build_path @ merlin.build_path; source_path = dot.source_path @ merlin.source_path; cmi_path = dot.cmi_path @ merlin.cmi_path; cmt_path = dot.cmt_path @ merlin.cmt_path; @@ -280,13 +265,9 @@ let merlin_flags = [ ( "-build-path", marg_path (fun dir merlin -> - let build_path = - { merlin.build_path with visible = dir :: merlin.build_path.visible } - in - {merlin with build_path = build_path}), + {merlin with build_path = dir :: merlin.build_path}), " Add to merlin build path" ); - (* CR ccasinghino: Do we want a similar flag for hidden includes? *) ( "-source-path", marg_path (fun dir merlin -> @@ -590,12 +571,6 @@ let ocaml_flags = [ {ocaml with include_dirs = dir :: ocaml.include_dirs}), " Add to the list of include directories" ); - ( - "-H", - marg_path (fun dir ocaml -> - {ocaml with hidden_include_dirs = dir :: ocaml.hidden_include_dirs}), - " Add to the list of hidden include directories" - ); ( "-nostdlib", Marg.unit (fun ocaml -> {ocaml with no_std_include = true}), @@ -737,7 +712,6 @@ let ocaml_flags = [ let initial = { ocaml = { include_dirs = []; - hidden_include_dirs = []; no_std_include = false; unsafe = false; classic = false; @@ -757,7 +731,7 @@ let initial = { as_parameter = false; }; merlin = { - build_path = {visible = []; hidden = []}; + build_path = []; source_path = []; cmi_path = []; cmt_path = []; @@ -875,45 +849,34 @@ let source_path config = |> List.filter_dup let build_path config = ( - let visible = + let dirs = match config.ocaml.threads with | `None -> config.ocaml.include_dirs | `Threads -> "+threads" :: config.ocaml.include_dirs | `Vmthreads -> "+vmthreads" :: config.ocaml.include_dirs in - let visible = + let dirs = config.merlin.cmi_path @ - config.merlin.build_path.visible @ - visible - in - let hidden = - config.merlin.build_path.hidden @ - config.ocaml.hidden_include_dirs + config.merlin.build_path @ + dirs in let stdlib = stdlib config in - let visible = - List.map ~f:(Misc.expand_directory stdlib) visible - in - let hidden = - List.rev_map ~f:(Misc.expand_directory stdlib) hidden + let exp_dirs = + List.map ~f:(Misc.expand_directory stdlib) dirs in let stdlib = if config.ocaml.no_std_include then [] else [stdlib] in - let visible = List.rev_append visible stdlib in - let visible = + let dirs = List.rev_append exp_dirs stdlib in + let result = if config.merlin.exclude_query_dir - then visible - else config.query.directory :: visible + then dirs + else config.query.directory :: dirs in - let visible' = List.filter_dup visible in - let hidden' = List.filter_dup hidden in + let result' = List.filter_dup result in log ~title:"build_path" "%d items in path, %d after deduplication" - (List.length visible) (List.length visible'); - log ~title:"hidden_build_path" "%d items in path, %d after deduplication" - (List.length hidden) (List.length hidden'); - { visible = visible'; hidden = hidden' } + (List.length result) (List.length result'); + result' ) -(* CR -H: What is `cmt_path` and does it need to consider hidden_includes? *) let cmt_path config = ( let dirs = match config.ocaml.threads with @@ -923,7 +886,7 @@ let cmt_path config = ( in let dirs = config.merlin.cmt_path @ - config.merlin.build_path.visible @ + config.merlin.build_path @ dirs in let stdlib = stdlib config in @@ -935,9 +898,7 @@ let cmt_path config = ( ) let global_modules ?(include_current=false) config = ( - (* CR -H: I took a look at a couple uses of `global_modules` and the `.visible` below - seems fine, but I'm not confident *) - let modules = Misc.modules_in_path ~ext:".cmi" (build_path config).visible in + let modules = Misc.modules_in_path ~ext:".cmi" (build_path config) in if include_current then modules else match config.query.filename with | "" -> modules diff --git a/src/kernel/mconfig.mli b/src/kernel/mconfig.mli index 37276b631..3e6fa15ab 100644 --- a/src/kernel/mconfig.mli +++ b/src/kernel/mconfig.mli @@ -4,7 +4,6 @@ open Std type ocaml = { include_dirs : string list; - hidden_include_dirs : string list; no_std_include : bool; unsafe : bool; classic : bool; @@ -29,12 +28,8 @@ val dump_ocaml : ocaml -> json (** {1 Merlin high-level settings} *) -type include_paths = - { visible : string list; - hidden : string list } - type merlin = { - build_path : include_paths; + build_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -113,7 +108,7 @@ val document_arguments : out_channel -> unit val source_path : t -> string list -val build_path : t -> include_paths +val build_path : t -> string list val cmt_path : t -> string list diff --git a/src/kernel/mconfig_dot.ml b/src/kernel/mconfig_dot.ml index 4fcec16ce..13ad8eba9 100644 --- a/src/kernel/mconfig_dot.ml +++ b/src/kernel/mconfig_dot.ml @@ -32,12 +32,8 @@ let {Logger. log} = Logger.for_section "Mconfig_dot" type directive = Merlin_dot_protocol.directive -type include_paths = - { visible : string list; - hidden : string list } - type config = { - build_path : include_paths; + build_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -51,7 +47,7 @@ type config = { } let empty_config = { - build_path = {visible = []; hidden = []}; + build_path = []; source_path = []; cmi_path = []; cmt_path = []; @@ -237,13 +233,7 @@ end let prepend_config ~dir:cwd configurator (directives : directive list) config = List.fold_left ~init:(config, []) ~f:(fun (config, errors) -> function - | `B path -> - (* CR -H: Probably some way to put hidden includes in merlin files is needed - eventually. *) - let build_path = { config.build_path with - visible = path :: config.build_path.visible } - in - {config with build_path = build_path}, errors + | `B path -> {config with build_path = path :: config.build_path}, errors | `S path -> {config with source_path = path :: config.source_path}, errors | `CMI path -> {config with cmi_path = path :: config.cmi_path}, errors | `CMT path -> {config with cmt_path = path :: config.cmt_path}, errors @@ -276,8 +266,7 @@ let prepend_config ~dir:cwd configurator (directives : directive list) config = let postprocess_config config = let clean list = List.rev (List.filter_dup list) in { - build_path = { visible = clean config.build_path.visible; - hidden = clean config.build_path.hidden }; + build_path = clean config.build_path; source_path = clean config.source_path; cmi_path = clean config.cmi_path; cmt_path = clean config.cmt_path; diff --git a/src/kernel/mconfig_dot.mli b/src/kernel/mconfig_dot.mli index 3b6c3dcdc..7e1ad9a1e 100644 --- a/src/kernel/mconfig_dot.mli +++ b/src/kernel/mconfig_dot.mli @@ -28,12 +28,8 @@ open Std -type include_paths = - { visible : string list; - hidden : string list } - type config = { - build_path : include_paths; + build_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; diff --git a/src/kernel/mocaml.ml b/src/kernel/mocaml.ml index a0019349f..971c951db 100644 --- a/src/kernel/mocaml.ml +++ b/src/kernel/mocaml.ml @@ -49,8 +49,8 @@ let setup_reader_config config = ( let setup_typer_config config = ( setup_reader_config config; - let Mconfig.{ visible; hidden } = Mconfig.build_path config in - Load_path.(init ~auto_include:no_auto_include ~visible ~hidden); + (* CR 5.1.1minus-4: is this right? *) + Load_path.(init ~auto_include:no_auto_include ~visible:(Mconfig.build_path config) ~hidden:[]); ) (** Switchable implementation of Oprint *) diff --git a/src/kernel/mppx.ml b/src/kernel/mppx.ml index 78a09737c..4e1fea600 100644 --- a/src/kernel/mppx.ml +++ b/src/kernel/mppx.ml @@ -2,7 +2,6 @@ open Mconfig let {Logger. log} = Logger.for_section "Mppx" -(* CR -H: do we need to do something for hidden includes here? *) let with_include_dir path f = let saved = !Clflags.include_dirs in let restore () = Clflags.include_dirs := saved in @@ -20,11 +19,10 @@ let with_include_dir path f = restore (); result -(* CR -H: do we need to do something for hidden includes here? *) let rewrite parsetree cfg = let ppx = cfg.ocaml.ppx in (* add include path attribute to the parsetree *) - with_include_dir (Mconfig.build_path cfg).visible @@ fun () -> + with_include_dir (Mconfig.build_path cfg) @@ fun () -> match Pparse.apply_rewriters ~restore:false ~ppx ~tool_name:"merlin" parsetree with diff --git a/tests/test-dirs/config/dot-merlin-reader/quoting.t b/tests/test-dirs/config/dot-merlin-reader/quoting.t index d9bf8896c..e99dfaeb7 100644 --- a/tests/test-dirs/config/dot-merlin-reader/quoting.t +++ b/tests/test-dirs/config/dot-merlin-reader/quoting.t @@ -12,10 +12,7 @@ $ echo | $MERLIN single dump-configuration -filename test.ml 2> /dev/null | jq '.value.merlin' { - "build_path": { - "visible": [], - "hidden": [] - }, + "build_path": [], "source_path": [], "cmi_path": [], "cmt_path": [], From f78fdfad7c7dc46c9056cc0f3be9d7cda3a31aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulysse=20G=C3=A9rard?= Date: Mon, 5 Feb 2024 18:51:54 +0100 Subject: [PATCH 02/11] upgrade: support for hidden dependencies --- src/dot-merlin/dot_merlin_reader.ml | 5 ++++- src/dot-protocol/merlin_dot_protocol.ml | 4 +++- src/dot-protocol/merlin_dot_protocol.mli | 2 +- src/kernel/mconfig.ml | 15 +++++++++++++++ src/kernel/mconfig.mli | 4 ++++ src/kernel/mconfig_dot.ml | 4 ++++ src/kernel/mconfig_dot.mli | 1 + src/kernel/mocaml.ml | 5 +++-- src/kernel/mtyper.ml | 2 +- 9 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/dot-merlin/dot_merlin_reader.ml b/src/dot-merlin/dot_merlin_reader.ml index e3a1aaba0..e768d6cac 100644 --- a/src/dot-merlin/dot_merlin_reader.ml +++ b/src/dot-merlin/dot_merlin_reader.ml @@ -72,6 +72,8 @@ module Cache = File_cache.Make (struct else if String.is_prefixed ~by:"B " line then tell (`B (String.drop 2 line)) + else if String.is_prefixed ~by:"H " line then + tell (`S (String.drop 2 line)) else if String.is_prefixed ~by:"S " line then tell (`S (String.drop 2 line)) else if String.is_prefixed ~by:"SRC " line then @@ -324,7 +326,7 @@ let empty_config = { let prepend_config ~cwd ~cfg = List.fold_left ~init:cfg ~f:(fun cfg (d : Merlin_dot_protocol.Directive.Raw.t) -> match d with - | `B _ | `S _ | `CMI _ | `CMT _ as directive -> + | `B _ | `H _ | `S _ | `CMI _ | `CMT _ as directive -> { cfg with to_canonicalize = (cwd, directive) :: cfg.to_canonicalize } | `EXT _ | `SUFFIX _ | `FLG _ | `READER _ | (`EXCLUDE_QUERY_DIR | `USE_PPX_CACHE | `UNKNOWN_TAG _) as directive -> @@ -452,6 +454,7 @@ let postprocess cfg = let dirs = match directive with | `B path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `B p) + | `H path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `H p) | `S path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `S p) | `CMI path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `CMI p) | `CMT path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `CMT p) diff --git a/src/dot-protocol/merlin_dot_protocol.ml b/src/dot-protocol/merlin_dot_protocol.ml index 97648d931..ba7ea25d0 100644 --- a/src/dot-protocol/merlin_dot_protocol.ml +++ b/src/dot-protocol/merlin_dot_protocol.ml @@ -31,7 +31,7 @@ open Merlin_utils.Std.Result module Directive = struct type include_path = - [ `B of string | `S of string | `CMI of string | `CMT of string ] + [ `B of string | `H of string | `S of string | `CMI of string | `CMT of string ] type no_processing_required = [ `EXT of string list @@ -82,6 +82,7 @@ module Sexp = struct begin match tag with | "S" -> `S value | "B" -> `B value + | "H" -> `H value | "CMI" -> `CMI value | "CMT" -> `CMT value | "STDLIB" -> `STDLIB value @@ -111,6 +112,7 @@ module Sexp = struct let single s = [ Atom s ] in match t with | `B s -> ("B", single s) + | `H s -> ("H", single s) | `S s -> ("S", single s) | `CMI s -> ("CMI", single s) | `CMT s -> ("CMT", single s) diff --git a/src/dot-protocol/merlin_dot_protocol.mli b/src/dot-protocol/merlin_dot_protocol.mli index c238b813a..2acff7bbf 100644 --- a/src/dot-protocol/merlin_dot_protocol.mli +++ b/src/dot-protocol/merlin_dot_protocol.mli @@ -43,7 +43,7 @@ really do not want to load them. *) module Directive : sig type include_path = - [ `B of string | `S of string | `CMI of string | `CMT of string ] + [ `B of string | `H of string| `S of string | `CMI of string | `CMT of string ] type no_processing_required = [ `EXT of string list diff --git a/src/kernel/mconfig.ml b/src/kernel/mconfig.ml index 64f8a9972..e78f99825 100644 --- a/src/kernel/mconfig.ml +++ b/src/kernel/mconfig.ml @@ -6,6 +6,7 @@ let {Logger. log} = Logger.for_section "Mconfig" type ocaml = { include_dirs : string list; + hidden_dirs : string list; no_std_include : bool; unsafe : bool; classic : bool; @@ -33,6 +34,7 @@ let dump_warnings st = let dump_ocaml x = `Assoc [ "include_dirs" , `List (List.map ~f:Json.string x.include_dirs); + "hidden_dirs" , `List (List.map ~f:Json.string x.hidden_dirs); "no_std_include" , `Bool x.no_std_include; "unsafe" , `Bool x.unsafe; "classic" , `Bool x.classic; @@ -73,6 +75,7 @@ let marg_commandline f = type merlin = { build_path : string list; + hidden_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -571,6 +574,13 @@ let ocaml_flags = [ {ocaml with include_dirs = dir :: ocaml.include_dirs}), " Add to the list of include directories" ); + ( + "-H", + marg_path (fun dir ocaml -> + {ocaml with hidden_dirs = dir :: ocaml.hidden_dirs}), + " Add to the list of \"hidden\" include directories\n\ + \ (Like -I, but the program can not directly reference these dependencies)" + ); ( "-nostdlib", Marg.unit (fun ocaml -> {ocaml with no_std_include = true}), @@ -712,6 +722,7 @@ let ocaml_flags = [ let initial = { ocaml = { include_dirs = []; + hidden_dirs = []; no_std_include = false; unsafe = false; classic = false; @@ -732,6 +743,7 @@ let initial = { }; merlin = { build_path = []; + hidden_path = []; source_path = []; cmi_path = []; cmt_path = []; @@ -877,6 +889,9 @@ let build_path config = ( result' ) +let hidden_path config = + config.merlin.hidden_path @ config.ocaml.hidden_dirs + let cmt_path config = ( let dirs = match config.ocaml.threads with diff --git a/src/kernel/mconfig.mli b/src/kernel/mconfig.mli index 3e6fa15ab..c529f5e48 100644 --- a/src/kernel/mconfig.mli +++ b/src/kernel/mconfig.mli @@ -4,6 +4,7 @@ open Std type ocaml = { include_dirs : string list; + hidden_dirs : string list; no_std_include : bool; unsafe : bool; classic : bool; @@ -30,6 +31,7 @@ val dump_ocaml : ocaml -> json type merlin = { build_path : string list; + hidden_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -110,6 +112,8 @@ val source_path : t -> string list val build_path : t -> string list +val hidden_path : t -> string list + val cmt_path : t -> string list val global_modules : ?include_current:bool -> t -> string list diff --git a/src/kernel/mconfig_dot.ml b/src/kernel/mconfig_dot.ml index 13ad8eba9..a4d7ff1a9 100644 --- a/src/kernel/mconfig_dot.ml +++ b/src/kernel/mconfig_dot.ml @@ -34,6 +34,7 @@ type directive = Merlin_dot_protocol.directive type config = { build_path : string list; + hidden_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; @@ -48,6 +49,7 @@ type config = { let empty_config = { build_path = []; + hidden_path = []; source_path = []; cmi_path = []; cmt_path = []; @@ -234,6 +236,7 @@ let prepend_config ~dir:cwd configurator (directives : directive list) config = List.fold_left ~init:(config, []) ~f:(fun (config, errors) -> function | `B path -> {config with build_path = path :: config.build_path}, errors + | `H path -> {config with hidden_path = path :: config.hidden_path}, errors | `S path -> {config with source_path = path :: config.source_path}, errors | `CMI path -> {config with cmi_path = path :: config.cmi_path}, errors | `CMT path -> {config with cmt_path = path :: config.cmt_path}, errors @@ -267,6 +270,7 @@ let postprocess_config config = let clean list = List.rev (List.filter_dup list) in { build_path = clean config.build_path; + hidden_path = clean config.hidden_path; source_path = clean config.source_path; cmi_path = clean config.cmi_path; cmt_path = clean config.cmt_path; diff --git a/src/kernel/mconfig_dot.mli b/src/kernel/mconfig_dot.mli index 7e1ad9a1e..60636e37e 100644 --- a/src/kernel/mconfig_dot.mli +++ b/src/kernel/mconfig_dot.mli @@ -30,6 +30,7 @@ open Std type config = { build_path : string list; + hidden_path : string list; source_path : string list; cmi_path : string list; cmt_path : string list; diff --git a/src/kernel/mocaml.ml b/src/kernel/mocaml.ml index 971c951db..a843757df 100644 --- a/src/kernel/mocaml.ml +++ b/src/kernel/mocaml.ml @@ -49,8 +49,9 @@ let setup_reader_config config = ( let setup_typer_config config = ( setup_reader_config config; - (* CR 5.1.1minus-4: is this right? *) - Load_path.(init ~auto_include:no_auto_include ~visible:(Mconfig.build_path config) ~hidden:[]); + let visible = Mconfig.build_path config in + let hidden = Mconfig.hidden_path config in + Load_path.(init ~auto_include:no_auto_include ~visible ~hidden); ) (** Switchable implementation of Oprint *) diff --git a/src/kernel/mtyper.ml b/src/kernel/mtyper.ml index 14e48e4fe..ab8623858 100644 --- a/src/kernel/mtyper.ml +++ b/src/kernel/mtyper.ml @@ -150,7 +150,7 @@ let run config parsetree = if not (Env.check_state_consistency ()) then ( (* Resetting the local store will clear the load_path cache. Save it now, reset the store and then restore the path. *) - let { visible; hidden } : Load_path.paths = Load_path.get_paths () in + let { Load_path.visible; hidden } = Load_path.get_paths () in Mocaml.flush_caches (); Local_store.reset (); Load_path.reset (); From bba99fe30a315b2e4200f6f8c133e45c8b5eb096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulysse=20G=C3=A9rard?= Date: Fri, 26 Apr 2024 16:39:24 +0200 Subject: [PATCH 03/11] hidden_path: use distinct source and build paths --- src/dot-merlin/dot_merlin_reader.ml | 5 ++-- src/dot-protocol/merlin_dot_protocol.ml | 13 +++++++--- src/dot-protocol/merlin_dot_protocol.mli | 7 ++++- src/kernel/mconfig.ml | 26 ++++++++++++++++--- src/kernel/mconfig.mli | 5 ++-- src/kernel/mconfig_dot.ml | 12 ++++++--- src/kernel/mconfig_dot.mli | 3 ++- src/kernel/mocaml.ml | 2 +- .../config/dot-merlin-reader/quoting.t | 2 ++ 9 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/dot-merlin/dot_merlin_reader.ml b/src/dot-merlin/dot_merlin_reader.ml index e768d6cac..fa8401dd3 100644 --- a/src/dot-merlin/dot_merlin_reader.ml +++ b/src/dot-merlin/dot_merlin_reader.ml @@ -326,7 +326,7 @@ let empty_config = { let prepend_config ~cwd ~cfg = List.fold_left ~init:cfg ~f:(fun cfg (d : Merlin_dot_protocol.Directive.Raw.t) -> match d with - | `B _ | `H _ | `S _ | `CMI _ | `CMT _ as directive -> + | `B _ | `S _ | `BH _ | `SH _ | `CMI _ | `CMT _ as directive -> { cfg with to_canonicalize = (cwd, directive) :: cfg.to_canonicalize } | `EXT _ | `SUFFIX _ | `FLG _ | `READER _ | (`EXCLUDE_QUERY_DIR | `USE_PPX_CACHE | `UNKNOWN_TAG _) as directive -> @@ -454,8 +454,9 @@ let postprocess cfg = let dirs = match directive with | `B path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `B p) - | `H path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `H p) | `S path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `S p) + | `BH path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `BH p) + | `SH path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `SH p) | `CMI path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `CMI p) | `CMT path -> List.map (expand ~stdlib dir path) ~f:(fun p -> `CMT p) in diff --git a/src/dot-protocol/merlin_dot_protocol.ml b/src/dot-protocol/merlin_dot_protocol.ml index ba7ea25d0..6798632b6 100644 --- a/src/dot-protocol/merlin_dot_protocol.ml +++ b/src/dot-protocol/merlin_dot_protocol.ml @@ -31,7 +31,12 @@ open Merlin_utils.Std.Result module Directive = struct type include_path = - [ `B of string | `H of string | `S of string | `CMI of string | `CMT of string ] + [ `B of string + | `S of string + | `BH of string + | `SH of string + | `CMI of string + | `CMT of string ] type no_processing_required = [ `EXT of string list @@ -82,7 +87,8 @@ module Sexp = struct begin match tag with | "S" -> `S value | "B" -> `B value - | "H" -> `H value + | "SH" -> `SH value + | "BH" -> `BH value | "CMI" -> `CMI value | "CMT" -> `CMT value | "STDLIB" -> `STDLIB value @@ -112,8 +118,9 @@ module Sexp = struct let single s = [ Atom s ] in match t with | `B s -> ("B", single s) - | `H s -> ("H", single s) | `S s -> ("S", single s) + | `BH s -> ("BH", single s) + | `SH s -> ("SH", single s) | `CMI s -> ("CMI", single s) | `CMT s -> ("CMT", single s) | `EXT ss -> ("EXT", [ List (atoms_of_strings ss) ]) diff --git a/src/dot-protocol/merlin_dot_protocol.mli b/src/dot-protocol/merlin_dot_protocol.mli index 2acff7bbf..96e34972d 100644 --- a/src/dot-protocol/merlin_dot_protocol.mli +++ b/src/dot-protocol/merlin_dot_protocol.mli @@ -43,7 +43,12 @@ really do not want to load them. *) module Directive : sig type include_path = - [ `B of string | `H of string| `S of string | `CMI of string | `CMT of string ] + [ `B of string + | `S of string + | `BH of string + | `SH of string + | `CMI of string + | `CMT of string ] type no_processing_required = [ `EXT of string list diff --git a/src/kernel/mconfig.ml b/src/kernel/mconfig.ml index e78f99825..846f122ad 100644 --- a/src/kernel/mconfig.ml +++ b/src/kernel/mconfig.ml @@ -75,8 +75,9 @@ let marg_commandline f = type merlin = { build_path : string list; - hidden_path : string list; source_path : string list; + hidden_build_path : string list; + hidden_source_path : string list; cmi_path : string list; cmt_path : string list; extensions : string list; @@ -108,6 +109,8 @@ let dump_merlin x = `Assoc [ "build_path" , `List (List.map ~f:Json.string x.build_path); "source_path" , `List (List.map ~f:Json.string x.source_path); + "hidden_build_path" , `List (List.map ~f:Json.string x.hidden_build_path); + "hidden_source_path", `List (List.map ~f:Json.string x.hidden_source_path); "cmi_path" , `List (List.map ~f:Json.string x.cmi_path); "cmt_path" , `List (List.map ~f:Json.string x.cmt_path); "flags_applied", `List (List.map ~f:dump_flag_list x.flags_applied); @@ -247,6 +250,8 @@ let get_external_config path t = merlin with build_path = dot.build_path @ merlin.build_path; source_path = dot.source_path @ merlin.source_path; + hidden_build_path = dot.hidden_build_path @ merlin.hidden_build_path; + hidden_source_path = dot.hidden_source_path @ merlin.hidden_source_path; cmi_path = dot.cmi_path @ merlin.cmi_path; cmt_path = dot.cmt_path @ merlin.cmt_path; exclude_query_dir = dot.exclude_query_dir || merlin.exclude_query_dir; @@ -277,6 +282,18 @@ let merlin_flags = [ {merlin with source_path = dir :: merlin.source_path}), " Add to merlin source path" ); + ( + "-hidden-build-path", + marg_path (fun dir merlin -> + {merlin with hidden_build_path = dir :: merlin.hidden_build_path}), + " Add to merlin hidden build path" + ); + ( + "-hidden-source-path", + marg_path (fun dir merlin -> + {merlin with hidden_source_path = dir :: merlin.hidden_source_path}), + " Add to merlin hidden source path" + ); ( "-cmi-path", marg_path (fun dir merlin -> @@ -743,8 +760,9 @@ let initial = { }; merlin = { build_path = []; - hidden_path = []; source_path = []; + hidden_build_path = []; + hidden_source_path = []; cmi_path = []; cmt_path = []; extensions = []; @@ -889,8 +907,8 @@ let build_path config = ( result' ) -let hidden_path config = - config.merlin.hidden_path @ config.ocaml.hidden_dirs +let hidden_build_path config = + config.merlin.hidden_build_path @ config.ocaml.hidden_dirs let cmt_path config = ( let dirs = diff --git a/src/kernel/mconfig.mli b/src/kernel/mconfig.mli index c529f5e48..e903cc6a8 100644 --- a/src/kernel/mconfig.mli +++ b/src/kernel/mconfig.mli @@ -31,8 +31,9 @@ val dump_ocaml : ocaml -> json type merlin = { build_path : string list; - hidden_path : string list; source_path : string list; + hidden_build_path : string list; + hidden_source_path : string list; cmi_path : string list; cmt_path : string list; extensions : string list; @@ -112,7 +113,7 @@ val source_path : t -> string list val build_path : t -> string list -val hidden_path : t -> string list +val hidden_build_path : t -> string list val cmt_path : t -> string list diff --git a/src/kernel/mconfig_dot.ml b/src/kernel/mconfig_dot.ml index a4d7ff1a9..a5303f7a5 100644 --- a/src/kernel/mconfig_dot.ml +++ b/src/kernel/mconfig_dot.ml @@ -34,8 +34,9 @@ type directive = Merlin_dot_protocol.directive type config = { build_path : string list; - hidden_path : string list; source_path : string list; + hidden_build_path : string list; + hidden_source_path : string list; cmi_path : string list; cmt_path : string list; flags : string list with_workdir list; @@ -49,7 +50,8 @@ type config = { let empty_config = { build_path = []; - hidden_path = []; + hidden_build_path =[]; + hidden_source_path = []; source_path = []; cmi_path = []; cmt_path = []; @@ -236,8 +238,9 @@ let prepend_config ~dir:cwd configurator (directives : directive list) config = List.fold_left ~init:(config, []) ~f:(fun (config, errors) -> function | `B path -> {config with build_path = path :: config.build_path}, errors - | `H path -> {config with hidden_path = path :: config.hidden_path}, errors | `S path -> {config with source_path = path :: config.source_path}, errors + | `BH path -> {config with hidden_build_path = path :: config.hidden_build_path}, errors + | `SH path -> {config with hidden_source_path = path :: config.hidden_source_path}, errors | `CMI path -> {config with cmi_path = path :: config.cmi_path}, errors | `CMT path -> {config with cmt_path = path :: config.cmt_path}, errors | `EXT exts -> @@ -270,8 +273,9 @@ let postprocess_config config = let clean list = List.rev (List.filter_dup list) in { build_path = clean config.build_path; - hidden_path = clean config.hidden_path; source_path = clean config.source_path; + hidden_build_path = clean config.hidden_build_path; + hidden_source_path = clean config.hidden_source_path; cmi_path = clean config.cmi_path; cmt_path = clean config.cmt_path; extensions = clean config.extensions; diff --git a/src/kernel/mconfig_dot.mli b/src/kernel/mconfig_dot.mli index 60636e37e..548b907e9 100644 --- a/src/kernel/mconfig_dot.mli +++ b/src/kernel/mconfig_dot.mli @@ -30,8 +30,9 @@ open Std type config = { build_path : string list; - hidden_path : string list; source_path : string list; + hidden_build_path : string list; + hidden_source_path : string list; cmi_path : string list; cmt_path : string list; flags : string list with_workdir list; diff --git a/src/kernel/mocaml.ml b/src/kernel/mocaml.ml index a843757df..fec1d67ef 100644 --- a/src/kernel/mocaml.ml +++ b/src/kernel/mocaml.ml @@ -50,7 +50,7 @@ let setup_reader_config config = ( let setup_typer_config config = ( setup_reader_config config; let visible = Mconfig.build_path config in - let hidden = Mconfig.hidden_path config in + let hidden = Mconfig.hidden_build_path config in Load_path.(init ~auto_include:no_auto_include ~visible ~hidden); ) diff --git a/tests/test-dirs/config/dot-merlin-reader/quoting.t b/tests/test-dirs/config/dot-merlin-reader/quoting.t index e99dfaeb7..59ce479a5 100644 --- a/tests/test-dirs/config/dot-merlin-reader/quoting.t +++ b/tests/test-dirs/config/dot-merlin-reader/quoting.t @@ -14,6 +14,8 @@ { "build_path": [], "source_path": [], + "hidden_build_path": [], + "hidden_source_path": [], "cmi_path": [], "cmt_path": [], "flags_applied": [ From 3bc2c996dd1365bb42633dcc053da3571173c7c9 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Mon, 29 Apr 2024 15:35:15 -0400 Subject: [PATCH 04/11] Add test and fix bug --- src/dot-merlin/dot_merlin_reader.ml | 6 +- .../config/dot-merlin-reader/load-config.t | 60 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/test-dirs/config/dot-merlin-reader/load-config.t diff --git a/src/dot-merlin/dot_merlin_reader.ml b/src/dot-merlin/dot_merlin_reader.ml index fa8401dd3..44fca4c5d 100644 --- a/src/dot-merlin/dot_merlin_reader.ml +++ b/src/dot-merlin/dot_merlin_reader.ml @@ -72,10 +72,12 @@ module Cache = File_cache.Make (struct else if String.is_prefixed ~by:"B " line then tell (`B (String.drop 2 line)) - else if String.is_prefixed ~by:"H " line then - tell (`S (String.drop 2 line)) else if String.is_prefixed ~by:"S " line then tell (`S (String.drop 2 line)) + else if String.is_prefixed ~by:"BH " line then + tell (`BH (String.drop 3 line)) + else if String.is_prefixed ~by:"SH " line then + tell (`SH (String.drop 3 line)) else if String.is_prefixed ~by:"SRC " line then tell (`S (String.drop 4 line)) else if String.is_prefixed ~by:"CMI " line then diff --git a/tests/test-dirs/config/dot-merlin-reader/load-config.t b/tests/test-dirs/config/dot-merlin-reader/load-config.t new file mode 100644 index 000000000..7bb9b7671 --- /dev/null +++ b/tests/test-dirs/config/dot-merlin-reader/load-config.t @@ -0,0 +1,60 @@ + $ cat > .merlin < B build/dir + > S source/dir + > BH build-hidden/dir + > SH source-hidden/dir + > EOF + + $ FILE=$(pwd)/test.ml; dot-merlin-reader < (4:File${#FILE}:$FILE) + > EOF + ((?:B?:$TESTCASE_ROOT/build/dir)(?:S?:$TESTCASE_ROOT/source/dir)(?:BH?:$TESTCASE_ROOT/build-hidden/dir)(?:SH?:$TESTCASE_ROOT/source-hidden/dir)) + + $ echo | $MERLIN single dump-configuration -filename test.ml 2> /dev/null | jq '.value.merlin' + { + "build_path": [ + "$TESTCASE_ROOT/build/dir" + ], + "source_path": [ + "$TESTCASE_ROOT/source/dir" + ], + "hidden_build_path": [ + "$TESTCASE_ROOT/build-hidden/dir" + ], + "hidden_source_path": [ + "$TESTCASE_ROOT/source-hidden/dir" + ], + "cmi_path": [], + "cmt_path": [], + "flags_applied": [], + "extensions": [], + "suffixes": [ + { + "impl": ".ml", + "intf": ".mli" + }, + { + "impl": ".re", + "intf": ".rei" + } + ], + "stdlib": "lib/ocaml", + "reader": [], + "protocol": "json", + "log_file": null, + "log_sections": [], + "flags_to_apply": [], + "failures": [], + "assoc_suffixes": [ + { + "extension": ".re", + "reader": "reason" + }, + { + "extension": ".rei", + "reader": "reason" + } + ] + } + + $ rm .merlin From 3b908bc33340d9033fce97b6994df05ee0115a59 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Tue, 30 Apr 2024 18:30:09 -0400 Subject: [PATCH 05/11] Create test for BH and SH --- tests/test-dirs/hidden-deps.t/a/a.ml | 1 + tests/test-dirs/hidden-deps.t/a/a.mli | 1 + tests/test-dirs/hidden-deps.t/b/b.ml | 2 + tests/test-dirs/hidden-deps.t/b/b.mli | 2 + tests/test-dirs/hidden-deps.t/build.sh | 43 ++++++++ tests/test-dirs/hidden-deps.t/c/correct.ml | 3 + tests/test-dirs/hidden-deps.t/c/error.ml | 3 + tests/test-dirs/hidden-deps.t/run.t | 118 +++++++++++++++++++++ 8 files changed, 173 insertions(+) create mode 100644 tests/test-dirs/hidden-deps.t/a/a.ml create mode 100644 tests/test-dirs/hidden-deps.t/a/a.mli create mode 100644 tests/test-dirs/hidden-deps.t/b/b.ml create mode 100644 tests/test-dirs/hidden-deps.t/b/b.mli create mode 100755 tests/test-dirs/hidden-deps.t/build.sh create mode 100644 tests/test-dirs/hidden-deps.t/c/correct.ml create mode 100644 tests/test-dirs/hidden-deps.t/c/error.ml create mode 100644 tests/test-dirs/hidden-deps.t/run.t diff --git a/tests/test-dirs/hidden-deps.t/a/a.ml b/tests/test-dirs/hidden-deps.t/a/a.ml new file mode 100644 index 000000000..e46c633fc --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/a/a.ml @@ -0,0 +1 @@ +let a = 10 diff --git a/tests/test-dirs/hidden-deps.t/a/a.mli b/tests/test-dirs/hidden-deps.t/a/a.mli new file mode 100644 index 000000000..3f79c8149 --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/a/a.mli @@ -0,0 +1 @@ +val a : int diff --git a/tests/test-dirs/hidden-deps.t/b/b.ml b/tests/test-dirs/hidden-deps.t/b/b.ml new file mode 100644 index 000000000..7a9a2287f --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/b/b.ml @@ -0,0 +1,2 @@ +include A +let b = 20 diff --git a/tests/test-dirs/hidden-deps.t/b/b.mli b/tests/test-dirs/hidden-deps.t/b/b.mli new file mode 100644 index 000000000..63567b698 --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/b/b.mli @@ -0,0 +1,2 @@ +val a : int +val b : int diff --git a/tests/test-dirs/hidden-deps.t/build.sh b/tests/test-dirs/hidden-deps.t/build.sh new file mode 100755 index 000000000..64a32dd01 --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/build.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e +cd "$(dirname "$0")" + +OCAMLC=/j/office/app/ocaml/prod/5.1.1minus/5.1.1minus-13-d49e4649/el8+fl2/bin/ocamlc +BUILD="$(realpath ./_build)" + +rm -rf $BUILD +mkdir -p $BUILD/a +mkdir -p $BUILD/b +mkdir -p $BUILD/c + +# cd a +# $OCAMLC -c a.mli -o $BUILD/a/a.cmi +# $OCAMLC -c -I $BUILD/a a.ml -o $BUILD/a/a.cmo +# $OCAMLC -a $BUILD/a/a.cmo -o $BUILD/a/a.cma + +# cd ../b +# $OCAMLC -c b.mli -o $BUILD/b/b.cmi +# $OCAMLC -c -I $BUILD/a -I $BUILD/b b.ml -o $BUILD/b/b.cmo +# $OCAMLC -a -I $BUILD/a $BUILD/b/b.cmo -o $BUILD/b/b.cma + +# cd ../c +# $OCAMLC -I $BUILD/a -H $BUILD/b $BUILD/a/a.cma $BUILD/b/b.cma c.ml -o $BUILD/c/c + + + +cp a/*.ml a/*.mli $BUILD/a +cd $BUILD/a +$OCAMLC -c -bin-annot a.mli -o a.cmi +$OCAMLC -c -bin-annot a.ml -o a.cmo +$OCAMLC -a -bin-annot a.cmo -o a.cma +cd ../.. + +cp b/*.ml b/*.mli $BUILD/b +cd $BUILD/b +$OCAMLC -c -bin-annot b.mli -o b.cmi +$OCAMLC -c -bin-annot -I $BUILD/a b.ml -o b.cmo +$OCAMLC -a -bin-annot -I $BUILD/a b.cmo -o b.cma +cd ../.. + +# cd ../c +# $OCAMLC -I $BUILD/a -H $BUILD/b $BUILD/a/a.cma $BUILD/b/b.cma c.ml -o $BUILD/c/c diff --git a/tests/test-dirs/hidden-deps.t/c/correct.ml b/tests/test-dirs/hidden-deps.t/c/correct.ml new file mode 100644 index 000000000..00eec83ea --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/c/correct.ml @@ -0,0 +1,3 @@ +let c = B.a + B.b + +let () = print_endline (Int.to_string c) diff --git a/tests/test-dirs/hidden-deps.t/c/error.ml b/tests/test-dirs/hidden-deps.t/c/error.ml new file mode 100644 index 000000000..1c2f4da76 --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/c/error.ml @@ -0,0 +1,3 @@ +let c = A.a + B.b + +let () = print_endline (Int.to_string c) diff --git a/tests/test-dirs/hidden-deps.t/run.t b/tests/test-dirs/hidden-deps.t/run.t new file mode 100644 index 000000000..d16ab98f2 --- /dev/null +++ b/tests/test-dirs/hidden-deps.t/run.t @@ -0,0 +1,118 @@ +Test that Merlin correctly handles BH and SH directives. +These are for hidden dependencies and correspond to the +-H compiler flag. + +Start by building some dependencies. C depends on B +which depends on A. A will be a hidden dependency of C, +while B will be direct. + +B exposes a variable from A, allowing C to directly use +it via B. + + $ mkdir -p _build/a + $ cp a/*.ml* _build/a + $ pushd _build/a > /dev/null + $ $OCAMLC -c -bin-annot a.mli -o a.cmi + $ $OCAMLC -c -bin-annot a.ml -o a.cmo + $ popd > /dev/null + + $ mkdir -p _build/b + $ cp b/*.ml* _build/b + $ pushd _build/b > /dev/null + $ $OCAMLC -c -bin-annot b.mli -o b.cmi + $ $OCAMLC -c -bin-annot -I ../a b.ml -o b.cmo + $ popd > /dev/null + +Merlin does not report errors when there are none + + $ $MERLIN single errors -filename c/correct.ml < c/correct.ml | jq ".value" + [] + +Merlin can locate a value in an interface from a direct dependency + + $ $MERLIN single locate -position 1:17 -look-for interface -filename c/correct.ml < c/correct.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/b/b.mli", + "pos": { + "line": 2, + "col": 0 + } + } + +Merlin can locate a value in an interface from a hidden dependency + + $ $MERLIN single locate -position 1:11 -look-for interface -filename c/correct.ml < c/correct.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/b/b.mli", + "pos": { + "line": 1, + "col": 0 + } + } + +Merlin can locate a value in an implementation from a direct dependency + + $ $MERLIN single locate -position 1:17 -look-for implementation -filename c/correct.ml < c/correct.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/b/b.ml", + "pos": { + "line": 2, + "col": 4 + } + } + +Merlin can locate a value in an implementation from a hidden dependency + + $ $MERLIN single locate -position 1:11 -look-for implementation -filename c/correct.ml < c/correct.ml | jq ".value" + +Merlin reports an error when a hidden dependency is directly used + + $ $MERLIN single errors -filename c/error.ml < c/error.ml | jq ".value" + [ + { + "start": { + "line": 1, + "col": 8 + }, + "end": { + "line": 1, + "col": 11 + }, + "type": "typer", + "sub": [], + "valid": true, + "message": "Unbound module A" + } + ] + +Merlin can locate a value in an interface from a direct dependency when there is an error + + $ $MERLIN single locate -position 1:17 -look-for interface -filename c/error.ml < c/error.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/b/b.mli", + "pos": { + "line": 2, + "col": 0 + } + } + +Merlin fails locate a value in an interface from a hidden dependency that is illegally used + + $ $MERLIN single locate -position 1:11 -look-for interface -filename c/error.ml < c/error.ml | jq ".value" + "Not in environment 'A.a'" + +Merlin can locate a value in an implementation from a direct dependency when there is an error + + $ $MERLIN single locate -position 1:17 -look-for implementation -filename c/error.ml < c/error.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/b/b.ml", + "pos": { + "line": 2, + "col": 4 + } + } + +Merlin fails locate a value in an implementation from a hidden dependency that is illegally used + + $ $MERLIN single locate -position 1:11 -look-for implementation -filename c/error.ml < c/error.ml | jq ".value" + "Not in environment 'A.a'" From 39d854c11da6eb79292f7c1b0605fb0acba878c3 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Wed, 1 May 2024 11:51:14 -0400 Subject: [PATCH 06/11] Fix failing tests --- src/analysis/locate.ml | 8 ++++---- src/frontend/query_commands.ml | 8 ++++++-- src/kernel/mconfig.ml | 3 +++ src/kernel/mconfig.mli | 2 ++ src/kernel/mppx.ml | 18 +++++++++++++----- tests/test-dirs/hidden-deps.t/run.t | 7 +++++++ 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/analysis/locate.ml b/src/analysis/locate.ml index 3f2e83ae1..a36026698 100644 --- a/src/analysis/locate.ml +++ b/src/analysis/locate.ml @@ -389,7 +389,7 @@ module Utils = struct let files = List.concat_map ~f:(fun synonym_pair -> find_all_in_path_uncap ~src_suffix_pair:synonym_pair ~with_fallback - (Mconfig.source_path config) file + (Mconfig.source_path config @ Mconfig.hidden_source_path config) file ) Mconfig.(config.merlin.suffixes) in List.dedup_adjacent files ~cmp:String.compare @@ -422,9 +422,9 @@ module Utils = struct let find_file ~config ?with_fallback (file : File.t) = find_file_with_path ~config ?with_fallback file @@ match file with - | ML _ | MLI _ | MLL _ -> Mconfig.source_path config - | CMT _ | CMTI _ -> Mconfig.build_path config - | CMS _ | CMSI _ -> Mconfig.build_path config + | ML _ | MLI _ | MLL _ -> Mconfig.source_path config @ Mconfig.hidden_source_path config + | CMT _ | CMTI _ -> Mconfig.build_path config @ Mconfig.hidden_build_path config + | CMS _ | CMSI _ -> Mconfig.build_path config @ Mconfig.hidden_build_path config end let move_to filename artifact = diff --git a/src/frontend/query_commands.ml b/src/frontend/query_commands.ml index b7c73f5e3..a221883c2 100644 --- a/src/frontend/query_commands.ml +++ b/src/frontend/query_commands.ml @@ -183,6 +183,10 @@ let dump pipeline = function let paths = Mconfig.build_path (Mpipeline.final_config pipeline) in `List (List.map paths ~f:(fun s -> `String s)) + | [`String "hidden-paths"] -> + let paths = Mconfig.hidden_build_path (Mpipeline.final_config pipeline) in + `List (List.map paths ~f:(fun s -> `String s)) + | [`String "typedtree"] -> let tree = Mpipeline.typer_result pipeline @@ -795,9 +799,9 @@ let dispatch pipeline (type a) : a Query_protocol.t -> a = | [] -> raise Not_found | x :: xs -> try - find_in_path_uncap (Mconfig.source_path config) x + find_in_path_uncap (Mconfig.source_path config @ Mconfig.hidden_source_path config) x with Not_found -> try - find_in_path_uncap (Mconfig.build_path config) x + find_in_path_uncap (Mconfig.build_path config @ Mconfig.hidden_build_path config) x with Not_found -> aux xs in diff --git a/src/kernel/mconfig.ml b/src/kernel/mconfig.ml index 846f122ad..f8b4e6fd4 100644 --- a/src/kernel/mconfig.ml +++ b/src/kernel/mconfig.ml @@ -878,6 +878,9 @@ let source_path config = config.merlin.source_path] |> List.filter_dup +let hidden_source_path config = + config.merlin.hidden_source_path @ config.ocaml.hidden_dirs + let build_path config = ( let dirs = match config.ocaml.threads with diff --git a/src/kernel/mconfig.mli b/src/kernel/mconfig.mli index e903cc6a8..609e9edc5 100644 --- a/src/kernel/mconfig.mli +++ b/src/kernel/mconfig.mli @@ -111,6 +111,8 @@ val document_arguments : out_channel -> unit val source_path : t -> string list +val hidden_source_path : t -> string list + val build_path : t -> string list val hidden_build_path : t -> string list diff --git a/src/kernel/mppx.ml b/src/kernel/mppx.ml index 4e1fea600..43bb0f0d1 100644 --- a/src/kernel/mppx.ml +++ b/src/kernel/mppx.ml @@ -2,10 +2,15 @@ open Mconfig let {Logger. log} = Logger.for_section "Mppx" -let with_include_dir path f = - let saved = !Clflags.include_dirs in - let restore () = Clflags.include_dirs := saved in - Clflags.include_dirs := path; +let with_include_dir ~visible_path ~hidden_path f = + let saved_visible = !Clflags.include_dirs in + let saved_hidden = !Clflags.hidden_include_dirs in + let restore () = + Clflags.include_dirs := saved_visible; + Clflags.hidden_include_dirs := saved_hidden + in + Clflags.include_dirs := visible_path; + Clflags.hidden_include_dirs := hidden_path; let result = begin try @@ -22,7 +27,10 @@ let with_include_dir path f = let rewrite parsetree cfg = let ppx = cfg.ocaml.ppx in (* add include path attribute to the parsetree *) - with_include_dir (Mconfig.build_path cfg) @@ fun () -> + with_include_dir + ~visible_path:(Mconfig.build_path cfg) + ~hidden_path:(Mconfig.hidden_build_path cfg) + @@ fun () -> match Pparse.apply_rewriters ~restore:false ~ppx ~tool_name:"merlin" parsetree with diff --git a/tests/test-dirs/hidden-deps.t/run.t b/tests/test-dirs/hidden-deps.t/run.t index d16ab98f2..ea09aea36 100644 --- a/tests/test-dirs/hidden-deps.t/run.t +++ b/tests/test-dirs/hidden-deps.t/run.t @@ -64,6 +64,13 @@ Merlin can locate a value in an implementation from a direct dependency Merlin can locate a value in an implementation from a hidden dependency $ $MERLIN single locate -position 1:11 -look-for implementation -filename c/correct.ml < c/correct.ml | jq ".value" + { + "file": "$TESTCASE_ROOT/a/a.ml", + "pos": { + "line": 1, + "col": 4 + } + } Merlin reports an error when a hidden dependency is directly used From 7a7015254796788cc2d30e0e34eeef80537553a7 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Wed, 1 May 2024 13:35:23 -0400 Subject: [PATCH 07/11] Fix tests that fail to run on CI --- tests/test-dirs/hidden-deps.t/build.sh | 43 -------------------------- tests/test-dirs/hidden-deps.t/run.t | 8 ++--- 2 files changed, 4 insertions(+), 47 deletions(-) delete mode 100755 tests/test-dirs/hidden-deps.t/build.sh diff --git a/tests/test-dirs/hidden-deps.t/build.sh b/tests/test-dirs/hidden-deps.t/build.sh deleted file mode 100755 index 64a32dd01..000000000 --- a/tests/test-dirs/hidden-deps.t/build.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -set -e -cd "$(dirname "$0")" - -OCAMLC=/j/office/app/ocaml/prod/5.1.1minus/5.1.1minus-13-d49e4649/el8+fl2/bin/ocamlc -BUILD="$(realpath ./_build)" - -rm -rf $BUILD -mkdir -p $BUILD/a -mkdir -p $BUILD/b -mkdir -p $BUILD/c - -# cd a -# $OCAMLC -c a.mli -o $BUILD/a/a.cmi -# $OCAMLC -c -I $BUILD/a a.ml -o $BUILD/a/a.cmo -# $OCAMLC -a $BUILD/a/a.cmo -o $BUILD/a/a.cma - -# cd ../b -# $OCAMLC -c b.mli -o $BUILD/b/b.cmi -# $OCAMLC -c -I $BUILD/a -I $BUILD/b b.ml -o $BUILD/b/b.cmo -# $OCAMLC -a -I $BUILD/a $BUILD/b/b.cmo -o $BUILD/b/b.cma - -# cd ../c -# $OCAMLC -I $BUILD/a -H $BUILD/b $BUILD/a/a.cma $BUILD/b/b.cma c.ml -o $BUILD/c/c - - - -cp a/*.ml a/*.mli $BUILD/a -cd $BUILD/a -$OCAMLC -c -bin-annot a.mli -o a.cmi -$OCAMLC -c -bin-annot a.ml -o a.cmo -$OCAMLC -a -bin-annot a.cmo -o a.cma -cd ../.. - -cp b/*.ml b/*.mli $BUILD/b -cd $BUILD/b -$OCAMLC -c -bin-annot b.mli -o b.cmi -$OCAMLC -c -bin-annot -I $BUILD/a b.ml -o b.cmo -$OCAMLC -a -bin-annot -I $BUILD/a b.cmo -o b.cma -cd ../.. - -# cd ../c -# $OCAMLC -I $BUILD/a -H $BUILD/b $BUILD/a/a.cma $BUILD/b/b.cma c.ml -o $BUILD/c/c diff --git a/tests/test-dirs/hidden-deps.t/run.t b/tests/test-dirs/hidden-deps.t/run.t index ea09aea36..e596538c5 100644 --- a/tests/test-dirs/hidden-deps.t/run.t +++ b/tests/test-dirs/hidden-deps.t/run.t @@ -11,17 +11,17 @@ it via B. $ mkdir -p _build/a $ cp a/*.ml* _build/a - $ pushd _build/a > /dev/null + $ cd _build/a $ $OCAMLC -c -bin-annot a.mli -o a.cmi $ $OCAMLC -c -bin-annot a.ml -o a.cmo - $ popd > /dev/null + $ cd ../.. $ mkdir -p _build/b $ cp b/*.ml* _build/b - $ pushd _build/b > /dev/null + $ cd _build/b $ $OCAMLC -c -bin-annot b.mli -o b.cmi $ $OCAMLC -c -bin-annot -I ../a b.ml -o b.cmo - $ popd > /dev/null + $ cd ../.. Merlin does not report errors when there are none From 62395d752dee58369213e5902971e81d07b1cdae Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Wed, 1 May 2024 13:56:05 -0400 Subject: [PATCH 08/11] Add .merlin file to tests --- tests/test-dirs/hidden-deps.t/run.t | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test-dirs/hidden-deps.t/run.t b/tests/test-dirs/hidden-deps.t/run.t index e596538c5..82bfddb00 100644 --- a/tests/test-dirs/hidden-deps.t/run.t +++ b/tests/test-dirs/hidden-deps.t/run.t @@ -23,6 +23,15 @@ it via B. $ $OCAMLC -c -bin-annot -I ../a b.ml -o b.cmo $ cd ../.. +Create a .merlin file + + $ cat >c/.merlin < BH ../_build/a + > SH ../a + > B ../_build/b + > S ../b + > EOF + Merlin does not report errors when there are none $ $MERLIN single errors -filename c/correct.ml < c/correct.ml | jq ".value" From ac10df3c7c0e1173f42afe76dc28924ccb7f56a1 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Fri, 3 May 2024 11:45:07 -0400 Subject: [PATCH 09/11] Refactor tests --- tests/test-dirs/{dash-h.t/run.t => hidden-deps/dash-h.t} | 0 .../test-dirs/{hidden-deps.t => hidden-deps/directives.t}/a/a.ml | 0 .../test-dirs/{hidden-deps.t => hidden-deps/directives.t}/a/a.mli | 0 .../test-dirs/{hidden-deps.t => hidden-deps/directives.t}/b/b.ml | 0 .../test-dirs/{hidden-deps.t => hidden-deps/directives.t}/b/b.mli | 0 .../{hidden-deps.t => hidden-deps/directives.t}/c/correct.ml | 0 .../{hidden-deps.t => hidden-deps/directives.t}/c/error.ml | 0 tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/run.t | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename tests/test-dirs/{dash-h.t/run.t => hidden-deps/dash-h.t} (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/a/a.ml (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/a/a.mli (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/b/b.ml (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/b/b.mli (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/c/correct.ml (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/c/error.ml (100%) rename tests/test-dirs/{hidden-deps.t => hidden-deps/directives.t}/run.t (100%) diff --git a/tests/test-dirs/dash-h.t/run.t b/tests/test-dirs/hidden-deps/dash-h.t similarity index 100% rename from tests/test-dirs/dash-h.t/run.t rename to tests/test-dirs/hidden-deps/dash-h.t diff --git a/tests/test-dirs/hidden-deps.t/a/a.ml b/tests/test-dirs/hidden-deps/directives.t/a/a.ml similarity index 100% rename from tests/test-dirs/hidden-deps.t/a/a.ml rename to tests/test-dirs/hidden-deps/directives.t/a/a.ml diff --git a/tests/test-dirs/hidden-deps.t/a/a.mli b/tests/test-dirs/hidden-deps/directives.t/a/a.mli similarity index 100% rename from tests/test-dirs/hidden-deps.t/a/a.mli rename to tests/test-dirs/hidden-deps/directives.t/a/a.mli diff --git a/tests/test-dirs/hidden-deps.t/b/b.ml b/tests/test-dirs/hidden-deps/directives.t/b/b.ml similarity index 100% rename from tests/test-dirs/hidden-deps.t/b/b.ml rename to tests/test-dirs/hidden-deps/directives.t/b/b.ml diff --git a/tests/test-dirs/hidden-deps.t/b/b.mli b/tests/test-dirs/hidden-deps/directives.t/b/b.mli similarity index 100% rename from tests/test-dirs/hidden-deps.t/b/b.mli rename to tests/test-dirs/hidden-deps/directives.t/b/b.mli diff --git a/tests/test-dirs/hidden-deps.t/c/correct.ml b/tests/test-dirs/hidden-deps/directives.t/c/correct.ml similarity index 100% rename from tests/test-dirs/hidden-deps.t/c/correct.ml rename to tests/test-dirs/hidden-deps/directives.t/c/correct.ml diff --git a/tests/test-dirs/hidden-deps.t/c/error.ml b/tests/test-dirs/hidden-deps/directives.t/c/error.ml similarity index 100% rename from tests/test-dirs/hidden-deps.t/c/error.ml rename to tests/test-dirs/hidden-deps/directives.t/c/error.ml diff --git a/tests/test-dirs/hidden-deps.t/run.t b/tests/test-dirs/hidden-deps/directives.t/run.t similarity index 100% rename from tests/test-dirs/hidden-deps.t/run.t rename to tests/test-dirs/hidden-deps/directives.t/run.t From 90c05225ab493437cc549d01ac097a2558ebb317 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Fri, 3 May 2024 11:54:42 -0400 Subject: [PATCH 10/11] Update docs for dump --- src/frontend/ocamlmerlin/new/new_commands.ml | 2 +- src/frontend/query_commands.ml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/ocamlmerlin/new/new_commands.ml b/src/frontend/ocamlmerlin/new/new_commands.ml index 645d5f37c..cb4f44dbb 100644 --- a/src/frontend/ocamlmerlin/new/new_commands.ml +++ b/src/frontend/ocamlmerlin/new/new_commands.ml @@ -701,7 +701,7 @@ The return value has the shape: command "dump" ~spec:[ arg "-what" " \ + |env|fullenv|browse|tokens|flags|warnings|exn|paths|hidden-paths> \ Information to dump ()" (Marg.param "string" (fun what _ -> what)); ] diff --git a/src/frontend/query_commands.ml b/src/frontend/query_commands.ml index a221883c2..2409c75f9 100644 --- a/src/frontend/query_commands.ml +++ b/src/frontend/query_commands.ml @@ -202,8 +202,8 @@ let dump pipeline = function `String (to_string ()) | _ -> failwith "known dump commands: \ - paths, exn, warnings, flags, tokens, browse, source, \ - parsetree, ppxed-source, ppxed-parsetree, typedtree, \ + paths, hidden-paths, exn, warnings, flags, tokens, browse, \ + source, parsetree, ppxed-source, ppxed-parsetree, typedtree, \ env/fullenv (at {col:, line:})" let reconstruct_identifier pipeline pos = function From d2b8b00c757936d58993577033eed139a2af2525 Mon Sep 17 00:00:00 2001 From: Liam Stevenson Date: Fri, 3 May 2024 11:59:14 -0400 Subject: [PATCH 11/11] Add -H deps to Path_list --- src/frontend/query_commands.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/query_commands.ml b/src/frontend/query_commands.ml index 2409c75f9..7ac8087c4 100644 --- a/src/frontend/query_commands.ml +++ b/src/frontend/query_commands.ml @@ -829,11 +829,11 @@ let dispatch pipeline (type a) : a Query_protocol.t -> a = | Path_list `Build -> let config = Mpipeline.final_config pipeline in - Mconfig.(config.merlin.build_path) + Mconfig.(config.merlin.build_path @ config.merlin.hidden_build_path) | Path_list `Source -> let config = Mpipeline.final_config pipeline in - Mconfig.(config.merlin.source_path) + Mconfig.(config.merlin.source_path @ config.merlin.hidden_source_path) | Occurrences (`Ident_at pos, _scope) -> let typer = Mpipeline.typer_result pipeline in