Skip to content
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

.merlin: add a SUFFIX directive for each dialect #3977

Merged
merged 1 commit into from
Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ Unreleased

- Add support for Coq's native compute compilation mode (@ejgallego, #3210)

- Add a SUFFIX directive in `.merlin` files for each dialect with no
preprocessing, to let merlin know of additional file extensions
(#3977, @vouillon)

2.7.1 (2/09/2020)
-----------------

Expand Down
2 changes: 2 additions & 0 deletions src/dune_engine/dialect.ml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ module DB = struct
(dialect, kind))
(String.Map.find by_extension extension)

let fold { by_name; _ } = String.Map.fold by_name

let to_dyn { by_name; _ } = String.Map.to_dyn to_dyn by_name

let builtin = of_list [ ocaml; reason ]
Expand Down
2 changes: 2 additions & 0 deletions src/dune_engine/dialect.mli
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ module DB : sig

val find_by_extension : t -> string -> (dialect * Ml_kind.t) option

val fold : t -> init:'a -> f:(dialect -> 'a -> 'a) -> 'a

val to_dyn : t -> Dyn.t

val builtin : t
Expand Down
3 changes: 2 additions & 1 deletion src/dune_rules/exe_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ let executables_rules ~sctx ~dir ~expander ~dir_contents ~scope ~compile_info
( cctx
, Merlin.make () ~requires:requires_compile ~flags ~modules
~preprocess:(Preprocess.Per_module.single_preprocess preprocess)
~obj_dir )
~obj_dir
~dialects:(Dune_project.dialects (Scope.project scope)) )

let compile_info ~scope (exes : Dune_file.Executables.t) =
let dune_version = Scope.project scope |> Dune_project.dune_version in
Expand Down
3 changes: 2 additions & 1 deletion src/dune_rules/lib_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ let library_rules (lib : Library.t) ~cctx ~source_modules ~dir_contents
( cctx
, Merlin.make () ~requires:requires_compile ~flags ~modules
~preprocess:(Preprocess.Per_module.single_preprocess preprocess)
~libname:(snd lib.name) ~obj_dir )
~libname:(snd lib.name) ~obj_dir
~dialects:(Dune_project.dialects (Scope.project scope)) )

let rules (lib : Library.t) ~sctx ~dir_contents ~dir ~expander ~scope :
Compilation_context.t * Merlin.t =
Expand Down
43 changes: 37 additions & 6 deletions src/dune_rules/merlin.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ open Build.O
open! No_io
module SC = Super_context

module Extensions = Comparable.Make (struct
type t = string * string

let compare = Tuple.T2.compare String.compare String.compare

let to_dyn = Tuple.T2.to_dyn String.to_dyn String.to_dyn
end)

let warn_dropped_pp loc ~allow_approx_merlin ~reason =
if not allow_approx_merlin then
User_warning.emit ~loc
Expand Down Expand Up @@ -73,11 +81,11 @@ let quote_for_merlin s =
module Dot_file = struct
let b = Buffer.create 256

let printf = Printf.bprintf b
let printf f = Printf.bprintf b f

let print = Buffer.add_string b

let to_string ~obj_dirs ~src_dirs ~flags ~pp ~remaindir =
let to_string ~obj_dirs ~src_dirs ~flags ~pp ~remaindir ~extensions =
let serialize_path = Path.reach ~from:(Path.source remaindir) in
Buffer.clear b;
print "EXCLUDE_QUERY_DIR\n";
Expand All @@ -90,6 +98,8 @@ module Dot_file = struct
print "FLG";
List.iter flags ~f:(fun f -> printf " %s" (quote_for_merlin f));
print "\n" );
Extensions.Set.iter extensions ~f:(fun (impl, intf) ->
printf "SUFFIX %s %s\n" (quote_for_merlin impl) (quote_for_merlin intf));
Buffer.contents b
end

Expand All @@ -100,10 +110,12 @@ type t =
; libname : Lib_name.Local.t option
; source_dirs : Path.Source.Set.t
; objs_dirs : Path.Set.t
; extensions : Extensions.Set.t
}

let make ?(requires = Ok []) ~flags ?(preprocess = Preprocess.No_preprocessing)
?libname ?(source_dirs = Path.Source.Set.empty) ~modules ~obj_dir () =
?libname ?(source_dirs = Path.Source.Set.empty) ~modules ~obj_dir ~dialects
() =
(* Merlin shouldn't cause the build to fail, so we just ignore errors *)
let requires =
match requires with
Expand All @@ -122,12 +134,29 @@ let make ?(requires = Ok []) ~flags ?(preprocess = Preprocess.No_preprocessing)
flags
|> Ocaml_flags.common
in
let extensions =
Dialect.DB.fold dialects ~init:Extensions.Set.empty ~f:(fun d s ->
let impl = Dialect.extension d Ml_kind.Impl in
let intf = Dialect.extension d Ml_kind.Intf in
if
(* Only include dialects with no preprocessing and skip default file
extensions *)
Dialect.preprocess d Ml_kind.Impl <> None
|| Dialect.preprocess d Ml_kind.Intf <> None
|| impl = Dialect.extension Dialect.ocaml Ml_kind.Impl
&& intf = Dialect.extension Dialect.ocaml Ml_kind.Intf
then
s
else
Extensions.Set.add s (impl, intf))
in
{ requires
; flags = Build.catch flags ~on_error:(fun _ -> [])
; preprocess
; libname
; source_dirs
; objs_dirs
; extensions
}

let merlin_file_name = ".merlin"
Expand Down Expand Up @@ -217,8 +246,8 @@ let lib_src_dirs ~sctx lib =
Path.Set.map ~f:Path.drop_optional_build_context
(Modules.source_dirs modules)

let dot_merlin sctx ~dir ~more_src_dirs ~expander ({ requires; flags; _ } as t)
=
let dot_merlin sctx ~dir ~more_src_dirs ~expander
({ requires; flags; extensions; _ } as t) =
Path.Build.drop_build_context dir
|> Option.iter ~f:(fun remaindir ->
let open Build.With_targets.O in
Expand Down Expand Up @@ -256,7 +285,8 @@ let dot_merlin sctx ~dir ~more_src_dirs ~expander ({ requires; flags; _ } as t)
Path.Set.union src_dirs
(Path.Set.of_list_map ~f:Path.source more_src_dirs)
in
Dot_file.to_string ~remaindir ~pp ~flags ~src_dirs ~obj_dirs)
Dot_file.to_string ~remaindir ~pp ~flags ~src_dirs ~obj_dirs
~extensions)
in
SC.add_rule sctx ~dir
~mode:(Promote { lifetime = Until_clean; into = None; only = None })
Expand All @@ -275,6 +305,7 @@ let merge_two ~allow_approx_merlin a b =
| None -> b.libname )
; source_dirs = Path.Source.Set.union a.source_dirs b.source_dirs
; objs_dirs = Path.Set.union a.objs_dirs b.objs_dirs
; extensions = Extensions.Set.union a.extensions b.extensions
}

let merge_all ~allow_approx_merlin = function
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/merlin.mli
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ val make :
-> ?source_dirs:Path.Source.Set.t
-> modules:Modules.t
-> obj_dir:Path.Build.t Obj_dir.t
-> dialects:Dialect.DB.t
-> unit
-> t

Expand Down