From 0b5d0a41fde1ae03bc6643dad3b904f579f716b5 Mon Sep 17 00:00:00 2001 From: Ekaterina Babshukova Date: Thu, 3 Oct 2019 03:00:47 +0300 Subject: [PATCH] replace a chain of `if let` by macro --- crates/ra_hir/src/from_source.rs | 40 +----- crates/ra_ide_api/src/name_kind.rs | 116 +++++++++++----- crates/ra_ide_api/src/search_scope.rs | 186 -------------------------- 3 files changed, 87 insertions(+), 255 deletions(-) delete mode 100644 crates/ra_ide_api/src/search_scope.rs diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index e09414ca3d..df61c227ae 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -12,8 +12,7 @@ use crate::{ ids::{AstItemDef, LocationCtx}, name::AsName, AssocItem, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, - Module, ModuleDef, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, - VariantDef, + Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, }; pub trait FromSource: Sized { @@ -148,43 +147,6 @@ impl FromSource for AssocItem { } } -// not fully matched -impl FromSource for ModuleDef { - type Ast = ast::ModuleItem; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - macro_rules! def { - ($kind:ident, $ast:ident) => { - $kind::from_source(db, Source { file_id: src.file_id, ast: $ast }) - .and_then(|it| Some(ModuleDef::from(it))) - }; - } - - match src.ast { - ast::ModuleItem::FnDef(f) => def!(Function, f), - ast::ModuleItem::ConstDef(c) => def!(Const, c), - ast::ModuleItem::TypeAliasDef(a) => def!(TypeAlias, a), - ast::ModuleItem::TraitDef(t) => def!(Trait, t), - ast::ModuleItem::StaticDef(s) => def!(Static, s), - ast::ModuleItem::StructDef(s) => { - let src = Source { file_id: src.file_id, ast: s }; - let s = Struct::from_source(db, src)?; - Some(ModuleDef::Adt(s.into())) - } - ast::ModuleItem::EnumDef(e) => { - let src = Source { file_id: src.file_id, ast: e }; - let e = Enum::from_source(db, src)?; - Some(ModuleDef::Adt(e.into())) - } - ast::ModuleItem::Module(ref m) if !m.has_semi() => { - let src = Source { file_id: src.file_id, ast: ModuleSource::Module(m.clone()) }; - let module = Module::from_definition(db, src)?; - Some(ModuleDef::Module(module)) - } - _ => None, - } - } -} - // FIXME: simplify it impl ModuleSource { pub fn from_position( diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs index 64adb17841..0effeb8a16 100644 --- a/crates/ra_ide_api/src/name_kind.rs +++ b/crates/ra_ide_api/src/name_kind.rs @@ -102,36 +102,92 @@ pub(crate) fn classify_name( let parent = name.syntax().parent()?; let file_id = file_id.into(); - if let Some(pat) = ast::BindPat::cast(parent.clone()) { - return Some(Pat(AstPtr::new(&pat))); + macro_rules! match_ast { + (match $node:ident { + $( ast::$ast:ident($it:ident) => $res:block, )* + _ => $catch_all:expr, + }) => {{ + $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* + { $catch_all } + }}; } - if let Some(var) = ast::EnumVariant::cast(parent.clone()) { - let src = hir::Source { file_id, ast: var }; - let var = hir::EnumVariant::from_source(db, src)?; - return Some(Def(var.into())); - } - if let Some(field) = ast::RecordFieldDef::cast(parent.clone()) { - let src = hir::Source { file_id, ast: hir::FieldSource::Named(field) }; - let field = hir::StructField::from_source(db, src)?; - return Some(FieldAccess(field)); - } - if let Some(field) = ast::TupleFieldDef::cast(parent.clone()) { - let src = hir::Source { file_id, ast: hir::FieldSource::Pos(field) }; - let field = hir::StructField::from_source(db, src)?; - return Some(FieldAccess(field)); - } - if let Some(_) = parent.parent().and_then(ast::ItemList::cast) { - let ast = ast::ImplItem::cast(parent.clone())?; - let src = hir::Source { file_id, ast }; - let item = hir::AssocItem::from_source(db, src)?; - return Some(AssocItem(item)); - } - if let Some(item) = ast::ModuleItem::cast(parent.clone()) { - let src = hir::Source { file_id, ast: item }; - let def = hir::ModuleDef::from_source(db, src)?; - return Some(Def(def)); - } - // FIXME: TYPE_PARAM, ALIAS, MACRO_CALL; Union - None + // FIXME: add ast::MacroCall(it) + match_ast! { + match parent { + ast::BindPat(it) => { + let pat = AstPtr::new(&it); + Some(Pat(pat)) + }, + ast::RecordFieldDef(it) => { + let src = hir::Source { file_id, ast: hir::FieldSource::Named(it) }; + let field = hir::StructField::from_source(db, src)?; + Some(FieldAccess(field)) + }, + ast::FnDef(it) => { + if parent.parent().and_then(ast::ItemList::cast).is_some() { + let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let item = hir::AssocItem::from_source(db, src)?; + Some(AssocItem(item)) + } else { + let src = hir::Source { file_id, ast: it }; + let def = hir::Function::from_source(db, src)?; + Some(Def(def.into())) + } + }, + ast::ConstDef(it) => { + if parent.parent().and_then(ast::ItemList::cast).is_some() { + let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let item = hir::AssocItem::from_source(db, src)?; + Some(AssocItem(item)) + } else { + let src = hir::Source { file_id, ast: it }; + let def = hir::Const::from_source(db, src)?; + Some(Def(def.into())) + } + }, + ast::TypeAliasDef(it) => { + if parent.parent().and_then(ast::ItemList::cast).is_some() { + let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let item = hir::AssocItem::from_source(db, src)?; + Some(AssocItem(item)) + } else { + let src = hir::Source { file_id, ast: it }; + let def = hir::TypeAlias::from_source(db, src)?; + Some(Def(def.into())) + } + }, + ast::Module(it) => { + let src = hir::Source { file_id, ast: hir::ModuleSource::Module(it) }; + let def = hir::Module::from_definition(db, src)?; + Some(Def(def.into())) + }, + ast::StructDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Struct::from_source(db, src)?; + Some(Def(def.into())) + }, + ast::EnumDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Enum::from_source(db, src)?; + Some(Def(def.into())) + }, + ast::TraitDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Trait::from_source(db, src)?; + Some(Def(def.into())) + }, + ast::StaticDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Static::from_source(db, src)?; + Some(Def(def.into())) + }, + ast::EnumVariant(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::EnumVariant::from_source(db, src)?; + Some(Def(def.into())) + }, + _ => None, + } + } } diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs deleted file mode 100644 index ca1ac2b030..0000000000 --- a/crates/ra_ide_api/src/search_scope.rs +++ /dev/null @@ -1,186 +0,0 @@ -pub enum SearchScope { - Function(hir::Function), - Module(hir::Module), - Crate(hir::Crate), - Crates(Vec), -} - -pub struct SearchScope{ - pub scope: Vec -} - -pub fn find_all_refs(db: &RootDatabase, decl: NameKind) -> Vec { - let (module, visibility) = match decl { - FieldAccess(field) => { - let parent = field.parent_def(db); - let module = parent.module(db); - let visibility = match parent { - VariantDef::Struct(s) => s.source(db).ast.visibility(), - VariantDef::EnumVariant(v) => v.parent_enum(db).source(db).ast.visibility(), - }; - (module, visibility) - } - AssocItem(item) => { - let parent = item.parent_trait(db)?; - let module = parent.module(db); - let visibility = parent.source(db).ast.visibility(); - (module, visibility) - } - Def(def) => { - let (module, visibility) = match def { - ModuleDef::Module(m) => (m, ), - ModuleDef::Function(f) => (f.module(db), f.source(db).ast.visibility()), - ModuleDef::Adt::Struct(s) => (s.module(db), s.source(db).ast.visibility()), - ModuleDef::Adt::Union(u) => (u.module(db), u.source(db).ast.visibility()), - ModuleDef::Adt::Enum(e) => (e.module(db), e.source(db).ast.visibility()), - ModuleDef::EnumVariant(v) => (v.module(db), v.source(db).ast.visibility()), - ModuleDef::Const(c) => (c.module(db), c.source(db).ast.visibility()), - ModuleDef::Static(s) => (s.module(db), s.source(db).ast.visibility()), - ModuleDef::Trait(t) => (t.module(db), t.source(db).ast.visibility()), - ModuleDef::TypeAlias(a) => (a.module(db), a.source(db).ast.visibility()), - ModuleDef::BuiltinType(_) => return vec![]; - }; - (module, visibility) - } - // FIXME: add missing kinds - _ => return vec![]; - }; - let scope = scope(db, module, visibility); -} - -fn scope(db: &RootDatabase, module: hir::Module, item_vis: Option) -> SearchScope { - if let Some(v) = item_vis { - let krate = module.krate(db)?; - - if v.syntax().text() == "pub" { - SearchScope::Crate(krate) - } - if v.syntax().text() == "pub(crate)" { - let crate_graph = db.crate_graph(); - let crates = crate_graph.iter().filter(|id| { - crate_graph.dependencies(id).any(|d| d.crate_id() == krate.crate_id()) - }).map(|id| Crate { id }).collect::>(); - crates.insert(0, krate); - SearchScope::Crates(crates) - } - // FIXME: "pub(super)", "pub(in path)" - SearchScope::Module(module) - } - SearchScope::Module(module) -} - -fn process_one(db, scope: SearchScope, pat) { - match scope { - SearchScope::Crate(krate) => { - let text = db.file_text(position.file_id).as_str(); - let parse = SourceFile::parse(text); - for (offset, name) in text.match_indices(pat) { - if let Some() = find_node_at_offset(parse, offset) { - - } - } - } - } -} - -#[cfg(test)] -mod tests { - use crate::{ - mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, - ReferenceSearchResult, - }; - use insta::assert_debug_snapshot; - use test_utils::assert_eq_text; - - #[test] - fn test_find_all_refs_for_local() { - let code = r#" - fn main() { - let mut i = 1; - let j = 1; - i = i<|> + j; - - { - i = 0; - } - - i = 5; - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 5); - } - - #[test] - fn test_find_all_refs_for_param_inside() { - let code = r#" - fn foo(i : u32) -> u32 { - i<|> - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); - } - - #[test] - fn test_find_all_refs_for_fn_param() { - let code = r#" - fn foo(i<|> : u32) -> u32 { - i - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); - } - - #[test] - fn test_find_all_refs_field_name() { - let code = r#" - //- /lib.rs - struct Foo { - spam<|>: u32, - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 1); - } - - #[test] - fn test_find_all_refs_methods() { - let code = r#" - //- /lib.rs - struct Foo; - impl Foo { - pub fn a() { - self.b() - } - fn b(&self) {} - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 1); - } - - #[test] - fn test_find_all_refs_pub_enum() { - let code = r#" - //- /lib.rs - pub enum Foo { - A, - B<|>, - C, - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 1); - } - - fn get_all_refs(text: &str) -> ReferenceSearchResult { - let (analysis, position) = single_file_with_position(text); - analysis.find_all_refs(position).unwrap().unwrap() - } -} \ No newline at end of file