mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 10:25:42 +02:00
Send LSP Completion Item Kind (#11443)
# Description This commit fills in the completion item kind into the `textDocument/completion` response so that LSP client can present more information to the user. It is an improvement in the context of #10794 # User-Facing Changes Improved information display in editor's intelli-sense menu 
This commit is contained in:
@ -11,18 +11,18 @@ use std::{
|
||||
use lsp_server::{Connection, IoThreads, Message, Response, ResponseError};
|
||||
use lsp_types::{
|
||||
request::{Completion, GotoDefinition, HoverRequest, Request},
|
||||
CompletionItem, CompletionParams, CompletionResponse, CompletionTextEdit, GotoDefinitionParams,
|
||||
GotoDefinitionResponse, Hover, HoverContents, HoverParams, Location, MarkupContent, MarkupKind,
|
||||
OneOf, Range, ServerCapabilities, TextDocumentSyncKind, TextEdit, Url,
|
||||
CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, CompletionTextEdit,
|
||||
GotoDefinitionParams, GotoDefinitionResponse, Hover, HoverContents, HoverParams, Location,
|
||||
MarkupContent, MarkupKind, OneOf, Range, ServerCapabilities, TextDocumentSyncKind, TextEdit,
|
||||
Url,
|
||||
};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use nu_cli::NuCompleter;
|
||||
use nu_cli::{NuCompleter, SuggestionKind};
|
||||
use nu_parser::{flatten_block, parse, FlatShape};
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
DeclId, Span, Value, VarId,
|
||||
};
|
||||
use reedline::Completer;
|
||||
use ropey::Rope;
|
||||
|
||||
mod diagnostics;
|
||||
@ -559,7 +559,8 @@ impl LanguageServer {
|
||||
|
||||
let location =
|
||||
Self::lsp_position_to_location(¶ms.text_document_position.position, rope_of_file);
|
||||
let results = completer.complete(&rope_of_file.to_string()[..location], location);
|
||||
let results =
|
||||
completer.fetch_completions_at(&rope_of_file.to_string()[..location], location);
|
||||
if results.is_empty() {
|
||||
None
|
||||
} else {
|
||||
@ -568,17 +569,18 @@ impl LanguageServer {
|
||||
.into_iter()
|
||||
.map(|r| {
|
||||
let mut start = params.text_document_position.position;
|
||||
start.character -= (r.span.end - r.span.start) as u32;
|
||||
start.character -= (r.suggestion.span.end - r.suggestion.span.start) as u32;
|
||||
|
||||
CompletionItem {
|
||||
label: r.value.clone(),
|
||||
detail: r.description,
|
||||
label: r.suggestion.value.clone(),
|
||||
detail: r.suggestion.description,
|
||||
kind: Self::lsp_completion_item_kind(r.kind),
|
||||
text_edit: Some(CompletionTextEdit::Edit(TextEdit {
|
||||
range: Range {
|
||||
start,
|
||||
end: params.text_document_position.position,
|
||||
},
|
||||
new_text: r.value,
|
||||
new_text: r.suggestion.value,
|
||||
})),
|
||||
..Default::default()
|
||||
}
|
||||
@ -587,12 +589,28 @@ impl LanguageServer {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn lsp_completion_item_kind(
|
||||
suggestion_kind: Option<SuggestionKind>,
|
||||
) -> Option<CompletionItemKind> {
|
||||
suggestion_kind.and_then(|suggestion_kind| match suggestion_kind {
|
||||
SuggestionKind::Type(t) => match t {
|
||||
nu_protocol::Type::String => Some(CompletionItemKind::VARIABLE),
|
||||
_ => None,
|
||||
},
|
||||
SuggestionKind::Command(c) => match c {
|
||||
nu_protocol::engine::CommandType::Keyword => Some(CompletionItemKind::KEYWORD),
|
||||
nu_protocol::engine::CommandType::Builtin => Some(CompletionItemKind::FUNCTION),
|
||||
_ => None,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use assert_json_diff::assert_json_eq;
|
||||
use assert_json_diff::{assert_json_eq, assert_json_include};
|
||||
use lsp_types::{
|
||||
notification::{
|
||||
DidChangeTextDocument, DidOpenTextDocument, Exit, Initialized, Notification,
|
||||
@ -1078,7 +1096,8 @@ mod tests {
|
||||
"start": { "character": 5, "line": 2 },
|
||||
"end": { "character": 9, "line": 2 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": 6
|
||||
}
|
||||
])
|
||||
);
|
||||
@ -1115,7 +1134,8 @@ mod tests {
|
||||
"end": { "line": 0, "character": 8 },
|
||||
},
|
||||
"newText": "config nu"
|
||||
}
|
||||
},
|
||||
"kind": 3
|
||||
}
|
||||
])
|
||||
);
|
||||
@ -1152,7 +1172,45 @@ mod tests {
|
||||
"end": { "line": 0, "character": 14 },
|
||||
},
|
||||
"newText": "str trim"
|
||||
}
|
||||
},
|
||||
"kind": 3
|
||||
}
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complete_keyword() {
|
||||
let (client_connection, _recv) = initialize_language_server();
|
||||
|
||||
let mut script = fixtures();
|
||||
script.push("lsp");
|
||||
script.push("completion");
|
||||
script.push("keyword.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = complete(&client_connection, script, 0, 2);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
response.result
|
||||
} else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
assert_json_include!(
|
||||
actual: result,
|
||||
expected: serde_json::json!([
|
||||
{
|
||||
"label": "def",
|
||||
"textEdit": {
|
||||
"newText": "def",
|
||||
"range": {
|
||||
"start": { "character": 0, "line": 0 },
|
||||
"end": { "character": 2, "line": 0 }
|
||||
}
|
||||
},
|
||||
"kind": 14
|
||||
}
|
||||
])
|
||||
);
|
||||
|
Reference in New Issue
Block a user