find scope for Declaration item

This commit is contained in:
Ekaterina Babshukova 2019-10-10 00:25:48 +03:00
parent 121aa35f12
commit 01853e8d6c
4 changed files with 86 additions and 46 deletions

View File

@ -207,7 +207,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget>
#[cfg(test)]
mod tests {
use test_utils::covers;
// use test_utils::covers;
use crate::mock_analysis::analysis_and_position;

View File

@ -41,6 +41,7 @@
mod display;
mod inlay_hints;
mod wasm_shims;
mod search_scope;
#[cfg(test)]
mod marks;

View File

@ -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<ast::Visibility>,
container: ModuleSource,
pub visibility: Option<ast::Visibility>,
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);

View File

@ -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<TextRange>)>,
}
impl Declaration {
pub fn scope(self, db: &RootDatabase) -> Option<SearchScope> {
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::<Vec<_>>();
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)] })
}
}