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

feat(lsp): Add Inlay types #2005

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
chore: Remove cmdline toggle
  • Loading branch information
spotandjake committed Oct 4, 2024
commit e86c6f2ce985400e44df64fbee71164a21ddad8e
4 changes: 0 additions & 4 deletions cli/bin/grain.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,6 @@ program

program
.command("lsp")
.forwardOption(
"--disable-inlay-types",
"Disable's the language server's inlay type hints"
)
.description("start the Grain LSP server")
.action(exec.grainlsp);

Expand Down
2 changes: 0 additions & 2 deletions compiler/grainlsp/dune
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
(:include ./config/flags.sexp)))
(libraries cmdliner grain_utils grain_language_server grain_formatting
dune-build-info)
(preprocess
(pps ppx_deriving_cmdliner))
(js_of_ocaml
(flags --no-sourcemap --no-extern-fs --quiet)
(javascript_files hacks.js)))
21 changes: 5 additions & 16 deletions compiler/grainlsp/grainlsp.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,15 @@ open Cmdliner;
open Grain_utils;
open Grain_language_server;

[@deriving cmdliner]
type params = {
/**
A feature flag to disable inlay type hints.
*/
[@name "disable-inlay-types"]
disable_inlay_types: bool,
};

let run = opts => {
let run = () => {
set_binary_mode_in(stdin, true);
set_binary_mode_out(stdout, true);

let rec read_stdin = () => {
switch (Protocol.request()) {
| Error(err) => Trace.log("Failed to read message: " ++ err)
| Ok(msg) =>
switch (
Driver.process(~toggle_type_hints=!opts.disable_inlay_types, msg)
) {
switch (Driver.process(msg)) {
| Exit(code) => exit(code)
| Break => ()
| Reading => read_stdin()
Expand All @@ -31,8 +20,8 @@ let run = opts => {
read_stdin();
};

let lsp = opts =>
try(run(opts)) {
let lsp = () =>
try(run()) {
| exn =>
Format.eprintf("@[%s@]@.", Printexc.to_string(exn));
exit(2);
Expand All @@ -50,7 +39,7 @@ let cmd = {

Cmd.v(
Cmd.info(Sys.argv[0], ~version, ~doc),
Grain_utils.Config.with_cli_options(lsp) $ params_cmdliner_term(),
Grain_utils.Config.with_cli_options(lsp) $ const(),
);
};

Expand Down
10 changes: 2 additions & 8 deletions compiler/src/language_server/driver.re
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let compiled_code: Hashtbl.t(Protocol.uri, code) = Hashtbl.create(128);
let is_initialized = ref(false);
let is_shutting_down = ref(false);

let process = (~toggle_type_hints, msg) => {
let process = msg => {
switch (Message.of_request(msg)) {
| Initialize(id, params) =>
Trace.log("initializing");
Expand All @@ -26,13 +26,7 @@ let process = (~toggle_type_hints, msg) => {
Hover.process(~id, ~compiled_code, ~documents, params);
Reading;
| TextDocumentInlayHint(id, params) when is_initialized^ =>
Inlayhint.process(
~id,
~compiled_code,
~documents,
~toggle_type_hints,
params,
);
Inlayhint.process(~id, ~compiled_code, ~documents, params);
Reading;
| TextDocumentCodeLens(id, params) when is_initialized^ =>
Lenses.process(~id, ~compiled_code, ~documents, params);
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/language_server/driver.rei
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ type status =
| Break
| Exit(int);

let process: (~toggle_type_hints: bool, Protocol.request_message) => status;
let process: Protocol.request_message => status;
91 changes: 43 additions & 48 deletions compiler/src/language_server/inlayhint.re
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ let is_func_typ = (typ: Types.type_expr) => {
};
};

let find_hints = (~toggle_type_hints: bool, program) => {
let find_hints = program => {
let hints = ref([]);
open Typedtree;
open Protocol;
Expand All @@ -65,57 +65,53 @@ let find_hints = (~toggle_type_hints: bool, program) => {
include TypedtreeIter.DefaultIteratorArgument;

let enter_expression = ({exp_desc, exp_type}: expression) =>
if (toggle_type_hints) {
switch (exp_desc) {
| TExpLambda(bindings, _) =>
List.iter(
({mb_pat, mb_loc}: match_branch) => {
switch (mb_pat.pat_desc) {
| TPatTuple(args) =>
switch (resolve_typ(exp_type).desc) {
| TTyArrow(typ_args, _, _) =>
let argument_typs =
List.map(
((arg, typ: Types.type_expr)) =>
switch (arg) {
| Default(_) => None
| _ => Some(typ)
},
typ_args,
);
w;
if (List.length(argument_typs) == List.length(args)) {
List.iter(
((arg: pattern, typ: option(Types.type_expr))) => {
switch (arg.pat_desc, typ) {
| (TPatVar(_, _), Some(typ)) =>
let bind_end = arg.pat_loc.loc_end;
let p: Protocol.position = {
line: bind_end.pos_lnum - 1,
character: bind_end.pos_cnum - bind_end.pos_bol,
};
let typeSignature = string_of_typ(typ);
hints :=
[build_hint(p, typeSignature), ...hints^];
| _ => ()
}
switch (exp_desc) {
| TExpLambda(bindings, _) =>
List.iter(
({mb_pat, mb_loc}: match_branch) => {
switch (mb_pat.pat_desc) {
| TPatTuple(args) =>
switch (resolve_typ(exp_type).desc) {
| TTyArrow(typ_args, _, _) =>
let argument_typs =
List.map(
((arg, typ: Types.type_expr)) =>
switch (arg) {
| Default(_) => None
| _ => Some(typ)
},
List.combine(args, argument_typs),
);
};
| _ => ()
}
typ_args,
);
if (List.length(argument_typs) == List.length(args)) {
List.iter(
((arg: pattern, typ: option(Types.type_expr))) => {
switch (arg.pat_desc, typ) {
| (TPatVar(_, _), Some(typ)) =>
let bind_end = arg.pat_loc.loc_end;
let p: Protocol.position = {
line: bind_end.pos_lnum - 1,
character: bind_end.pos_cnum - bind_end.pos_bol,
};
let typeSignature = string_of_typ(typ);
hints := [build_hint(p, typeSignature), ...hints^];
| _ => ()
}
},
List.combine(args, argument_typs),
);
};
| _ => ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this ever be possible? If not should we do failwith("Impossible: ...")?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems as though there is a case where it can be a constructor.

}
},
bindings,
)
| _ => ()
};
| _ => ()
}
},
bindings,
)
| _ => ()
};

let enter_binding = ({vb_pat, vb_expr}: value_binding, toplevel: bool) =>
if (!toplevel && toggle_type_hints) {
if (!toplevel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: cut down on the condition nesting, perhaps if (!toplevel && toggle_type_hints) and then

switch (vb_pat) {
| {pat_extra: [], pat_desc: TPatVar(_, {loc}) => ...
| _ => ()
}

switch (vb_pat) {
| {pat_extra: [], pat_desc: TPatVar(_, {loc})} =>
let bind_end = loc.loc_end;
Expand All @@ -141,14 +137,13 @@ let process =
~id: Protocol.message_id,
~compiled_code: Hashtbl.t(Protocol.uri, code),
~documents: Hashtbl.t(Protocol.uri, string),
~toggle_type_hints: bool,
params: RequestParams.t,
) => {
Trace.log("Inlay hint request received");
switch (Hashtbl.find_opt(compiled_code, params.text_document.uri)) {
| None => send_no_result(~id)
| Some({program, sourcetree}) =>
let hints = find_hints(~toggle_type_hints, program);
let hints = find_hints(program);
Protocol.response(~id, ResponseResult.to_yojson(hints));
};
};
1 change: 0 additions & 1 deletion compiler/src/language_server/inlayhint.rei
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ let process:
~id: Protocol.message_id,
~compiled_code: Hashtbl.t(Protocol.uri, Lsp_types.code),
~documents: Hashtbl.t(Protocol.uri, string),
~toggle_type_hints: bool,
RequestParams.t
) =>
unit;
Loading