From 01853e8d6c6f4b44801c74f4fcdef735d9e77b48 Mon Sep 17 00:00:00 2001 From: Ekaterina Babshukova Date: Thu, 10 Oct 2019 00:25:48 +0300 Subject: find scope for `Declaration` item --- crates/ra_ide_api/src/goto_definition.rs | 2 +- crates/ra_ide_api/src/lib.rs | 1 + crates/ra_ide_api/src/name_kind.rs | 65 ++++++++++---------------------- crates/ra_ide_api/src/search_scope.rs | 64 +++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 crates/ra_ide_api/src/search_scope.rs diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index f49764513..fefd59cdd 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -207,7 +207,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option #[cfg(test)] mod tests { - use test_utils::covers; + // use test_utils::covers; use crate::mock_analysis::analysis_and_position; diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index cbf79ce03..2dc3f0944 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -41,6 +41,7 @@ mod matching_brace; mod display; mod inlay_hints; mod wasm_shims; +mod search_scope; #[cfg(test)] mod marks; diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs index 31f6f277d..6d1eb153f 100644 --- a/crates/ra_ide_api/src/name_kind.rs +++ b/crates/ra_ide_api/src/name_kind.rs @@ -2,8 +2,8 @@ use hir::{ db::AstDatabase, Adt, AssocItem, DefWithBody, Either, EnumVariant, FromSource, HasSource, - HirFileId, MacroDef, ModuleDef, ModuleSource, Path, PathResolution, SourceAnalyzer, - StructField, Ty, VariantDef, + HirFileId, MacroDef, Module, ModuleDef, ModuleSource, Path, PathResolution, Source, + SourceAnalyzer, StructField, Ty, VariantDef, }; use ra_db::FileId; use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; @@ -22,8 +22,8 @@ pub enum NameKind { } pub(crate) struct Declaration { - visibility: Option, - container: ModuleSource, + pub visibility: Option, + pub container: Module, pub item: NameKind, } @@ -80,16 +80,9 @@ pub(crate) fn classify_name_ref( } } + let ast = ModuleSource::from_child_node(db, file_id, &parent); let file_id = file_id.into(); - let container = parent.ancestors().find_map(|node| { - if let Some(it) = ast::Module::cast(node.clone()) { - Some(ModuleSource::Module(it)) - } else if let Some(it) = ast::SourceFile::cast(node.clone()) { - Some(ModuleSource::SourceFile(it)) - } else { - None - } - })?; + let container = Module::from_definition(db, Source { file_id, ast })?; if let Some(macro_call) = parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) @@ -117,7 +110,7 @@ pub(crate) fn classify_name_ref( } PathResolution::SelfType(impl_block) => { let ty = impl_block.target_ty(db); - let container = impl_block.module().definition_source(db).ast; + let container = impl_block.module(); Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None }) } PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)), @@ -184,7 +177,7 @@ fn decl_from_pat( } })?; let item = NameKind::Pat((def, pat)); - let container = def.module(db).definition_source(db).ast; + let container = def.module(db); Some(Declaration { item, container, visibility: None }) } @@ -195,7 +188,7 @@ impl HasDeclaration for StructField { fn declaration(self, db: &RootDatabase) -> Declaration { let item = NameKind::FieldAccess(self); let parent = self.parent_def(db); - let container = parent.module(db).definition_source(db).ast; + let container = parent.module(db); let visibility = match parent { VariantDef::Struct(s) => s.source(db).ast.visibility(), VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), @@ -225,7 +218,7 @@ impl HasDeclaration for AssocItem { fn declaration(self, db: &RootDatabase) -> Declaration { let item = NameKind::AssocItem(self); - let container = self.module(db).definition_source(db).ast; + let container = self.module(db); let visibility = match self { AssocItem::Function(f) => f.source(db).ast.visibility(), AssocItem::Const(c) => c.source(db).ast.visibility(), @@ -255,43 +248,25 @@ impl HasDeclaration for ModuleDef { type Ref = ast::Path; fn declaration(self, db: &RootDatabase) -> Declaration { - // FIXME: use macro let (container, visibility) = match self { ModuleDef::Module(it) => { - let container = - it.parent(db).or_else(|| Some(it)).unwrap().definition_source(db).ast; + let container = it.parent(db).or_else(|| Some(it)).unwrap(); let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); (container, visibility) } ModuleDef::EnumVariant(it) => { - let container = it.module(db).definition_source(db).ast; + let container = it.module(db); let visibility = it.source(db).ast.parent_enum().visibility(); (container, visibility) } - ModuleDef::Function(it) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Const(it) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Static(it) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Trait(it) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::TypeAlias(it) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Adt(Adt::Struct(it)) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Adt(Adt::Union(it)) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } - ModuleDef::Adt(Adt::Enum(it)) => { - (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) - } + ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), ModuleDef::BuiltinType(..) => unreachable!(), }; let item = NameKind::Def(self); diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs new file mode 100644 index 000000000..1cf1aed37 --- /dev/null +++ b/crates/ra_ide_api/src/search_scope.rs @@ -0,0 +1,64 @@ +use hir::{DefWithBody, HasSource, ModuleSource}; +use ra_db::{FileId, SourceDatabase}; +use ra_syntax::{AstNode, TextRange}; + +use crate::{ + db::RootDatabase, + name_kind::{Declaration, NameKind}, +}; + +pub struct SearchScope { + pub scope: Vec<(FileId, Option)>, +} + +impl Declaration { + pub fn scope(self, db: &RootDatabase) -> Option { + let module_src = self.container.definition_source(db); + let file_id = module_src.file_id.original_file(db); + + if let NameKind::Pat((def, _)) = self.item { + let range = match def { + DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), + DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), + DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), + }; + return Some(SearchScope { scope: vec![(file_id, Some(range))] }); + } + + if let Some(vis) = self.visibility { + let source_root_id = db.file_source_root(file_id); + let source_root = db.source_root(source_root_id); + let mut files = source_root.walk().map(|id| (id.into(), None)).collect::>(); + + if vis.syntax().text() == "pub(crate)" { + return Some(SearchScope { scope: files }); + } + if vis.syntax().text() == "pub" { + let krate = self.container.krate(db).unwrap(); + let crate_graph = db.crate_graph(); + + for crate_id in crate_graph.iter() { + let mut crate_deps = crate_graph.dependencies(crate_id); + + if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { + let root_file = crate_graph.crate_root(crate_id); + let source_root_id = db.file_source_root(root_file); + let source_root = db.source_root(source_root_id); + files.extend(source_root.walk().map(|id| (id.into(), None))); + } + } + + return Some(SearchScope { scope: files }); + } + // FIXME: extend to "pub(super)" and "pub(in path)" cases, + // then remove `Option` + return None; + } + + let range = match module_src.ast { + ModuleSource::Module(m) => Some(m.syntax().text_range()), + ModuleSource::SourceFile(_) => None, + }; + Some(SearchScope { scope: vec![(file_id, range)] }) + } +} -- cgit v1.2.3