mirror of
https://github.com/nushell/nushell.git
synced 2025-01-13 09:48:30 +01:00
Fix "Char index out of bounds" Error (#11526)
# Description The code that converts Nushell's span into LSP line and character indices accidentally treated the span as character indices while they are byte indices. Fixes #11522. # User-Facing Changes None, just a bugfix.
This commit is contained in:
parent
0ebbc8f71c
commit
41119d3f88
@ -73,7 +73,7 @@ mod tests {
|
||||
use lsp_types::Url;
|
||||
use nu_test_support::fs::fixtures;
|
||||
|
||||
use crate::tests::{initialize_language_server, open, update};
|
||||
use crate::tests::{initialize_language_server, open_unchecked, update};
|
||||
|
||||
#[test]
|
||||
fn publish_diagnostics_variable_does_not_exists() {
|
||||
@ -85,7 +85,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
let notification = open(&client_connection, script.clone());
|
||||
let notification = open_unchecked(&client_connection, script.clone());
|
||||
|
||||
assert_json_eq!(
|
||||
notification,
|
||||
@ -116,7 +116,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
let notification = update(
|
||||
&client_connection,
|
||||
script.clone(),
|
||||
|
@ -180,7 +180,7 @@ impl LanguageServer {
|
||||
}
|
||||
|
||||
fn span_to_range(span: &Span, rope_of_file: &Rope, offset: usize) -> lsp_types::Range {
|
||||
let line = rope_of_file.char_to_line(span.start - offset);
|
||||
let line = rope_of_file.byte_to_line(span.start - offset);
|
||||
let character = span.start - offset - rope_of_file.line_to_char(line);
|
||||
|
||||
let start = lsp_types::Position {
|
||||
@ -188,7 +188,7 @@ impl LanguageServer {
|
||||
character: character as u32,
|
||||
};
|
||||
|
||||
let line = rope_of_file.char_to_line(span.end - offset);
|
||||
let line = rope_of_file.byte_to_line(span.end - offset);
|
||||
let character = span.end - offset - rope_of_file.line_to_char(line);
|
||||
|
||||
let end = lsp_types::Position {
|
||||
@ -704,8 +704,16 @@ mod tests {
|
||||
assert_json_eq!(result, serde_json::json!(null));
|
||||
}
|
||||
|
||||
pub fn open(client_connection: &Connection, uri: Url) -> lsp_server::Notification {
|
||||
let text = std::fs::read_to_string(uri.to_file_path().unwrap()).unwrap();
|
||||
pub fn open_unchecked(client_connection: &Connection, uri: Url) -> lsp_server::Notification {
|
||||
open(client_connection, uri).unwrap()
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
client_connection: &Connection,
|
||||
uri: Url,
|
||||
) -> Result<lsp_server::Notification, String> {
|
||||
let text =
|
||||
std::fs::read_to_string(uri.to_file_path().unwrap()).map_err(|e| e.to_string())?;
|
||||
|
||||
client_connection
|
||||
.sender
|
||||
@ -721,17 +729,17 @@ mod tests {
|
||||
})
|
||||
.unwrap(),
|
||||
}))
|
||||
.unwrap();
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let notification = client_connection
|
||||
.receiver
|
||||
.recv_timeout(Duration::from_secs(2))
|
||||
.unwrap();
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if let Message::Notification(n) = notification {
|
||||
n
|
||||
Ok(n)
|
||||
} else {
|
||||
panic!();
|
||||
Err(String::from("Did not receive a notification from server"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,7 +821,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = goto_definition(&client_connection, script.clone(), 2, 12);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -844,7 +852,7 @@ mod tests {
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = goto_definition(&client_connection, script.clone(), 4, 1);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -875,7 +883,7 @@ mod tests {
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = goto_definition(&client_connection, script.clone(), 1, 14);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -929,7 +937,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = hover(&client_connection, script.clone(), 2, 0);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -956,7 +964,7 @@ mod tests {
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = hover(&client_connection, script.clone(), 3, 0);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -1011,7 +1019,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = complete(&client_connection, script, 2, 9);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -1047,7 +1055,7 @@ mod tests {
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = complete(&client_connection, script, 0, 8);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -1073,4 +1081,41 @@ mod tests {
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complete_command_with_utf_line() {
|
||||
let (client_connection, _recv) = initialize_language_server();
|
||||
|
||||
let mut script = fixtures();
|
||||
script.push("lsp");
|
||||
script.push("completion");
|
||||
script.push("utf_pipeline.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = complete(&client_connection, script, 0, 14);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
response.result
|
||||
} else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
assert_json_eq!(
|
||||
result,
|
||||
serde_json::json!([
|
||||
{
|
||||
"label": "str trim",
|
||||
"detail": "Trim whitespace or specific character.",
|
||||
"textEdit": {
|
||||
"range": {
|
||||
"start": { "line": 0, "character": 9 },
|
||||
"end": { "line": 0, "character": 14 },
|
||||
},
|
||||
"newText": "str trim"
|
||||
}
|
||||
}
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ mod tests {
|
||||
use lsp_types::{Range, Url};
|
||||
use nu_test_support::fs::fixtures;
|
||||
|
||||
use crate::tests::{hover, initialize_language_server, open, update};
|
||||
use crate::tests::{hover, initialize_language_server, open, open_unchecked, update};
|
||||
|
||||
#[test]
|
||||
fn hover_correct_documentation_on_let() {
|
||||
@ -107,7 +107,7 @@ mod tests {
|
||||
script.push("var.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
|
||||
let resp = hover(&client_connection, script.clone(), 0, 0);
|
||||
let result = if let Message::Response(response) = resp {
|
||||
@ -137,7 +137,7 @@ mod tests {
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
update(
|
||||
&client_connection,
|
||||
script.clone(),
|
||||
@ -178,7 +178,7 @@ hello"#,
|
||||
script.push("command.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
open(&client_connection, script.clone());
|
||||
open_unchecked(&client_connection, script.clone());
|
||||
update(
|
||||
&client_connection,
|
||||
script.clone(),
|
||||
@ -212,4 +212,19 @@ hello"#,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_document_with_utf_char() {
|
||||
let (client_connection, _recv) = initialize_language_server();
|
||||
|
||||
let mut script = fixtures();
|
||||
script.push("lsp");
|
||||
script.push("notifications");
|
||||
script.push("issue_11522.nu");
|
||||
let script = Url::from_file_path(script).unwrap();
|
||||
|
||||
let result = open(&client_connection, script);
|
||||
|
||||
assert_eq!(result.map(|_| ()), Ok(()))
|
||||
}
|
||||
}
|
||||
|
1
tests/fixtures/lsp/completion/utf_pipeline.nu
vendored
Normal file
1
tests/fixtures/lsp/completion/utf_pipeline.nu
vendored
Normal file
@ -0,0 +1 @@
|
||||
" è " | str t
|
6
tests/fixtures/lsp/notifications/issue_11522.nu
vendored
Normal file
6
tests/fixtures/lsp/notifications/issue_11522.nu
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env nu
|
||||
|
||||
# Important to reproduce the crash
|
||||
# use a non ascii char somewhere in comments: è
|
||||
|
||||
[a b c d] | filter {
|
Loading…
Reference in New Issue
Block a user