lsp: Check if language server supports workspace/symbol
request (#27491)
This ensures that we do not get a bunch of error logs when using the symbol search: ``` [2025-03-26T13:23:32+01:00 ERROR project] Method not found [2025-03-26T13:23:32+01:00 ERROR project] Method not found [2025-03-26T13:23:32+01:00 ERROR project] Method not found [2025-03-26T13:23:32+01:00 ERROR project] Method not found [2025-03-26T13:23:32+01:00 ERROR project] Method not found [2025-03-26T13:23:33+01:00 ERROR project] Method not found ... ``` Release Notes: - N/A
This commit is contained in:
parent
1d9c581ae0
commit
1e22faebc9
4 changed files with 69 additions and 43 deletions
|
@ -26,7 +26,7 @@ use language::{
|
||||||
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticEntry, FakeLspAdapter,
|
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticEntry, FakeLspAdapter,
|
||||||
Language, LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope,
|
Language, LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope,
|
||||||
};
|
};
|
||||||
use lsp::LanguageServerId;
|
use lsp::{LanguageServerId, OneOf};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use project::{
|
use project::{
|
||||||
|
@ -5399,9 +5399,16 @@ async fn test_project_symbols(
|
||||||
let active_call_a = cx_a.read(ActiveCall::global);
|
let active_call_a = cx_a.read(ActiveCall::global);
|
||||||
|
|
||||||
client_a.language_registry().add(rust_lang());
|
client_a.language_registry().add(rust_lang());
|
||||||
let mut fake_language_servers = client_a
|
let mut fake_language_servers = client_a.language_registry().register_fake_lsp(
|
||||||
.language_registry()
|
"Rust",
|
||||||
.register_fake_lsp("Rust", Default::default());
|
FakeLspAdapter {
|
||||||
|
capabilities: lsp::ServerCapabilities {
|
||||||
|
workspace_symbol_provider: Some(OneOf::Left(true)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
client_a
|
client_a
|
||||||
.fs()
|
.fs()
|
||||||
|
|
|
@ -1483,6 +1483,7 @@ impl LanguageServer {
|
||||||
document_formatting_provider: Some(OneOf::Left(true)),
|
document_formatting_provider: Some(OneOf::Left(true)),
|
||||||
document_range_formatting_provider: Some(OneOf::Left(true)),
|
document_range_formatting_provider: Some(OneOf::Left(true)),
|
||||||
definition_provider: Some(OneOf::Left(true)),
|
definition_provider: Some(OneOf::Left(true)),
|
||||||
|
workspace_symbol_provider: Some(OneOf::Left(true)),
|
||||||
implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
|
implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
|
||||||
type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
|
type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -5791,48 +5791,57 @@ impl LspStore {
|
||||||
|
|
||||||
_ => continue 'next_server,
|
_ => continue 'next_server,
|
||||||
};
|
};
|
||||||
|
let supports_workspace_symbol_request =
|
||||||
|
match server.capabilities().workspace_symbol_provider {
|
||||||
|
Some(OneOf::Left(supported)) => supported,
|
||||||
|
Some(OneOf::Right(_)) => true,
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
if !supports_workspace_symbol_request {
|
||||||
|
continue 'next_server;
|
||||||
|
}
|
||||||
let worktree_abs_path = worktree.abs_path().clone();
|
let worktree_abs_path = worktree.abs_path().clone();
|
||||||
let worktree_handle = worktree_handle.clone();
|
let worktree_handle = worktree_handle.clone();
|
||||||
let server_id = server.server_id();
|
let server_id = server.server_id();
|
||||||
requests.push(
|
requests.push(
|
||||||
server
|
server
|
||||||
.request::<lsp::request::WorkspaceSymbolRequest>(
|
.request::<lsp::request::WorkspaceSymbolRequest>(
|
||||||
lsp::WorkspaceSymbolParams {
|
lsp::WorkspaceSymbolParams {
|
||||||
query: query.to_string(),
|
query: query.to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.log_err()
|
.log_err()
|
||||||
.map(move |response| {
|
.map(move |response| {
|
||||||
let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
|
let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
|
||||||
lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
|
lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
|
||||||
flat_responses.into_iter().map(|lsp_symbol| {
|
flat_responses.into_iter().map(|lsp_symbol| {
|
||||||
(lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
|
(lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
}
|
|
||||||
lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
|
|
||||||
nested_responses.into_iter().filter_map(|lsp_symbol| {
|
|
||||||
let location = match lsp_symbol.location {
|
|
||||||
OneOf::Left(location) => location,
|
|
||||||
OneOf::Right(_) => {
|
|
||||||
log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some((lsp_symbol.name, lsp_symbol.kind, location))
|
|
||||||
}).collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
}).unwrap_or_default();
|
|
||||||
|
|
||||||
WorkspaceSymbolsResult {
|
|
||||||
server_id,
|
|
||||||
lsp_adapter,
|
|
||||||
worktree: worktree_handle.downgrade(),
|
|
||||||
worktree_abs_path,
|
|
||||||
lsp_symbols,
|
|
||||||
}
|
}
|
||||||
}),
|
lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
|
||||||
);
|
nested_responses.into_iter().filter_map(|lsp_symbol| {
|
||||||
|
let location = match lsp_symbol.location {
|
||||||
|
OneOf::Left(location) => location,
|
||||||
|
OneOf::Right(_) => {
|
||||||
|
log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some((lsp_symbol.name, lsp_symbol.kind, location))
|
||||||
|
}).collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
}).unwrap_or_default();
|
||||||
|
|
||||||
|
WorkspaceSymbolsResult {
|
||||||
|
server_id,
|
||||||
|
lsp_adapter,
|
||||||
|
worktree: worktree_handle.downgrade(),
|
||||||
|
worktree_abs_path,
|
||||||
|
lsp_symbols,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
requested_servers.append(&mut servers_to_query);
|
requested_servers.append(&mut servers_to_query);
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,7 @@ mod tests {
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use gpui::{SemanticVersion, TestAppContext, VisualContext};
|
use gpui::{SemanticVersion, TestAppContext, VisualContext};
|
||||||
use language::{FakeLspAdapter, Language, LanguageConfig, LanguageMatcher};
|
use language::{FakeLspAdapter, Language, LanguageConfig, LanguageMatcher};
|
||||||
|
use lsp::OneOf;
|
||||||
use project::FakeFs;
|
use project::FakeFs;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
|
@ -298,8 +299,16 @@ mod tests {
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)));
|
)));
|
||||||
let mut fake_servers =
|
let mut fake_servers = language_registry.register_fake_lsp(
|
||||||
language_registry.register_fake_lsp("Rust", FakeLspAdapter::default());
|
"Rust",
|
||||||
|
FakeLspAdapter {
|
||||||
|
capabilities: lsp::ServerCapabilities {
|
||||||
|
workspace_symbol_provider: Some(OneOf::Left(true)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let _buffer = project
|
let _buffer = project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue