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 new contexts commands #10324

Merged
merged 27 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1a25498
merlin: add rules regardless of (merlin)
jchavarri Mar 28, 2024
d0efe86
merlin: update tests
jchavarri Mar 28, 2024
ee2ed54
merlin: add GetContexts command
jchavarri Mar 27, 2024
6dfdd5a
merlin: add SetContexts (wip)
jchavarri Mar 27, 2024
7067792
better tests
jchavarri Mar 28, 2024
b9f9c80
merlin: simpler get-set-contexts test
jchavarri Mar 28, 2024
7c10f83
Revert "merlin: add rules regardless of (merlin)"
jchavarri Apr 2, 2024
ef635bc
merlin: introduce generate_merlin_rules
jchavarri Mar 28, 2024
606d42f
add docs and changelog
jchavarri Mar 28, 2024
2bec4bb
merlin: roll back changes in default-based-context test
jchavarri Apr 2, 2024
83a9b6b
merlin: update get-set-contexts test
jchavarri Apr 2, 2024
727d3a6
update changes
jchavarri Apr 2, 2024
cc27c7a
rename Standard to Default
jchavarri Apr 2, 2024
6122054
merlin: rename Nothing to Not_selected
jchavarri Apr 2, 2024
6653a03
merlin: fix tests
jchavarri Apr 2, 2024
094d1b9
describe: add contexts subcommand
jchavarri Apr 8, 2024
8bc5679
merlin: replace get/set context with flag
jchavarri Apr 8, 2024
4482ad7
merlin: cleanup
jchavarri Apr 8, 2024
603e123
cleanup
jchavarri Apr 11, 2024
a7436ab
merlin: remove context check
jchavarri Apr 12, 2024
b41a254
apply suggestions from code review
jchavarri May 2, 2024
8981216
gate generate_merlin_rules to 3.16
jchavarri May 2, 2024
c894fa1
merlin: add --context to dump_dot_merlin
jchavarri May 2, 2024
44f10c9
apply suggestions from code review
jchavarri May 3, 2024
e76a082
merlin: add Select_context.conv
jchavarri May 3, 2024
9ddb4c3
fix: promote tests after rebase
anmonteiro May 6, 2024
3295d2f
refactor: remove `Selected_context.t`, reuse the context arg, use it …
anmonteiro May 6, 2024
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
1 change: 1 addition & 0 deletions bin/describe/describe.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ let subcommands =
; Aliases_targets.Aliases_cmd.command
; Package_entries.command
; Describe_pkg.command
; Describe_contexts.command
]
;;

Expand Down
23 changes: 23 additions & 0 deletions bin/describe/describe_contexts.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
open Import

let term =
let+ builder = Common.Builder.term in
let common, config = Common.init builder in
Scheduler.go ~common ~config
@@ fun () ->
let open Fiber.O in
let* setup = Import.Main.setup () in
let+ setup = Memo.run setup in
let ctxts =
List.map
~f:(fun (name, _) -> Context_name.to_string name)
(Context_name.Map.to_list setup.scontexts)
in
List.iter ctxts ~f:print_endline
;;

let command =
let doc = "List the build contexts available in the workspace." in
let info = Cmd.info ~doc "contexts" in
Cmd.v info term
;;
4 changes: 4 additions & 0 deletions bin/describe/describe_contexts.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
open Import

(** Dune command to print out the available build contexts.*)
val command : unit Cmd.t
78 changes: 53 additions & 25 deletions bin/ocaml/ocaml_merlin.ml
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
open Import

