mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
find scope for Declaration
item
This commit is contained in:
parent
121aa35f12
commit
01853e8d6c
4 changed files with 86 additions and 46 deletions
|
@ -207,7 +207,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget>
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use test_utils::covers;
|
// use test_utils::covers;
|
||||||
|
|
||||||
use crate::mock_analysis::analysis_and_position;
|
use crate::mock_analysis::analysis_and_position;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ mod matching_brace;
|
||||||
mod display;
|
mod display;
|
||||||
mod inlay_hints;
|
mod inlay_hints;
|
||||||
mod wasm_shims;
|
mod wasm_shims;
|
||||||
|
mod search_scope;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod marks;
|
mod marks;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use hir::{
|
use hir::{
|
||||||
db::AstDatabase, Adt, AssocItem, DefWithBody, Either, EnumVariant, FromSource, HasSource,
|
db::AstDatabase, Adt, AssocItem, DefWithBody, Either, EnumVariant, FromSource, HasSource,
|
||||||
HirFileId, MacroDef, ModuleDef, ModuleSource, Path, PathResolution, SourceAnalyzer,
|
HirFileId, MacroDef, Module, ModuleDef, ModuleSource, Path, PathResolution, Source,
|
||||||
StructField, Ty, VariantDef,
|
SourceAnalyzer, StructField, Ty, VariantDef,
|
||||||
};
|
};
|
||||||
use ra_db::FileId;
|
use ra_db::FileId;
|
||||||
use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr};
|
use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr};
|
||||||
|
@ -22,8 +22,8 @@ pub enum NameKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Declaration {
|
pub(crate) struct Declaration {
|
||||||
visibility: Option<ast::Visibility>,
|
pub visibility: Option<ast::Visibility>,
|
||||||
container: ModuleSource,
|
pub container: Module,
|
||||||
pub item: NameKind,
|
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 file_id = file_id.into();
|
||||||
let container = parent.ancestors().find_map(|node| {
|
let container = Module::from_definition(db, Source { file_id, ast })?;
|
||||||
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
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Some(macro_call) =
|
if let Some(macro_call) =
|
||||||
parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast)
|
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) => {
|
PathResolution::SelfType(impl_block) => {
|
||||||
let ty = impl_block.target_ty(db);
|
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 })
|
Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None })
|
||||||
}
|
}
|
||||||
PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)),
|
PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)),
|
||||||
|
@ -184,7 +177,7 @@ fn decl_from_pat(
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
let item = NameKind::Pat((def, 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 })
|
Some(Declaration { item, container, visibility: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +188,7 @@ impl HasDeclaration for StructField {
|
||||||
fn declaration(self, db: &RootDatabase) -> Declaration {
|
fn declaration(self, db: &RootDatabase) -> Declaration {
|
||||||
let item = NameKind::FieldAccess(self);
|
let item = NameKind::FieldAccess(self);
|
||||||
let parent = self.parent_def(db);
|
let parent = self.parent_def(db);
|
||||||
let container = parent.module(db).definition_source(db).ast;
|
let container = parent.module(db);
|
||||||
let visibility = match parent {
|
let visibility = match parent {
|
||||||
VariantDef::Struct(s) => s.source(db).ast.visibility(),
|
VariantDef::Struct(s) => s.source(db).ast.visibility(),
|
||||||
VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().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 {
|
fn declaration(self, db: &RootDatabase) -> Declaration {
|
||||||
let item = NameKind::AssocItem(self);
|
let item = NameKind::AssocItem(self);
|
||||||
let container = self.module(db).definition_source(db).ast;
|
let container = self.module(db);
|
||||||
let visibility = match self {
|
let visibility = match self {
|
||||||
AssocItem::Function(f) => f.source(db).ast.visibility(),
|
AssocItem::Function(f) => f.source(db).ast.visibility(),
|
||||||
AssocItem::Const(c) => c.source(db).ast.visibility(),
|
AssocItem::Const(c) => c.source(db).ast.visibility(),
|
||||||
|
@ -255,43 +248,25 @@ impl HasDeclaration for ModuleDef {
|
||||||
type Ref = ast::Path;
|
type Ref = ast::Path;
|
||||||
|
|
||||||
fn declaration(self, db: &RootDatabase) -> Declaration {
|
fn declaration(self, db: &RootDatabase) -> Declaration {
|
||||||
// FIXME: use macro
|
|
||||||
let (container, visibility) = match self {
|
let (container, visibility) = match self {
|
||||||
ModuleDef::Module(it) => {
|
ModuleDef::Module(it) => {
|
||||||
let container =
|
let container = it.parent(db).or_else(|| Some(it)).unwrap();
|
||||||
it.parent(db).or_else(|| Some(it)).unwrap().definition_source(db).ast;
|
|
||||||
let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility());
|
let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility());
|
||||||
(container, visibility)
|
(container, visibility)
|
||||||
}
|
}
|
||||||
ModuleDef::EnumVariant(it) => {
|
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();
|
let visibility = it.source(db).ast.parent_enum().visibility();
|
||||||
(container, visibility)
|
(container, visibility)
|
||||||
}
|
}
|
||||||
ModuleDef::Function(it) => {
|
ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()),
|
||||||
(it.module(db).definition_source(db).ast, 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::Const(it) => {
|
ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()),
|
||||||
(it.module(db).definition_source(db).ast, 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::Static(it) => {
|
ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()),
|
||||||
(it.module(db).definition_source(db).ast, it.source(db).ast.visibility())
|
ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), 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::BuiltinType(..) => unreachable!(),
|
ModuleDef::BuiltinType(..) => unreachable!(),
|
||||||
};
|
};
|
||||||
let item = NameKind::Def(self);
|
let item = NameKind::Def(self);
|
||||||
|
|
64
crates/ra_ide_api/src/search_scope.rs
Normal file
64
crates/ra_ide_api/src/search_scope.rs
Normal 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)] })
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue