diff --git a/CHANGES.md b/CHANGES.md index 96ab9db68..c4dc10442 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ unreleased + merlin binary - Respect the `EXCLUDE_QUERY_DIR` configuration directive when looking for cmt files (#1854) + - Fix occurrences bug in which relative paths in index files are resolved against the + PWD rather than the SOURCE_ROOT (#1855) merlin 5.2.1 ============ diff --git a/src/analysis/occurrences.ml b/src/analysis/occurrences.ml index 4be51bca9..829c8146c 100644 --- a/src/analysis/occurrences.ml +++ b/src/analysis/occurrences.ml @@ -234,7 +234,10 @@ let locs_of ~config ~env ~typer_result ~pos ~scope path = is not necessary for correctness, it makes the output a bit nicer. *) let canonicalize_file_in_loc ({ txt; loc } : 'a Location.loc) : 'a Location.loc = - let file = Misc.canonicalize_filename loc.loc_start.pos_fname in + let file = + Misc.canonicalize_filename ?cwd:config.merlin.source_root + loc.loc_start.pos_fname + in { txt; loc = set_fname ~file loc } in let locs = Lid_set.map canonicalize_file_in_loc locs in diff --git a/tests/test-dirs/occurrences/project-wide/pwo-canonicalize.t b/tests/test-dirs/occurrences/project-wide/pwo-canonicalize.t index ad3e8cae5..5a7b91f72 100644 --- a/tests/test-dirs/occurrences/project-wide/pwo-canonicalize.t +++ b/tests/test-dirs/occurrences/project-wide/pwo-canonicalize.t @@ -12,10 +12,10 @@ > SOURCE_ROOT . > EOF - $ ocamlc -bin-annot -bin-annot-occurrences -c lib.ml main.ml + $ $OCAMLC -bin-annot -bin-annot-occurrences -c lib.ml main.ml $ ocaml-index aggregate main.cmt lib.cmt --root . --rewrite-root - $ ocamlmerlin single occurrences -scope project -identifier-at 1:4 \ + $ $MERLIN single occurrences -scope project -identifier-at 1:4 \ > -filename lib.ml < lib.ml | jq .value [ { diff --git a/tests/test-dirs/occurrences/project-wide/pwo-relative.t b/tests/test-dirs/occurrences/project-wide/pwo-relative.t new file mode 100644 index 000000000..1c9e928b5 --- /dev/null +++ b/tests/test-dirs/occurrences/project-wide/pwo-relative.t @@ -0,0 +1,95 @@ +This test demonstrates project-wide occurrences resolving file paths relative to the +correct directory. + +Create a small ocaml project + $ mkdir main + $ mkdir lib + $ cat > lib/foo.ml << EOF + > let bar = "bar" + > let () = print_string bar + > EOF + + $ cat > main/main.ml << EOF + > let x = Foo.bar + > let () = print_string Foo.bar + > EOF + +Compile project + $ ( cd lib ; $OCAMLC -bin-annot -bin-annot-occurrences -c foo.ml ) + $ ( cd main ; $OCAMLC -bin-annot -bin-annot-occurrences -I ../lib -c main.ml ) + +Build indices + $ ( cd lib ; ocaml-index aggregate foo.cmt --root ./lib --rewrite-root -o lib.stanza.merlin-index ) + $ ( cd main ; ocaml-index aggregate main.cmt --root ./main --rewrite-root -o main.stanza.merlin-index ) + $ ocaml-index aggregate main/main.stanza.merlin-index lib/lib.stanza.merlin-index --root . --rewrite-root -o global.merlin-index + $ ocaml-index dump global.merlin-index + 3 uids: + {uid: Foo.0; locs: + "bar": File "./lib/foo.ml", line 1, characters 4-7; + "bar": File "./lib/foo.ml", line 2, characters 22-25; + "Foo.bar": File "./main/main.ml", line 1, characters 8-15; + "Foo.bar": File "./main/main.ml", line 2, characters 22-29 + uid: Main.0; locs: "x": File "./main/main.ml", line 1, characters 4-5 + uid: Stdlib.312; locs: + "print_string": File "./lib/foo.ml", line 2, characters 9-21; + "print_string": File "./main/main.ml", line 2, characters 9-21 + }, 0 approx shapes: {}, and shapes for CUS . + +Configure merlin + $ cat > main/.merlin << EOF + > INDEX ../global.merlin-index + > SOURCE_ROOT .. + > S . + > B ../lib + > S ../lib + > EOF + +Perform the occurrences query + $ ( cd main ; $MERLIN single occurrences -scope project -identifier-at 1:13 \ + > -filename main.ml < main.ml | jq .value ) + [ + { + "file": "$TESTCASE_ROOT/lib/foo.ml", + "start": { + "line": 1, + "col": 4 + }, + "end": { + "line": 1, + "col": 7 + } + }, + { + "file": "$TESTCASE_ROOT/lib/foo.ml", + "start": { + "line": 2, + "col": 22 + }, + "end": { + "line": 2, + "col": 25 + } + }, + { + "file": "$TESTCASE_ROOT/main/main.ml", + "start": { + "line": 1, + "col": 12 + }, + "end": { + "line": 1, + "col": 15 + } + }, + { + "file": "$TESTCASE_ROOT/main/main.ml", + "start": { + "line": 2, + "col": 26 + }, + "end": { + "line": 2, + "col": 29 + } + } + ]