diff --git a/merlin-lib.opam b/merlin-lib.opam index f715ee1f8..fa219e8b3 100644 --- a/merlin-lib.opam +++ b/merlin-lib.opam @@ -19,6 +19,7 @@ depends: [ "menhirSdk" {dev & = "20231231"} "yojson" {>= "2.0.0"} "ppx_yojson_conv" {>= "0.17.0"} + "ppx_jane" {>= "0.17.0"} ] synopsis: "Merlin's libraries" diff --git a/src/analysis/dune b/src/analysis/dune index f19629e87..943685e15 100644 --- a/src/analysis/dune +++ b/src/analysis/dune @@ -23,6 +23,7 @@ ocaml_parsing ocaml_preprocess query_protocol + query_protocol_kernel ocaml_typing ocaml_utils str diff --git a/src/commands/new_commands.ml b/src/commands/new_commands.ml index 2b5397aab..29088702d 100644 --- a/src/commands/new_commands.ml +++ b/src/commands/new_commands.ml @@ -480,9 +480,8 @@ let all_commands = "<%s> Which context to search for the identifier in" contexts) (Marg.param (Format.sprintf "<%s>" contexts) (fun ctx (prefix, pos, kind, _) -> - match Query_protocol.Locate_context.of_string ctx with - | Some ctx -> (prefix, pos, kind, Some ctx) - | None -> failwithf "invalid context %s." ctx))) + let ctx = Query_protocol.Locate_context.of_string ctx in + (prefix, pos, kind, Some ctx)))) ] ~doc: "Finds the declaration of entity at the specified position, Or \ diff --git a/src/commands/query_json.ml b/src/commands/query_json.ml index 64e0c093e..031c39d4d 100644 --- a/src/commands/query_json.ml +++ b/src/commands/query_json.ml @@ -40,17 +40,7 @@ let dump (type a) : a t -> json = in let kinds_to_json kind = `List - (List.map - ~f:(function - | `Constructor -> `String "constructor" - | `Keywords -> `String "keywords" - | `Labels -> `String "label" - | `Modules -> `String "module" - | `Modules_type -> `String "module-type" - | `Types -> `String "type" - | `Values -> `String "value" - | `Variants -> `String "variant") - kind) + (List.map ~f:(fun kind -> `String (Compl.In_kind.to_string kind)) kind) in function | Type_expr (expr, pos) -> @@ -224,19 +214,12 @@ let dump (type a) : a t -> json = mk "signature-help" [ ("position", mk_position position) ] | Version -> mk "version" [] -let string_of_completion_kind = function - | `Value -> "Value" - | `Variant -> "Variant" - | `Constructor -> "Constructor" - | `Label -> "Label" - | `Module -> "Module" - | `Modtype -> "Signature" - | `Type -> "Type" - | `Method -> "Method" - | `MethodCall -> "#" - | `Exn -> "Exn" - | `Class -> "Class" - | `Keyword -> "Keyword" +let string_of_completion_kind = + (* Merlin-jst: In upstream Merlin, the to_string logic lives here. But in Merlin-jst, + we've moved it to query_protocol_kernel so that it can be used in jsoo contexts *) + function + | #Compl.Out_kind.t as kind -> Compl.Out_kind.to_string kind + | #Outline_kind.t as kind -> Outline_kind.to_string kind let with_location ?(with_file = false) ?(skip_none = false) loc assoc = let with_file l = diff --git a/src/frontend/kernel/completion_kind.ml b/src/frontend/kernel/completion_kind.ml new file mode 100644 index 000000000..4b4ad8068 --- /dev/null +++ b/src/frontend/kernel/completion_kind.ml @@ -0,0 +1,88 @@ +module In = struct + type t = + [ `Constructor + | `Labels + | `Modules + | `Modules_type + | `Types + | `Values + | `Variants + | `Keywords ] + [@@deriving enumerate, equal] + + let to_string = function + | `Constructor -> "constructor" + | `Keywords -> "keywords" + | `Labels -> "label" + | `Modules -> "module" + | `Modules_type -> "module-type" + | `Types -> "type" + | `Values -> "value" + | `Variants -> "variant" + + let of_string_opt = function + | "t" | "type" | "types" -> Some `Types + | "v" | "val" | "value" | "values" -> Some `Values + | "variant" | "variants" | "var" -> Some `Variants + | "c" | "constr" | "constructor" -> Some `Constructor + | "l" | "label" | "labels" -> Some `Labels + | "m" | "mod" | "module" -> Some `Modules + | "mt" | "modtype" | "module-type" -> Some `Modules_type + | "k" | "kw" | "keyword" | "keywords" -> Some `Keywords + | _ -> None +end + +module Out = struct + (* CR-someday: This module is necessary because ppx_string_conv doesn't currently + (v0.17.0) support polymorphic variants. *) + module For_deriving = struct + type t = + | Value [@rename "Value"] + | Constructor [@rename "Constructor"] + | Variant [@rename "Variant"] + | Label [@rename "Label"] + | Module [@rename "Module"] + | Modtype [@rename "Signature"] + | Type [@rename "Type"] + | MethodCall [@rename "#"] + | Keyword [@rename "Keyword"] + [@@deriving string] + + let to_poly = function + | Value -> `Value + | Constructor -> `Constructor + | Variant -> `Variant + | Label -> `Label + | Module -> `Module + | Modtype -> `Modtype + | Type -> `Type + | MethodCall -> `MethodCall + | Keyword -> `Keyword + + let of_poly = function + | `Value -> Value + | `Constructor -> Constructor + | `Variant -> Variant + | `Label -> Label + | `Module -> Module + | `Modtype -> Modtype + | `Type -> Type + | `MethodCall -> MethodCall + | `Keyword -> Keyword + end + + type t = + [ `Value + | `Constructor + | `Variant + | `Label + | `Module + | `Modtype + | `Type + | `MethodCall + | `Keyword ] + [@@deriving enumerate, equal] + + let to_string x = For_deriving.of_poly x |> For_deriving.to_string + let of_string s = For_deriving.of_string s |> For_deriving.to_poly +end diff --git a/src/frontend/kernel/completion_kind.mli b/src/frontend/kernel/completion_kind.mli new file mode 100644 index 000000000..2676dfd8d --- /dev/null +++ b/src/frontend/kernel/completion_kind.mli @@ -0,0 +1,28 @@ +module In : sig + type t = + [ `Constructor + | `Labels + | `Modules + | `Modules_type + | `Types + | `Values + | `Variants + | `Keywords ] + [@@deriving to_string, enumerate, equal] + + val of_string_opt : string -> t option +end + +module Out : sig + type t = + [ `Value + | `Constructor + | `Variant + | `Label + | `Module + | `Modtype + | `Type + | `MethodCall + | `Keyword ] + [@@deriving string, enumerate, equal] +end diff --git a/src/frontend/kernel/dune b/src/frontend/kernel/dune index 79b296275..ec42db942 100644 --- a/src/frontend/kernel/dune +++ b/src/frontend/kernel/dune @@ -2,4 +2,4 @@ (name query_protocol_kernel) (public_name merlin-lib.query_protocol_kernel) (libraries yojson) - (preprocess (pps ppx_yojson_conv))) + (preprocess (pps ppx_jane ppx_yojson_conv))) diff --git a/src/frontend/kernel/locate_context.ml b/src/frontend/kernel/locate_context.ml new file mode 100644 index 000000000..9a11ed3b0 --- /dev/null +++ b/src/frontend/kernel/locate_context.ml @@ -0,0 +1,11 @@ +type t = + | Expr [@rename "expr"] + | Module_path [@rename "module_path"] + | Module_type [@rename "module_type"] + | Patt [@rename "pattern"] + | Type [@rename "type"] + | Constant [@rename "constant"] + | Constructor [@rename "constructor"] + | Label [@rename "label"] + | Unknown [@rename "unknown"] +[@@deriving string ~case_insensitive, enumerate] diff --git a/src/frontend/kernel/locate_context.mli b/src/frontend/kernel/locate_context.mli new file mode 100644 index 000000000..bd6e1892f --- /dev/null +++ b/src/frontend/kernel/locate_context.mli @@ -0,0 +1,11 @@ +type t = + | Expr + | Module_path + | Module_type + | Patt + | Type + | Constant + | Constructor + | Label + | Unknown +[@@deriving string, enumerate] diff --git a/src/frontend/kernel/locate_type_multi_result.ml b/src/frontend/kernel/locate_type_multi_result.ml new file mode 100644 index 000000000..3fb27cb39 --- /dev/null +++ b/src/frontend/kernel/locate_type_multi_result.ml @@ -0,0 +1,33 @@ +(* This module contains definitions that can be used in a js-of-ocaml environment. This + is useful because it allows VSCode extensions (which run in javascript) to use the + serializers/deserializers defined in this module. *) + +open Ppx_yojson_conv_lib.Yojson_conv.Primitives + +module Lexing = struct + include Lexing + + type nonrec position = position = + { pos_fname : string; pos_lnum : int; pos_bol : int; pos_cnum : int } + [@@deriving yojson] +end + +type node_data = + | Arrow + | Tuple + | Object + | Type_ref of + { type_ : string; + result : + [ `Found of string option * Lexing.position + | `Builtin of string + | `Not_in_env of string + | `File_not_found of string + | `Not_found of string * string option ] + } +[@@deriving yojson] + +type type_tree = { data : node_data; children : type_tree list } +[@@deriving yojson] + +type t = Success of type_tree | Invalid_context [@@deriving yojson] diff --git a/src/frontend/kernel/locate_type_multi_result.mli b/src/frontend/kernel/locate_type_multi_result.mli new file mode 100644 index 000000000..f8afa40ec --- /dev/null +++ b/src/frontend/kernel/locate_type_multi_result.mli @@ -0,0 +1,19 @@ +type node_data = + | Arrow + | Tuple + | Object + | Type_ref of + { type_ : string; + result : + [ `Found of string option * Lexing.position + | `Builtin of string + | `Not_in_env of string + | `File_not_found of string + | `Not_found of string * string option ] + } +[@@deriving yojson] + +type type_tree = { data : node_data; children : type_tree list } +[@@deriving yojson] + +type t = Success of type_tree | Invalid_context [@@deriving yojson] diff --git a/src/frontend/kernel/outline_kind.ml b/src/frontend/kernel/outline_kind.ml new file mode 100644 index 000000000..80b164a2c --- /dev/null +++ b/src/frontend/kernel/outline_kind.ml @@ -0,0 +1,50 @@ +module For_deriving = struct + type t = + | Value [@rename "Value"] + | Constructor [@rename "Constructor"] + | Label [@rename "Label"] + | Module [@rename "Module"] + | Modtype [@rename "Signature"] + | Type [@rename "Type"] + | Exn [@rename "Exn"] + | Class [@rename "Class"] + | Method [@rename "Method"] + [@@deriving string] + + let to_poly = function + | Value -> `Value + | Constructor -> `Constructor + | Label -> `Label + | Module -> `Module + | Modtype -> `Modtype + | Type -> `Type + | Exn -> `Exn + | Class -> `Class + | Method -> `Method + + let of_poly = function + | `Value -> Value + | `Constructor -> Constructor + | `Label -> Label + | `Module -> Module + | `Modtype -> Modtype + | `Type -> Type + | `Exn -> Exn + | `Class -> Class + | `Method -> Method +end + +type t = + [ `Value + | `Constructor + | `Label + | `Module + | `Modtype + | `Type + | `Exn + | `Class + | `Method ] +[@@deriving equal, enumerate] + +let to_string x = For_deriving.of_poly x |> For_deriving.to_string +let of_string s = For_deriving.of_string s |> For_deriving.to_poly diff --git a/src/frontend/kernel/outline_kind.mli b/src/frontend/kernel/outline_kind.mli new file mode 100644 index 000000000..2df662c05 --- /dev/null +++ b/src/frontend/kernel/outline_kind.mli @@ -0,0 +1,11 @@ +type t = + [ `Value + | `Constructor + | `Label + | `Module + | `Modtype + | `Type + | `Exn + | `Class + | `Method ] +[@@deriving string, equal, enumerate] diff --git a/src/frontend/kernel/query_protocol_kernel.ml b/src/frontend/kernel/query_protocol_kernel.ml index f4caab6da..a1db11239 100644 --- a/src/frontend/kernel/query_protocol_kernel.ml +++ b/src/frontend/kernel/query_protocol_kernel.ml @@ -2,38 +2,7 @@ is useful because it allows VSCode extensions (which run in javascript) to use the serializers/deserializers defined in this module. *) -open struct - include Ppx_yojson_conv_lib.Yojson_conv.Primitives - - module Lexing = struct - include Lexing - - type nonrec position = position = - { pos_fname : string; pos_lnum : int; pos_bol : int; pos_cnum : int } - [@@deriving yojson] - end -end - -module Locate_type_multi_result = struct - open Ppx_yojson_conv_lib.Yojson_conv.Primitives - - type node_data = - | Arrow - | Tuple - | Object - | Type_ref of - { type_ : string; - result : - [ `Found of string option * Lexing.position - | `Builtin of string - | `Not_in_env of string - | `File_not_found of string - | `Not_found of string * string option ] - } - [@@deriving yojson] - - type type_tree = { data : node_data; children : type_tree list } - [@@deriving yojson] - - type t = Success of type_tree | Invalid_context [@@deriving yojson] -end +module Completion_kind = Completion_kind +module Locate_context = Locate_context +module Locate_type_multi_result = Locate_type_multi_result +module Outline_kind = Outline_kind diff --git a/src/frontend/query_protocol.ml b/src/frontend/query_protocol.ml index 553eafeb7..fa5252f5b 100644 --- a/src/frontend/query_protocol.ml +++ b/src/frontend/query_protocol.ml @@ -29,18 +29,11 @@ include Query_protocol_kernel module Compl = struct + module Out_kind = Completion_kind.Out + type 'desc raw_entry = { name : string; - kind : - [ `Value - | `Constructor - | `Variant - | `Label - | `Module - | `Modtype - | `Type - | `MethodCall - | `Keyword ]; + kind : Out_kind.t; desc : 'desc; info : 'desc; deprecated : bool @@ -56,15 +49,8 @@ module Compl = struct context : [ `Unknown | `Application of application_context ] } - type kind = - [ `Constructor - | `Labels - | `Modules - | `Modules_type - | `Types - | `Values - | `Variants - | `Keywords ] + module In_kind = Completion_kind.In + type kind = In_kind.t end type completions = Compl.t @@ -81,16 +67,7 @@ type 'a type_search_result = type outline = item list and item = { outline_name : string; - outline_kind : - [ `Value - | `Constructor - | `Label - | `Module - | `Modtype - | `Type - | `Exn - | `Class - | `Method ]; + outline_kind : Outline_kind.t; outline_type : string option; deprecated : bool; location : Location_aux.t; @@ -133,53 +110,7 @@ type occurrences_status = type occurrence = { loc : Location.t; is_stale : bool } -module Locate_context = struct - type t = - | Expr - | Module_path - | Module_type - | Patt - | Type - | Constant - | Constructor - | Label - | Unknown - - let to_string = function - | Expr -> "expr" - | Module_path -> "module_path" - | Module_type -> "module_type" - | Patt -> "pattern" - | Type -> "type" - | Constant -> "constant" - | Constructor -> "constructor" - | Label -> "label" - | Unknown -> "unknown" - - let of_string = function - | "expr" -> Some Expr - | "module_path" -> Some Module_path - | "module_type" -> Some Module_type - | "pattern" -> Some Patt - | "type" -> Some Type - | "constant" -> Some Constant - | "constructor" -> Some Constructor - | "label" -> Some Label - | "unknown" -> Some Unknown - | _ -> None - - let all = - [ Expr; - Module_path; - Module_type; - Patt; - Type; - Constant; - Constructor; - Label; - Unknown - ] -end +module Locate_context = Locate_context type _ t = | Type_expr (* *) : string * Msource.position -> string t