module Selected_context = struct
let arg =
let ctx_name_conv =
let parse ctx_name =
match Context_name.of_string_opt ctx_name with
| None -> Error (`Msg (Printf.sprintf "Invalid context name %S" ctx_name))
| Some ctx_name -> Ok ctx_name
in
let print ppf t = Stdlib.Format.fprintf ppf "%s" (Context_name.to_string t) in
Arg.conv ~docv:"context" (parse, print)
in
Arg.(
value
& opt ctx_name_conv Context_name.default
& info
[ "context" ]
~docv:"CONTEXT"
~doc:"Select the Dune build context that will be used to return information")
;;
end

module Server : sig
val dump : string -> unit Fiber.t
val dump_dot_merlin : string -> unit Fiber.t
val dump : selected_context:Context_name.t -> string -> unit Fiber.t
val dump_dot_merlin : selected_context:Context_name.t -> string -> unit Fiber.t

(** Once started the server will wait for commands on stdin, read the
requested merlin dot file and return its content on stdout. The server
will halt when receiving EOF of a bad csexp. *)
val start : unit -> unit Fiber.t
val start : selected_context:Context_name.t -> unit -> unit Fiber.t
end = struct
open Fiber.O

Expand Down Expand Up @@ -129,48 +150,53 @@ end = struct
|> error
;;

let to_local file =
let to_local ~selected_context file =
match to_local file with
| Error s -> Fiber.return (Error s)
| Ok file ->
let+ workspace = Memo.run (Workspace.workspace ()) in
let module Context_name = Dune_engine.Context_name in
(match workspace.merlin_context with
| None -> Error "no merlin context configured"
| Some context ->
Ok (Path.Build.append_local (Context_name.build_dir context) file))
(match Dune_engine.Context_name.is_default selected_context with
| false ->
Fiber.return
(Ok (Path.Build.append_local (Context_name.build_dir selected_context) file))
| true ->
let+ workspace = Memo.run (Workspace.workspace ()) in
(match workspace.merlin_context with
| None -> Error "no merlin context configured"
| Some context ->
Ok (Path.Build.append_local (Context_name.build_dir context) file)))
;;

let print_merlin_conf file =
to_local file
let print_merlin_conf ~selected_context file =
to_local ~selected_context file
>>| (function
| Error s -> Merlin_conf.make_error s
| Ok file -> load_merlin_file file)
>>| Merlin_conf.to_stdout
;;

let dump s =
to_local s
let dump ~selected_context s =
to_local ~selected_context s
>>| function
| Error mess -> Printf.eprintf "%s\n%!" mess
| Ok path -> get_merlin_files_paths path |> List.iter ~f:Merlin.Processed.print_file
;;

let dump_dot_merlin s =
to_local s
let dump_dot_merlin ~selected_context s =
to_local ~selected_context s
>>| function
| Error mess -> Printf.eprintf "%s\n%!" mess
| Ok path ->
let files = get_merlin_files_paths path in
Merlin.Processed.print_generic_dot_merlin files
;;

let start () =
let start ~selected_context () =
let open Fiber.O in
let rec main () =
match Commands.read_input stdin with
| Halt -> Fiber.return ()
| File path ->
let* () = print_merlin_conf path in
let* () = print_merlin_conf ~selected_context path in
main ()
| Unknown msg ->
Merlin_conf.to_stdout (Merlin_conf.make_error msg);
Expand All @@ -192,15 +218,16 @@ module Dump_config = struct

let term =
let+ builder = Common.Builder.term
and+ dir = Arg.(value & pos 0 dir "" & info [] ~docv:"PATH") in
and+ dir = Arg.(value & pos 0 dir "" & info [] ~docv:"PATH")
and+ selected_context = Selected_context.arg in
let common, config =
let builder =
let builder = Common.Builder.forbid_builds builder in
Common.Builder.disable_log_file builder
in
Common.init builder
in
Scheduler.go ~common ~config (fun () -> Server.dump dir)
Scheduler.go ~common ~config (fun () -> Server.dump ~selected_context dir)
;;

let command = Cmd.v info term
Expand All @@ -222,15 +249,16 @@ let man =
let start_session_info name = Cmd.info name ~doc ~man

let start_session_term =
let+ builder = Common.Builder.term in
let+ builder = Common.Builder.term
and+ selected_context = Selected_context.arg in
let common, config =
let builder =
let builder = Common.Builder.forbid_builds builder in
Common.Builder.disable_log_file builder
in
Common.init builder
in
Scheduler.go ~common ~config Server.start
Scheduler.go ~common ~config (Server.start ~selected_context)
;;

let command = Cmd.v (start_session_info "ocaml-merlin") start_session_term
Expand Down Expand Up @@ -264,7 +292,7 @@ module Dump_dot_merlin = struct
~doc:
"The path to the folder of which the configuration should be printed. \
Defaults to the current directory.")
in
and+ selected_context = Selected_context.arg in
let common, config =
let builder =
let builder = Common.Builder.forbid_builds builder in
Expand All @@ -274,8 +302,8 @@ module Dump_dot_merlin = struct
in
Scheduler.go ~common ~config (fun () ->
match path with
| Some s -> Server.dump_dot_merlin s
| None -> Server.dump_dot_merlin ".")
| Some s -> Server.dump_dot_merlin ~selected_context s
| None -> Server.dump_dot_merlin ~selected_context ".")
;;

let command = Cmd.v info term
Expand Down
5 changes: 5 additions & 0 deletions doc/changes/10324.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Add new flag `--context` to `dune ocaml-merlin`, which allows to select a Dune
context when requesting Merlin config. Add `dune describe contexts`
subcommand. Introduce a field `generate_merlin_rules` for contexts declared in
the workspace, that allows to optionally produce Merlin rules for other
contexts besides the one selected for Merlin (#10324, @jchavarri)
3 changes: 3 additions & 0 deletions doc/reference/dune-workspace/context.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ the description of an opam switch, as follows:

- ``(merlin)`` instructs Dune to use this build context for Merlin.

- ``(generate_merlin_rules)`` instructs Dune to generate Merlin rules for this
context, even if it is not the one selected via ``(merlin)``.

- ``(profile <profile>)`` sets a different profile for a :term:`build context`. This has
precedence over the command-line option ``--profile``.

Expand Down
13 changes: 11 additions & 2 deletions src/dune_rules/context.ml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ module Builder = struct
extend_paths ~env paths
in
{ t with
merlin
merlin =
(match merlin with
| Selected -> true
| Rules_only | Not_selected -> false)
; profile
; dynamically_linked_foreign_archives
; instrument_with
Expand Down Expand Up @@ -610,7 +613,13 @@ module Group = struct
| Opam opam -> Builder.set_workspace_base builder opam.base
| Default default ->
let builder = Builder.set_workspace_base builder default.base in
let merlin = workspace.merlin_context = Some (Workspace.Context.name context) in
let merlin =
workspace.merlin_context = Some (Workspace.Context.name context)
||
match default.base.merlin with
| Rules_only -> true
| Not_selected | Selected -> false
in
{ builder with merlin }
in
match context with
Expand Down
47 changes: 40 additions & 7 deletions src/dune_rules/workspace.ml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,28 @@ module Context = struct
;;
end

module Merlin = struct
type t =
| Selected
| Rules_only
| Not_selected

let equal x y =
match x, y with
| Selected, Selected | Rules_only, Rules_only | Not_selected, Not_selected -> true
| Selected, (Rules_only | Not_selected)
| (Rules_only | Not_selected), Selected
| Rules_only, Not_selected
| Not_selected, Rules_only -> false
;;

let to_dyn : t -> Dyn.t = function
| Selected -> String "selected"
| Rules_only -> String "rules_only"
| Not_selected -> String "not_selected"
;;
end

module Common = struct
type t =
{ loc : Loc.t
Expand All @@ -279,7 +301,7 @@ module Context = struct
; fdo_target_exe : Path.t option
; dynamically_linked_foreign_archives : bool
; instrument_with : Lib_name.t list
; merlin : bool
; merlin : Merlin.t
}

let to_dyn { name; targets; host_context; _ } =
Expand Down Expand Up @@ -318,7 +340,7 @@ module Context = struct
dynamically_linked_foreign_archives
t.dynamically_linked_foreign_archives
&& List.equal Lib_name.equal instrument_with t.instrument_with
&& Bool.equal merlin t.merlin
&& Merlin.equal merlin t.merlin
;;

let fdo_suffix t =
Expand Down Expand Up @@ -384,7 +406,12 @@ module Context = struct
"instrument_with"
(Dune_lang.Syntax.since syntax (2, 7) >>> repeat Lib_name.decode)
and+ loc = loc
and+ merlin = field_b "merlin" in
and+ merlin = field_b "merlin"
and+ generate_merlin_rules =
field_b
~check:(Dune_lang.Syntax.since Stanza.syntax (3, 16))
"generate_merlin_rules"
in
fun ~profile_default ~instrument_with_default ->
let profile = Option.value profile ~default:profile_default in
let instrument_with =
Expand All @@ -409,7 +436,13 @@ module Context = struct
; fdo_target_exe
; dynamically_linked_foreign_archives
; instrument_with
; merlin
; merlin =
(match merlin with
| true -> Selected
| false ->
(match generate_merlin_rules with
| true -> Rules_only
| false -> Not_selected))
}
;;
end
Expand Down Expand Up @@ -571,7 +604,7 @@ module Context = struct
; fdo_target_exe = None
; dynamically_linked_foreign_archives = true
; instrument_with = Option.value instrument_with ~default:[]
; merlin = false
; merlin = Not_selected
}
}
;;
Expand Down Expand Up @@ -840,11 +873,11 @@ let step1 clflags =
!defined_names
(Context_name.Set.of_list (Context.all_names ctx));
match Context.base ctx, acc with
| { merlin = true; _ }, Some _ ->
| { merlin = Selected; _ }, Some _ ->
User_error.raise
~loc:(Context.loc ctx)
[ Pp.text "you can only have one context for merlin" ]
| { merlin = true; _ }, None -> Some name
| { merlin = Selected; _ }, None -> Some name
| _ -> acc)
in
let contexts =
Expand Down
12 changes: 11 additions & 1 deletion src/dune_rules/workspace.mli
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ module Context : sig
val equal : t -> t -> bool
end

module Merlin : sig
type t =
| Selected
| Rules_only
| Not_selected

val equal : t -> t -> bool
val to_dyn : t -> Dyn.t
end

module Common : sig
type t =
{ loc : Loc.t
Expand All @@ -57,7 +67,7 @@ module Context : sig
the runtime system. *)
; dynamically_linked_foreign_archives : bool
; instrument_with : Lib_name.t list
; merlin : bool
; merlin : Merlin.t
}
end

Expand Down
19 changes: 19 additions & 0 deletions test/blackbox-tests/test-cases/describe/describe-contexts.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Showcase behavior of the `dune describe contexts` subcommand

$ cat >dune-project <<EOF
> (lang dune 3.14)
> EOF

$ cat > dune-workspace << EOF
> (lang dune 3.14)
>
> (context default)
>
> (context
> (default
> (name alt)))
> EOF

$ dune describe contexts
alt
default
Loading
Loading