refactor(lsp): span fix made easy by bumping lsp-textdocument to 0.4.2 (#15287)

# Description

The upstream crate fixed a bug of position calc, which made some extra
checking in lsp unnecessary.
Also moved some follow-up fixing of #15238 from #15270 here, as it has
something to do with previous position calc bug.

# User-Facing Changes

# Tests + Formatting

Adjusted

# After Submitting
This commit is contained in:
zc he 2025-03-11 19:13:58 +08:00 committed by GitHub
parent 2dab65f852
commit 81e496673e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 34 additions and 43 deletions

6
Cargo.lock generated
View File

@ -3105,9 +3105,9 @@ dependencies = [
[[package]] [[package]]
name = "lsp-textdocument" name = "lsp-textdocument"
version = "0.4.1" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a17dcde15cae78fb2e54166da22cd6c53f48033a0391cc392b22f2437805792" checksum = "2d564d595f4e3dcd3c071bf472dbd2cac53bc3665ae7222d2abfecd18feaed2c"
dependencies = [ dependencies = [
"lsp-types", "lsp-types",
"serde_json", "serde_json",
@ -8078,7 +8078,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]

View File

@ -104,7 +104,7 @@ lru = "0.12"
lscolors = { version = "0.17", default-features = false } lscolors = { version = "0.17", default-features = false }
lsp-server = "0.7.8" lsp-server = "0.7.8"
lsp-types = { version = "0.97.0", features = ["proposed"] } lsp-types = { version = "0.97.0", features = ["proposed"] }
lsp-textdocument = "0.4.1" lsp-textdocument = "0.4.2"
mach2 = "0.4" mach2 = "0.4"
md5 = { version = "0.10", package = "md-5" } md5 = { version = "0.10", package = "md-5" }
miette = "7.5" miette = "7.5"

View File

@ -307,9 +307,8 @@ impl NuCompleter {
let need_externals = !prefix_str.contains(' '); let need_externals = !prefix_str.contains(' ');
let need_internals = !prefix_str.starts_with('^'); let need_internals = !prefix_str.starts_with('^');
let mut span = element_expression.span; let mut span = element_expression.span;
span.end = std::cmp::min(span.end, pos + 1);
if !need_internals { if !need_internals {
span = Span::new(span.start + 1, span.end) span.start += 1;
}; };
suggestions.extend(self.command_completion_helper( suggestions.extend(self.command_completion_helper(
working_set, working_set,

View File

@ -1,13 +1,15 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{uri_to_path, LanguageServer}; use crate::{span_to_range, uri_to_path, LanguageServer};
use lsp_types::{ use lsp_types::{
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionParams, CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionParams,
CompletionResponse, CompletionTextEdit, Documentation, MarkupContent, MarkupKind, Range, CompletionResponse, CompletionTextEdit, Documentation, MarkupContent, MarkupKind, TextEdit,
TextEdit,
}; };
use nu_cli::{NuCompleter, SuggestionKind}; use nu_cli::{NuCompleter, SuggestionKind};
use nu_protocol::engine::{CommandType, Stack}; use nu_protocol::{
engine::{CommandType, Stack},
Span,
};
impl LanguageServer { impl LanguageServer {
pub(crate) fn complete(&mut self, params: &CompletionParams) -> Option<CompletionResponse> { pub(crate) fn complete(&mut self, params: &CompletionParams) -> Option<CompletionResponse> {
@ -44,17 +46,12 @@ impl LanguageServer {
) )
}; };
let docs = self.docs.lock().ok()?;
let file = docs.get_document(&path_uri)?;
(!results.is_empty()).then_some(CompletionResponse::Array( (!results.is_empty()).then_some(CompletionResponse::Array(
results results
.into_iter() .into_iter()
.map(|r| { .map(|r| {
let mut start = params.text_document_position.position;
start.character = start.character.saturating_sub(
r.suggestion
.span
.end
.saturating_sub(r.suggestion.span.start) as u32,
);
let decl_id = r.kind.clone().and_then(|kind| { let decl_id = r.kind.clone().and_then(|kind| {
matches!(kind, SuggestionKind::Command(_)) matches!(kind, SuggestionKind::Command(_))
.then_some(engine_state.find_decl(r.suggestion.value.as_bytes(), &[])?) .then_some(engine_state.find_decl(r.suggestion.value.as_bytes(), &[])?)
@ -64,8 +61,17 @@ impl LanguageServer {
if r.suggestion.append_whitespace { if r.suggestion.append_whitespace {
label_value.push(' '); label_value.push(' ');
} }
let span = r.suggestion.span;
let range = span_to_range(&Span::new(span.start, span.end), file, 0);
let text_edit = Some(CompletionTextEdit::Edit(TextEdit {
range,
new_text: label_value.clone(),
}));
CompletionItem { CompletionItem {
label: label_value.clone(), label: label_value,
label_details: r label_details: r
.kind .kind
.clone() .clone()
@ -97,13 +103,7 @@ impl LanguageServer {
}) })
}), }),
kind: Self::lsp_completion_item_kind(r.kind), kind: Self::lsp_completion_item_kind(r.kind),
text_edit: Some(CompletionTextEdit::Edit(TextEdit { text_edit,
range: Range {
start,
end: params.text_document_position.position,
},
new_text: label_value,
})),
..Default::default() ..Default::default()
} }
}) })
@ -230,16 +230,14 @@ mod tests {
actual: result_from_message(resp), actual: result_from_message(resp),
expected: serde_json::json!([ expected: serde_json::json!([
// defined after the cursor // defined after the cursor
{
"label": "config ",
"detail": "Edit nushell configuration files.",
"textEdit": { "range": { "start": { "line": 0, "character": 0 }, "end": { "line": 0, "character": 6 }, },
"newText": "config "
},
},
{ "label": "config env ", "kind": 3 },
{ "label": "config flatten ", "kind": 3 },
{ "label": "config n foo bar ", "detail": detail_str, "kind": 2 }, { "label": "config n foo bar ", "detail": detail_str, "kind": 2 },
{
"label": "config nu ",
"detail": "Edit nu configurations.",
"textEdit": { "range": { "start": { "line": 0, "character": 0 }, "end": { "line": 0, "character": 8 }, },
"newText": "config nu "
}
},
]) ])
); );

View File

@ -80,27 +80,21 @@ impl LanguageServer {
if sp < last_span { if sp < last_span {
continue; continue;
} }
// in case the start position is at the end of lastline let mut delta_start = range.start.character;
let real_start_char = if range.end.line != range.start.line {
0
} else {
range.start.character
};
let mut delta_start = real_start_char;
if range.end.line == last_token_line { if range.end.line == last_token_line {
delta_start -= last_token_char; delta_start -= last_token_char;
} }
tokens.push(SemanticToken { tokens.push(SemanticToken {
delta_start, delta_start,
delta_line: range.end.line.saturating_sub(last_token_line), delta_line: range.end.line.saturating_sub(last_token_line),
length: range.end.character.saturating_sub(real_start_char), length: range.end.character.saturating_sub(range.start.character),
// 0 means function in semantic_token_legend // 0 means function in semantic_token_legend
token_type: 0, token_type: 0,
token_modifiers_bitset: 0, token_modifiers_bitset: 0,
}); });
last_span = sp; last_span = sp;
last_token_line = range.end.line; last_token_line = range.end.line;
last_token_char = real_start_char; last_token_char = range.start.character;
} }
tokens tokens
} }