From 4450365ec8743fa583758dfa74e3f276b114e7af Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 15 Jul 2021 21:28:30 +0200 Subject: [PATCH] Simplify --- crates/ide/src/goto_implementation.rs | 21 ++--- crates/ide/src/prime_caches.rs | 6 +- crates/ide/src/references.rs | 90 ++++++++++++---------- crates/ide/src/syntax_highlighting.rs | 106 +++++++++++++------------- 4 files changed, 111 insertions(+), 112 deletions(-) diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index bde0fbd176..0fc922125c 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -105,31 +105,24 @@ fn impls_for_trait_item( #[cfg(test)] mod tests { use ide_db::base_db::FileRange; + use itertools::Itertools; use crate::fixture; fn check(ra_fixture: &str) { - let (analysis, position, annotations) = fixture::annotations(ra_fixture); + let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis.goto_implementation(position).unwrap().unwrap().info; - let key = |frange: &FileRange| (frange.file_id, frange.range.start()); + let cmp = |frange: &FileRange| (frange.file_id, frange.range.start()); - let mut expected = annotations - .into_iter() - .map(|(range, data)| { - assert!(data.is_empty()); - range - }) - .collect::>(); - expected.sort_by_key(key); - - let mut actual = navs + let actual = navs .into_iter() .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) + .sorted_by_key(cmp) .collect::>(); - actual.sort_by_key(key); - + let expected = + expected.into_iter().map(|(range, _)| range).sorted_by_key(cmp).collect::>(); assert_eq!(expected, actual); } diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs index 36801c964b..ac23ed8bd2 100644 --- a/crates/ide/src/prime_caches.rs +++ b/crates/ide/src/prime_caches.rs @@ -1,6 +1,6 @@ -//! rust-analyzer is lazy and doesn't not compute anything unless asked. This +//! rust-analyzer is lazy and doesn't compute anything unless asked. This //! sometimes is counter productive when, for example, the first goto definition -//! request takes longer to compute. This modules implemented prepopulating of +//! request takes longer to compute. This modules implemented prepopulation of //! various caches, it's not really advanced at the moment. use hir::db::DefDatabase; @@ -27,7 +27,7 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress) let topo = &graph.crates_in_topological_order(); cb(PrimeCachesProgress::Started); - // Take care to emit the finish signal even when the computation is canceled. + // Take care to emit the finish signal even when the computation is canceled. let _d = stdx::defer(|| cb(PrimeCachesProgress::Finished)); // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that. diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 6b08212c75..305836f79d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -13,7 +13,7 @@ use hir::{PathResolution, Semantics}; use ide_db::{ base_db::FileId, defs::{Definition, NameClass, NameRefClass}, - search::{ReferenceAccess, SearchScope}, + search::{ReferenceAccess, SearchScope, UsageSearchResult}, RootDatabase, }; use rustc_hash::FxHashMap; @@ -56,48 +56,20 @@ pub(crate) fn find_all_refs( let _p = profile::span("find_all_refs"); let syntax = sema.parse(position.file_id).syntax().clone(); - let (def, is_literal_search) = - if let Some(name) = get_name_of_item_declaration(&syntax, position) { - ( - match NameClass::classify(sema, &name)? { - NameClass::Definition(it) | NameClass::ConstReference(it) => it, - NameClass::PatFieldShorthand { local_def: _, field_ref } => { - Definition::Field(field_ref) - } - }, - true, - ) - } else { - (find_def(sema, &syntax, position.offset)?, false) - }; + let mut is_literal_search = false; + let def = if let Some(name) = name_for_constructor_search(&syntax, position) { + is_literal_search = true; + match NameClass::classify(sema, &name)? { + NameClass::Definition(it) | NameClass::ConstReference(it) => it, + NameClass::PatFieldShorthand { local_def: _, field_ref } => { + Definition::Field(field_ref) + } + } + } else { + find_def(sema, &syntax, position.offset)? + }; let mut usages = def.usages(sema).set_scope(search_scope).include_self_refs().all(); - if is_literal_search { - // filter for constructor-literals - let refs = usages.references.values_mut(); - match def { - Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(enum_))) => { - refs.for_each(|it| { - it.retain(|reference| { - reference - .name - .as_name_ref() - .map_or(false, |name_ref| is_enum_lit_name_ref(sema, enum_, name_ref)) - }) - }); - usages.references.retain(|_, it| !it.is_empty()); - } - Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => { - refs.for_each(|it| { - it.retain(|reference| { - reference.name.as_name_ref().map_or(false, is_lit_name_ref) - }) - }); - usages.references.retain(|_, it| !it.is_empty()); - } - _ => {} - } - } let declaration = match def { Definition::ModuleDef(hir::ModuleDef::Module(module)) => { Some(NavigationTarget::from_module_to_decl(sema.db, module)) @@ -108,6 +80,10 @@ pub(crate) fn find_all_refs( let decl_range = nav.focus_or_full_range(); Declaration { nav, access: decl_access(&def, &syntax, decl_range) } }); + if is_literal_search { + retain_adt_literal_usages(&mut usages, def, sema); + } + let references = usages .into_iter() .map(|(file_id, refs)| { @@ -174,7 +150,37 @@ pub(crate) fn decl_access( None } -fn get_name_of_item_declaration(syntax: &SyntaxNode, position: FilePosition) -> Option { +/// Filter out all non-literal usages for adt-defs +fn retain_adt_literal_usages( + usages: &mut UsageSearchResult, + def: Definition, + sema: &Semantics, +) { + let refs = usages.references.values_mut(); + match def { + Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(enum_))) => { + refs.for_each(|it| { + it.retain(|reference| { + reference + .name + .as_name_ref() + .map_or(false, |name_ref| is_enum_lit_name_ref(sema, enum_, name_ref)) + }) + }); + usages.references.retain(|_, it| !it.is_empty()); + } + Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => { + refs.for_each(|it| { + it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref)) + }); + usages.references.retain(|_, it| !it.is_empty()); + } + _ => {} + } +} + +/// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages +fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option { let token = syntax.token_at_offset(position.offset).right_biased()?; let token_parent = token.parent()?; let kind = token.kind(); diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 55ee85434a..b8e62a1a86 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -17,7 +17,7 @@ use ide_db::{RootDatabase, SymbolKind}; use rustc_hash::FxHashMap; use syntax::{ ast::{self, HasFormatSpecifier}, - AstNode, AstToken, Direction, NodeOrToken, + match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxKind::*, SyntaxNode, TextRange, WalkEvent, T, }; @@ -159,15 +159,16 @@ pub(crate) fn highlight( // Determine the root based on the given range. let (root, range_to_highlight) = { let source_file = sema.parse(file_id); + let source_file = source_file.syntax(); match range_to_highlight { Some(range) => { - let node = match source_file.syntax().covering_element(range) { + let node = match source_file.covering_element(range) { NodeOrToken::Node(it) => it, - NodeOrToken::Token(it) => it.parent().unwrap(), + NodeOrToken::Token(it) => it.parent().unwrap_or_else(|| source_file.clone()), }; (node, range) } - None => (source_file.syntax().clone(), source_file.syntax().text_range()), + None => (source_file.clone(), source_file.text_range()), } }; @@ -211,62 +212,61 @@ fn traverse( continue; } - // Track "inside macro" state - match event.clone().map(|it| it.into_node().and_then(ast::MacroCall::cast)) { - WalkEvent::Enter(Some(mc)) => { - if let Some(range) = macro_call_range(&mc) { - hl.add(HlRange { - range, - highlight: HlTag::Symbol(SymbolKind::Macro).into(), - binding_hash: None, - }); - } - current_macro_call = Some(mc.clone()); - continue; - } - WalkEvent::Leave(Some(mc)) => { - assert_eq!(current_macro_call, Some(mc)); - current_macro_call = None; - } - _ => (), - } - match event.clone().map(|it| it.into_node().and_then(ast::Item::cast)) { - WalkEvent::Enter(Some(item)) => { - if sema.is_attr_macro_call(&item) { - current_attr_macro_call = Some(item); + match event.clone() { + WalkEvent::Enter(NodeOrToken::Node(node)) => { + match_ast! { + match node { + ast::MacroCall(mcall) => { + if let Some(range) = macro_call_range(&mcall) { + hl.add(HlRange { + range, + highlight: HlTag::Symbol(SymbolKind::Macro).into(), + binding_hash: None, + }); + } + current_macro_call = Some(mcall); + continue; + }, + ast::Macro(mac) => { + macro_highlighter.init(); + current_macro = Some(mac); + continue; + }, + ast::Item(item) => { + if sema.is_attr_macro_call(&item) { + current_attr_macro_call = Some(item); + } + }, + ast::Attr(__) => inside_attribute = true, + _ => () + } } } - WalkEvent::Leave(Some(item)) => { - if current_attr_macro_call == Some(item) { - current_attr_macro_call = None; + WalkEvent::Leave(NodeOrToken::Node(node)) => { + match_ast! { + match node { + ast::MacroCall(mcall) => { + assert_eq!(current_macro_call, Some(mcall)); + current_macro_call = None; + }, + ast::Macro(mac) => { + assert_eq!(current_macro, Some(mac)); + current_macro = None; + macro_highlighter = MacroHighlighter::default(); + }, + ast::Item(item) => { + if current_attr_macro_call == Some(item) { + current_attr_macro_call = None; + } + }, + ast::Attr(__) => inside_attribute = false, + _ => () + } } } _ => (), } - match event.clone().map(|it| it.into_node().and_then(ast::Macro::cast)) { - WalkEvent::Enter(Some(mac)) => { - macro_highlighter.init(); - current_macro = Some(mac); - continue; - } - WalkEvent::Leave(Some(mac)) => { - assert_eq!(current_macro, Some(mac)); - current_macro = None; - macro_highlighter = MacroHighlighter::default(); - } - _ => (), - } - match &event { - WalkEvent::Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { - inside_attribute = true - } - WalkEvent::Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { - inside_attribute = false - } - _ => (), - } - let element = match event { WalkEvent::Enter(it) => it, WalkEvent::Leave(it) => {