fix(lsp): exit on null root_dir (#15051)

# Description

This PR fixes one reported bug of recent lsp changes.

It exit unexpectedly with empty `root_dir` settings in neovim.

# User-Facing Changes

# Tests + Formatting

+1 test case

# After Submitting
This commit is contained in:
zc he 2025-02-08 20:49:38 +08:00 committed by GitHub
parent 2891867de9
commit 9fa2f43d06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 72 additions and 43 deletions

View File

@ -151,7 +151,7 @@ impl LanguageServer {
!self.initial_engine_state.signals().interrupted()
})
.into_diagnostic()?;
self.initialize_workspace_folders(init_params)?;
self.initialize_workspace_folders(init_params);
while !self.initial_engine_state.signals().interrupted() {
// first check new messages from child thread
@ -730,7 +730,7 @@ mod tests {
DidChangeTextDocument, DidOpenTextDocument, Exit, Initialized, Notification,
},
request::{Completion, HoverRequest, Initialize, Request, Shutdown},
CompletionParams, DidChangeTextDocumentParams, DidOpenTextDocumentParams, InitializeParams,
CompletionParams, DidChangeTextDocumentParams, DidOpenTextDocumentParams,
InitializedParams, PartialResultParams, Position, TextDocumentContentChangeEvent,
TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams,
WorkDoneProgressParams,
@ -740,7 +740,7 @@ mod tests {
use std::time::Duration;
pub(crate) fn initialize_language_server(
params: Option<InitializeParams>,
params: Option<serde_json::Value>,
) -> (Connection, Receiver<Result<()>>) {
use std::sync::mpsc;
let (client_connection, server_connection) = Connection::memory();
@ -757,7 +757,7 @@ mod tests {
.send(Message::Request(lsp_server::Request {
id: 1.into(),
method: Initialize::METHOD.to_string(),
params: serde_json::to_value(params.unwrap_or_default()).unwrap(),
params: params.unwrap_or(serde_json::Value::Null),
}))
.unwrap();
client_connection

View File

@ -50,15 +50,14 @@ impl LanguageServer {
pub(crate) fn initialize_workspace_folders(
&mut self,
init_params: serde_json::Value,
) -> Result<()> {
) -> Option<()> {
if let Some(array) = init_params.get("workspaceFolders") {
let folders: Vec<WorkspaceFolder> =
serde_json::from_value(array.clone()).into_diagnostic()?;
let folders: Vec<WorkspaceFolder> = serde_json::from_value(array.clone()).ok()?;
for folder in folders {
self.workspace_folders.insert(folder.name.clone(), folder);
}
}
Ok(())
Some(())
}
/// Highlight all occurrences of the text at cursor, in current file
@ -568,18 +567,36 @@ mod tests {
.unwrap()
}
/// Should not exit on malformed init_params
#[test]
fn malformed_init_params() {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(
serde_json::json!({ "workspaceFolders": serde_json::Value::Null }),
));
script.push("foo.nu");
let script = path_to_uri(&script);
open_unchecked(&client_connection, script.clone());
}
#[test]
fn command_reference_in_workspace() {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
}));
let (client_connection, _recv) = initialize_language_server(
serde_json::to_value(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
})
.ok(),
);
script.push("foo.nu");
let script = path_to_uri(&script);
@ -620,13 +637,16 @@ mod tests {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
}));
let (client_connection, _recv) = initialize_language_server(
serde_json::to_value(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
})
.ok(),
);
script.push("foo.nu");
let script = path_to_uri(&script);
@ -667,13 +687,16 @@ mod tests {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
}));
let (client_connection, _recv) = initialize_language_server(
serde_json::to_value(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
})
.ok(),
);
script.push("foo.nu");
let script = path_to_uri(&script);
@ -742,13 +765,16 @@ mod tests {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
}));
let (client_connection, _recv) = initialize_language_server(
serde_json::to_value(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
})
.ok(),
);
script.push("foo.nu");
let script = path_to_uri(&script);
@ -807,13 +833,16 @@ mod tests {
let mut script = fixtures();
script.push("lsp");
script.push("workspace");
let (client_connection, _recv) = initialize_language_server(Some(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
}));
let (client_connection, _recv) = initialize_language_server(
serde_json::to_value(InitializeParams {
workspace_folders: Some(vec![WorkspaceFolder {
uri: path_to_uri(&script),
name: "random name".to_string(),
}]),
..Default::default()
})
.ok(),
);
script.push("foo.nu");
let script = path_to_uri(&script);