Skip to content

Commit

Permalink
feat(grainlsp): Implement inlay hints for module includes (#1793)
Browse files Browse the repository at this point in the history
* Add initial capability for inlay hints

* Added inlay hint capability

* Added simple test of printing out an inline value

* Debug

* Cleaned up and formatted the code

* Nit cleanup after review

* Remove whitespace

---------

Co-authored-by: marcusroberts <marcus@marcusr.com>
  • Loading branch information
marcusroberts and marcusroberts authored Apr 15, 2023
1 parent 4969d73 commit 408da76
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 0 deletions.
3 changes: 3 additions & 0 deletions compiler/src/language_server/driver.re
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ let process = msg => {
| TextDocumentHover(id, params) when is_initialized^ =>
Hover.process(~id, ~compiled_code, ~documents, params);
Reading;
| TextDocumentInlayHint(id, params) when is_initialized^ =>
Inlayhint.process(~id, ~compiled_code, ~documents, params);
Reading;
| TextDocumentCodeLens(id, params) when is_initialized^ =>
Lenses.process(~id, ~compiled_code, ~documents, params);
Reading;
Expand Down
5 changes: 5 additions & 0 deletions compiler/src/language_server/initialize.re
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ module ResponseResult = {
document_range_formatting_provider: bool,
[@key "renameProvider"]
rename_provider: bool,
[@key "inlayHintProvider"]
inlay_hint_provider: Protocol.inlay_hint_options,
};
[@deriving yojson]
type t = {capabilities: lsp_capabilities};
Expand All @@ -78,6 +80,9 @@ module ResponseResult = {
document_highlight_provider: false,
document_range_formatting_provider: false,
rename_provider: false,
inlay_hint_provider: {
resolve_provider: false,
},
};
};

Expand Down
84 changes: 84 additions & 0 deletions compiler/src/language_server/inlayhint.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
open Grain;
open Compile;
open Grain_parsing;
open Grain_utils;
open Grain_typed;
open Grain_diagnostics;
open Sourcetree;
open Lsp_types;

// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHintParams
module RequestParams = {
[@deriving yojson({strict: false})]
type t = {
[@key "textDocument"]
text_document: Protocol.text_document_identifier,
range: Protocol.range,
};
};

// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint
module ResponseResult = {
[@deriving yojson]
type inlay_hint = {
label: string,
position: Protocol.position,
};

[@deriving yojson]
type t = list(inlay_hint);
};

let send_no_result = (~id: Protocol.message_id) => {
Protocol.response(~id, `Null);
};

let find_hints = program => {
let hints = ref([]);
open Typedtree;
open Protocol;
module Iterator =
TypedtreeIter.MakeIterator({
include TypedtreeIter.DefaultIteratorArgument;
let enter_toplevel_stmt = (stmt: toplevel_stmt) => {
switch (stmt.ttop_desc) {
| TTopInclude(inc) =>
let path = inc.tinc_path;
let name = Path.name(inc.tinc_path);

let stmt_loc = stmt.ttop_loc;
let stmt_end = stmt_loc.loc_end;

let p: Protocol.position = {
line: stmt_end.pos_lnum - 1,
character: stmt_end.pos_cnum - stmt_end.pos_bol + 1 + 1,
};

let r: ResponseResult.inlay_hint = {
label: ": " ++ name,
position: p,
};
hints := [r, ...hints^];
| _ => ()
};
};
});
Iterator.iter_typed_program(program);
hints^;
};

let process =
(
~id: Protocol.message_id,
~compiled_code: Hashtbl.t(Protocol.uri, code),
~documents: Hashtbl.t(Protocol.uri, string),
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(program);
Protocol.response(~id, ResponseResult.to_yojson(hints));
};
};
22 changes: 22 additions & 0 deletions compiler/src/language_server/inlayhint.rei
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
open Grain_typed;

// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHintParams
module RequestParams: {
[@deriving yojson({strict: false})]
type t;
};

// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint
module ResponseResult: {
[@deriving yojson]
type t;
};

let process:
(
~id: Protocol.message_id,
~compiled_code: Hashtbl.t(Protocol.uri, Lsp_types.code),
~documents: Hashtbl.t(Protocol.uri, string),
RequestParams.t
) =>
unit;
6 changes: 6 additions & 0 deletions compiler/src/language_server/message.re
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type t =
| Exit(Protocol.message_id, Exit.RequestParams.t)
| TextDocumentDidOpen(Protocol.uri, Code_file.DidOpen.RequestParams.t)
| TextDocumentDidChange(Protocol.uri, Code_file.DidChange.RequestParams.t)
| TextDocumentInlayHint(Protocol.message_id, Inlayhint.RequestParams.t)
| Formatting(Protocol.message_id, Formatting.RequestParams.t)
| SetTrace(Protocol.trace_value)
| Unsupported
Expand All @@ -25,6 +26,11 @@ let of_request = (msg: Protocol.request_message): t => {
| Ok(params) => TextDocumentHover(id, params)
| Error(msg) => Error(msg)
}
| {method: "textDocument/inlayHint", id: Some(id), params: Some(params)} =>
switch (Inlayhint.RequestParams.of_yojson(params)) {
| Ok(params) => TextDocumentInlayHint(id, params)
| Error(msg) => Error(msg)
}
| {method: "textDocument/codeLens", id: Some(id), params: Some(params)} =>
switch (Lenses.RequestParams.of_yojson(params)) {
| Ok(params) => TextDocumentCodeLens(id, params)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/language_server/message.rei
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type t =
| Exit(Protocol.message_id, Exit.RequestParams.t)
| TextDocumentDidOpen(Protocol.uri, Code_file.DidOpen.RequestParams.t)
| TextDocumentDidChange(Protocol.uri, Code_file.DidChange.RequestParams.t)
| TextDocumentInlayHint(Protocol.message_id, Inlayhint.RequestParams.t)
| Formatting(Protocol.message_id, Formatting.RequestParams.t)
| SetTrace(Protocol.trace_value)
| Unsupported
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/language_server/protocol.re
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ let uri_to_yojson = (uri: Uri.t): Yojson.Safe.t =>
let uri_of_yojson = (json: Yojson.Safe.t) =>
json |> [%of_yojson: string] |> Result.map(Uri.of_string);

//https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHintOptions
[@deriving yojson]
type inlay_hint_options = {
[@key "resolveProvider"]
resolve_provider: bool,
};

type uri = [@to_yojson uri_to_yojson] [@of_yojson uri_of_yojson] Uri.t;

[@deriving yojson]
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/language_server/protocol.rei
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
open Grain_utils;

//https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHintOptions
[@deriving yojson]
type inlay_hint_options = {
[@key "resolveProvider"]
resolve_provider: bool,
};

[@deriving yojson]
type version;

Expand Down

0 comments on commit 408da76

Please sign in to comment.