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:
Bennet Bo Fenner 2025-03-26 14:09:41 +01:00 committed by GitHub
parent 1d9c581ae0
commit 1e22faebc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 69 additions and 43 deletions

View file

@ -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()

View file

@ -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()

View file

@ -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);
} }

View file

@ -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| {