diff --git a/lsp/lsp-harness/src/lib.rs b/lsp/lsp-harness/src/lib.rs index 061888bf..2829ee2b 100644 --- a/lsp/lsp-harness/src/lib.rs +++ b/lsp/lsp-harness/src/lib.rs @@ -4,8 +4,8 @@ mod output; pub use jsonrpc::Server; use log::error; use lsp_types::{ - GotoDefinitionParams, Location, Position, Range, TextDocumentIdentifier, - TextDocumentPositionParams, Url, + CompletionContext, CompletionParams, GotoDefinitionParams, Location, Position, Range, + TextDocumentIdentifier, TextDocumentPositionParams, Url, }; pub use output::LspDebug; @@ -34,6 +34,7 @@ pub struct TestFile { /// A subset of LSP requests that our harness supports. pub enum Request { GotoDefinition(GotoDefinitionParams), + Completion(CompletionParams), } /// A private FromStr, with simpler error handling and (because it's @@ -92,6 +93,28 @@ impl Parse for Request { work_done_progress_params: Default::default(), partial_result_params: Default::default(), })), + // The format of a Completion request is the file:line:char location, + // followed by an optional trigger character. + "Completion" => { + let (pos, context) = if let Some((pos, trigger)) = params.split_once(' ') { + ( + pos, + Some(CompletionContext { + trigger_kind: lsp_types::CompletionTriggerKind::TriggerCharacter, + trigger_character: Some(trigger.to_owned()), + }), + ) + } else { + (params, None) + }; + Some(Request::Completion(CompletionParams { + text_document_position: TextDocumentPositionParams::parse(pos)?, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context, + })) + } + _ => None, } } diff --git a/lsp/lsp-harness/src/output.rs b/lsp/lsp-harness/src/output.rs index fe1007bd..4d69b0a7 100644 --- a/lsp/lsp-harness/src/output.rs +++ b/lsp/lsp-harness/src/output.rs @@ -85,3 +85,27 @@ impl LspDebug for lsp_types::GotoDefinitionResponse { } } } + +impl LspDebug for lsp_types::CompletionItem { + fn debug(&self, mut w: impl Write) -> std::io::Result<()> { + write!(w, "{}", self.label) + } +} + +impl LspDebug for lsp_types::CompletionResponse { + fn debug(&self, w: impl Write) -> std::io::Result<()> { + match self { + lsp_types::CompletionResponse::Array(items) => { + // The order of completions is non-deterministic, so sort them. + let mut items = items.clone(); + items.sort_by_key(|i| i.label.clone()); + Iter(items.iter()).debug(w) + } + lsp_types::CompletionResponse::List(list) => { + let mut items = list.items.clone(); + items.sort_by_key(|i| i.label.clone()); + Iter(list.items.iter()).debug(w) + } + } + } +} diff --git a/lsp/nls/tests/inputs/completion-basic.ncl b/lsp/nls/tests/inputs/completion-basic.ncl new file mode 100644 index 00000000..bd1b8ade --- /dev/null +++ b/lsp/nls/tests/inputs/completion-basic.ncl @@ -0,0 +1,17 @@ +### /completion-basic.ncl +let config = { + version = "1.2", + verified = { really = true }, + foo = "bar", +} +in +{ + a = config.version, + b = config.verified.really, +} +### Completion /completion-basic.ncl:7:12 +### Completion /completion-basic.ncl:7:15 . +### Completion /completion-basic.ncl:8:15 . +### Completion /completion-basic.ncl:8:23 +### Completion /completion-basic.ncl:8:24 . +### Completion /completion-basic.ncl:8:27 diff --git a/lsp/nls/tests/main.rs b/lsp/nls/tests/main.rs index 6427bf96..0eb42b86 100644 --- a/lsp/nls/tests/main.rs +++ b/lsp/nls/tests/main.rs @@ -1,5 +1,5 @@ use assert_cmd::cargo::CommandCargoExt; -use lsp_types::request::{GotoDefinition, Request as LspRequest}; +use lsp_types::request::{Completion, GotoDefinition, Request as LspRequest}; use nickel_lang_utils::project_root::project_root; use test_generator::test_resources; @@ -32,6 +32,7 @@ impl TestHarness { fn request_dyn(&mut self, req: Request) { match req { Request::GotoDefinition(d) => self.request::(d), + Request::Completion(c) => self.request::(c), } } diff --git a/lsp/nls/tests/snapshots/main__lsp__nls__tests__inputs__completion-basic.ncl.snap b/lsp/nls/tests/snapshots/main__lsp__nls__tests__inputs__completion-basic.ncl.snap new file mode 100644 index 00000000..135a2612 --- /dev/null +++ b/lsp/nls/tests/snapshots/main__lsp__nls__tests__inputs__completion-basic.ncl.snap @@ -0,0 +1,11 @@ +--- +source: lsp/nls/tests/main.rs +expression: output +--- +[a, b, config] +[foo, verified, version] +[foo, verified, version] +[foo, verified, version] +[really] +[really] +