-
Notifications
You must be signed in to change notification settings - Fork 454
Fix Merlin file loading #12621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix Merlin file loading #12621
Conversation
|
Oops looks like I definitely over-tuned that testcase to my system, I'll fix that |
change merlin to load files searching for exact match first Signed-off-by: Will Thomas <[email protected]>
e50d2f9 to
8eb27b7
Compare
voodoos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, your heuristic seems like a good improvement on the current version!
bin/ocaml/ocaml_merlin.ml
Outdated
| (* FIXME we are racing against the build system writing these | ||
| files here *) | ||
| match Merlin.Processed.load_file file_path with | ||
| | Error msg -> Some (Merlin_conf.make_error msg) | ||
| | Ok config -> Merlin.Processed.get config ~file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's find a way not to repeat that code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I think I got it unless you want it even further abstracted
Signed-off-by: Will Thomas <[email protected]>
c2855f2 to
56e45f1
Compare
|
Some other things I'd thought about while working on this:
let good_names =
List.map
~f:(fun pref -> Printf.sprintf "%s-%s" pref basename)
[ "lib"; "exe"; "melange" ]
|
|
I thought more about this, and I think there is a much better thing to do. The current proposal does improve the situation a bit, but only when the module name is the same as the library or executable. We can do better: each of the Ideally we could know to which library or executable a module is associated in advance, but I am not sure that's possible without loading the project which is costly. Is that right @Alizter ? (In the future we probably want to connect to any running Dune via RPC.) Reading I think we should fix it so that we do return the config for the actually requested module, always :-) @Durbatuluk1701 Does this makes sense to you ? Are you interested in having a closer look at it ? |
This is a great insight, so it seems that This maybe leads me to the question: should
Definitely seems optimal
Happy to keep looking, although guidance on questions such as the one above will be greatly appreciated Some debugging prints I did to discover thisI've annotated this with ! (* We start just debug printing both the found Merlin Confs *)
Found merlin file: _build/default/multi-exes/bin/.merlin-conf/exe-b
Successfully loaded merlin file: _build/default/multi-exes/bin/.merlin-conf/exe-b
with content: { config =
{ stdlib_dir =
Some (External "/OCAMLC_WHERE")
; source_root = In_source_tree "."
; obj_dirs = set { In_build_dir "default/multi-exes/bin/.b.eobjs/byte" }
; src_dirs = set { In_source_tree "multi-exes/bin" }
; hidden_obj_dirs = set {}
; hidden_src_dirs = set {}
; flags =
[ "-w"
; "@[email protected]@30..39@[email protected]@[email protected]"
; "-strict-sequence"
; "-strict-formats"
; "-short-paths"
; "-keep-locs"
; "-g"
]
; extensions = []
; indexes =
[ In_build_dir "default/multi-exes/bin/.c.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/bin/.b.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/lib/.lib.objs/cctx.ocaml-index"
]
; parameters = []
}
; per_file_config =
map
{ "default/multi-exes/bin/b" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/b.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
! (* Note: This is .merlin-conf/exe-b, and "c" is being managed within its `per_file_config` *)
; "default/multi-exes/bin/c" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/c.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
}
; pp_config = { map = map {}; values = [| None |] }
}
Found merlin file: _build/default/multi-exes/bin/.merlin-conf/exe-c
Successfully loaded merlin file: _build/default/multi-exes/bin/.merlin-conf/exe-c
with content: { config =
{ stdlib_dir =
Some (External "/OCAMLC_WHERE")
; source_root = In_source_tree "."
; obj_dirs =
! (* These are the objs we actually need for "c". They only appear in `.merlin-conf/exe-c` *)
set
{ In_build_dir "default/multi-exes/bin/.c.eobjs/byte"
; In_build_dir "default/multi-exes/lib/.lib.objs/byte"
}
; src_dirs =
set
{ In_source_tree "multi-exes/bin"
; In_source_tree "multi-exes/lib"
}
; hidden_obj_dirs = set {}
; hidden_src_dirs = set {}
; flags =
[ "-w"
; "@[email protected]@30..39@[email protected]@[email protected]"
; "-strict-sequence"
; "-strict-formats"
; "-short-paths"
; "-keep-locs"
; "-g"
]
; extensions = []
; indexes =
[ In_build_dir "default/multi-exes/bin/.c.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/bin/.b.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/lib/.lib.objs/cctx.ocaml-index"
]
; parameters = []
}
; per_file_config =
map
{ "default/multi-exes/bin/b" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/b.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/c" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/c.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path =
In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
}
; pp_config = { map = map {}; values = [| None |] }
}
! (* We are now in Merlin.Processed.get *)
Trying to load merlin file: _build/default/multi-exes/bin/.merlin-conf/exe-b
File Config:
map
{ "default/multi-exes/bin/b" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path = In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/b.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "B" ]
; files =
{ impl =
Some
{ path = In_build_dir "default/multi-exes/bin/b.ml"
; original_path =
In_build_dir "default/multi-exes/bin/b.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "b"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/c" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path = In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
; "default/multi-exes/bin/c.ml" :
{ opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path = In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
}
Raw Config:
{ stdlib_dir = Some (External "/OCAMLC_WHERE")
; source_root = In_source_tree "."
! (* The wrong obj_dirs. We ultimately accept them because we find "c" in `per_file_config` *)
; obj_dirs = set { In_build_dir "default/multi-exes/bin/.b.eobjs/byte" }
; src_dirs = set { In_source_tree "multi-exes/bin" }
; hidden_obj_dirs = set {}
; hidden_src_dirs = set {}
; flags =
[ "-w"
; "@[email protected]@30..39@[email protected]@[email protected]"
; "-strict-sequence"
; "-strict-formats"
; "-short-paths"
; "-keep-locs"
; "-g"
]
; extensions = []
; indexes =
[ In_build_dir "default/multi-exes/bin/.c.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/bin/.b.eobjs/cctx.ocaml-index"
; In_build_dir "default/multi-exes/lib/.lib.objs/cctx.ocaml-index"
]
; parameters = []
}
Found exact match for file: _build/default/multi-exes/bin/c.ml
Returning: { opens = []
; module_ =
{ source =
{ path = [ "C" ]
; files =
{ impl =
Some
{ path = In_build_dir "default/multi-exes/bin/c.ml"
; original_path =
In_build_dir "default/multi-exes/bin/c.ml"
; dialect = "ocaml"
}
; intf = None
}
}
; obj_name = "c"
; pp = None
; visibility = "public"
; kind = "impl"
; install_as = None
}
; reader = None
}
pp flag: None
unit_name: c
Found merlin config in: _build/default/multi-exes/bin
with resulting csexp ((?:INDEX?:$TESTCASE_ROOT/_build/default/multi-exes/bin/.c.eobjs/cctx.ocaml-index)(?:INDEX?:$TESTCASE_ROOT/_build/default/multi-exes/bin/.b.eobjs/cctx.ocaml-index)(?:INDEX?:$TESTCASE_ROOT/_build/default/multi-exes/lib/.lib.objs/cctx.ocaml-index)(?:STDLIB?:/OCAMLC_WHERE)(?:SOURCE_ROOT?:$TESTCASE_ROOT)(?:EXCLUDE_QUERY_DIR)(?:B?:$TESTCASE_ROOT/_build/default/multi-exes/bin/.b.eobjs/byte)(?:S?:$TESTCASE_ROOT/multi-exes/bin)(?:FLG(?:-w?:@[email protected]@30..39@[email protected]@[email protected]?:-strict-sequence?:-strict-formats?:-short-paths?:-keep-locs?:-g))(?:UNIT_NAME?:c)) |
|
@voodoos We have |
This is meant to address #12611.
In particular, the following things are added:
The added testcase
test/blackbox-tests/test-cases/merlin/merlin-multi-exes.t/run.tshould fail on main and after this fix be working.I do not really think this is the optimal solution, but I think the root of the issue has been identified (in particular the use of
List.find_mapis too aggressive when searching for a possible merlin-conf) and a possible fix is here that someone with more experience could improve upon