Detailed changes
@@ -568,13 +568,14 @@ impl LspAdapter for RustLspAdapter {
language: &Arc<Language>,
) -> Option<CodeLabel> {
let (prefix, suffix) = match kind {
- lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => ("fn ", " () {}"),
- lsp::SymbolKind::STRUCT => ("struct ", " {}"),
- lsp::SymbolKind::ENUM => ("enum ", " {}"),
- lsp::SymbolKind::INTERFACE => ("trait ", " {}"),
- lsp::SymbolKind::CONSTANT => ("const ", ": () = ();"),
- lsp::SymbolKind::MODULE => ("mod ", " {}"),
- lsp::SymbolKind::TYPE_PARAMETER => ("type ", " {}"),
+ lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => ("fn ", "();"),
+ lsp::SymbolKind::STRUCT => ("struct ", ";"),
+ lsp::SymbolKind::ENUM => ("enum ", "{}"),
+ lsp::SymbolKind::INTERFACE => ("trait ", "{}"),
+ lsp::SymbolKind::CONSTANT => ("const ", ":()=();"),
+ lsp::SymbolKind::MODULE => ("mod ", ";"),
+ lsp::SymbolKind::PACKAGE => ("extern crate ", ";"),
+ lsp::SymbolKind::TYPE_PARAMETER => ("type ", "=();"),
_ => return None,
};
@@ -1824,6 +1825,17 @@ mod tests {
vec![(0..4, highlight_keyword), (5..10, highlight_type)],
))
);
+
+ assert_eq!(
+ adapter
+ .label_for_symbol("zed", lsp::SymbolKind::PACKAGE, &language)
+ .await,
+ Some(CodeLabel::new(
+ "extern crate zed".to_string(),
+ 13..16,
+ vec![(0..6, highlight_keyword), (7..12, highlight_keyword),],
+ ))
+ );
}
#[gpui::test]
@@ -7792,46 +7792,62 @@ impl LspStore {
let worktree_handle = worktree_handle.clone();
let server_id = server.server_id();
requests.push(
- server
- .request::<lsp::request::WorkspaceSymbolRequest>(
- lsp::WorkspaceSymbolParams {
- query: query.to_string(),
- ..Default::default()
- },
- )
- .map(move |response| {
- let lsp_symbols = response.into_response()
- .context("workspace symbols request")
- .log_err()
- .flatten()
- .map(|symbol_response| match symbol_response {
- lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
- flat_responses.into_iter().map(|lsp_symbol| {
- (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
- }).collect::<Vec<_>>()
- }
- lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
- nested_responses.into_iter().filter_map(|lsp_symbol| {
+ server
+ .request::<lsp::request::WorkspaceSymbolRequest>(
+ lsp::WorkspaceSymbolParams {
+ query: query.to_string(),
+ ..Default::default()
+ },
+ )
+ .map(move |response| {
+ let lsp_symbols = response
+ .into_response()
+ .context("workspace symbols request")
+ .log_err()
+ .flatten()
+ .map(|symbol_response| match symbol_response {
+ lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
+ flat_responses
+ .into_iter()
+ .map(|lsp_symbol| {
+ (
+ lsp_symbol.name,
+ lsp_symbol.kind,
+ lsp_symbol.location,
+ )
+ })
+ .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
+ 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();
+ })
+ .collect::<Vec<_>>()
+ }
+ })
+ .unwrap_or_default();
- WorkspaceSymbolsResult {
- server_id,
- lsp_adapter,
- worktree: worktree_handle.downgrade(),
- lsp_symbols,
- }
- }),
- );
+ WorkspaceSymbolsResult {
+ server_id,
+ lsp_adapter,
+ worktree: worktree_handle.downgrade(),
+ lsp_symbols,
+ }
+ }),
+ );
}
cx.spawn(async move |this, cx| {
@@ -178,7 +178,15 @@ impl PickerDelegate for ProjectSymbolsDelegate {
window: &mut Window,
cx: &mut Context<Picker<Self>>,
) -> Task<()> {
- self.filter(&query, window, cx);
+ // Try to support rust-analyzer's path based symbols feature which
+ // allows to search by rust path syntax, in that case we only want to
+ // filter names by the last segment
+ // Ideally this was a first class LSP feature (rich queries)
+ let query_filter = query
+ .rsplit_once("::")
+ .map_or(&*query, |(_, suffix)| suffix)
+ .to_owned();
+ self.filter(&query_filter, window, cx);
self.show_worktree_root_name = self.project.read(cx).visible_worktrees(cx).count() > 1;
let symbols = self
.project
@@ -208,7 +216,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
delegate.visible_match_candidates = visible_match_candidates;
delegate.external_match_candidates = external_match_candidates;
delegate.symbols = symbols;
- delegate.filter(&query, window, cx);
+ delegate.filter(&query_filter, window, cx);
})
.log_err();
}
@@ -354,17 +362,24 @@ mod tests {
let executor = cx.background_executor().clone();
let fake_symbols = fake_symbols.clone();
async move {
+ let (query, prefixed) = match params.query.strip_prefix("dir::") {
+ Some(query) => (query, true),
+ None => (&*params.query, false),
+ };
let candidates = fake_symbols
.iter()
.enumerate()
+ .filter(|(_, symbol)| {
+ !prefixed || symbol.location.uri.path().contains("dir")
+ })
.map(|(id, symbol)| StringMatchCandidate::new(id, &symbol.name))
.collect::<Vec<_>>();
- let matches = if params.query.is_empty() {
+ let matches = if query.is_empty() {
Vec::new()
} else {
fuzzy::match_strings(
&candidates,
- ¶ms.query,
+ &query,
true,
true,
100,
@@ -434,6 +449,16 @@ mod tests {
symbols.read_with(cx, |symbols, _| {
assert_eq!(symbols.delegate.matches.len(), 0);
});
+
+ // Check that rust-analyzer path style symbols work
+ symbols.update_in(cx, |p, window, cx| {
+ p.update_matches("dir::to".to_string(), window, cx);
+ });
+
+ cx.run_until_parked();
+ symbols.read_with(cx, |symbols, _| {
+ assert_eq!(symbols.delegate.matches.len(), 1);
+ });
}
fn init_test(cx: &mut TestAppContext) {