2020-02-06 15:23:28 +00:00
|
|
|
//! `NameDefinition` keeps information about the element we want to search references for.
|
|
|
|
//! The element is represented by `NameKind`. It's located inside some `container` and
|
|
|
|
//! has a `visibility`, which defines a search scope.
|
|
|
|
//! Note that the reference search is possible for not all of the classified items.
|
|
|
|
|
2020-02-06 15:24:14 +00:00
|
|
|
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
|
|
|
|
|
2020-02-06 15:23:28 +00:00
|
|
|
use hir::{
|
2020-02-19 13:45:49 +00:00
|
|
|
Adt, FieldSource, HasSource, ImplBlock, InFile, Local, MacroDef, Module, ModuleDef,
|
|
|
|
SourceBinder, StructField, TypeParam,
|
2020-02-06 15:23:28 +00:00
|
|
|
};
|
|
|
|
use ra_prof::profile;
|
|
|
|
use ra_syntax::{
|
|
|
|
ast::{self, AstNode, VisibilityOwner},
|
|
|
|
match_ast,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::RootDatabase;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2020-02-19 13:56:22 +00:00
|
|
|
pub enum NameDefinition {
|
2020-02-06 15:23:28 +00:00
|
|
|
Macro(MacroDef),
|
2020-02-07 13:26:59 +00:00
|
|
|
StructField(StructField),
|
|
|
|
ModuleDef(ModuleDef),
|
2020-02-06 15:23:28 +00:00
|
|
|
SelfType(ImplBlock),
|
|
|
|
Local(Local),
|
|
|
|
TypeParam(TypeParam),
|
|
|
|
}
|
|
|
|
|
2020-02-19 13:32:22 +00:00
|
|
|
impl NameDefinition {
|
|
|
|
pub fn module(&self, db: &RootDatabase) -> Option<Module> {
|
2020-02-19 13:56:22 +00:00
|
|
|
match self {
|
|
|
|
NameDefinition::Macro(it) => it.module(db),
|
|
|
|
NameDefinition::StructField(it) => Some(it.parent_def(db).module(db)),
|
|
|
|
NameDefinition::ModuleDef(it) => it.module(db),
|
|
|
|
NameDefinition::SelfType(it) => Some(it.module(db)),
|
|
|
|
NameDefinition::Local(it) => Some(it.module(db)),
|
|
|
|
NameDefinition::TypeParam(it) => Some(it.module(db)),
|
2020-02-19 13:32:22 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-19 13:45:49 +00:00
|
|
|
|
|
|
|
pub fn visibility(&self, db: &RootDatabase) -> Option<ast::Visibility> {
|
2020-02-19 13:56:22 +00:00
|
|
|
match self {
|
|
|
|
NameDefinition::Macro(_) => None,
|
|
|
|
NameDefinition::StructField(sf) => match sf.source(db).value {
|
2020-02-19 13:45:49 +00:00
|
|
|
FieldSource::Named(it) => it.visibility(),
|
|
|
|
FieldSource::Pos(it) => it.visibility(),
|
|
|
|
},
|
2020-02-19 13:56:22 +00:00
|
|
|
NameDefinition::ModuleDef(def) => match def {
|
2020-02-19 13:45:49 +00:00
|
|
|
ModuleDef::Module(it) => it.declaration_source(db)?.value.visibility(),
|
|
|
|
ModuleDef::Function(it) => it.source(db).value.visibility(),
|
|
|
|
ModuleDef::Adt(adt) => match adt {
|
|
|
|
Adt::Struct(it) => it.source(db).value.visibility(),
|
|
|
|
Adt::Union(it) => it.source(db).value.visibility(),
|
|
|
|
Adt::Enum(it) => it.source(db).value.visibility(),
|
|
|
|
},
|
|
|
|
ModuleDef::Const(it) => it.source(db).value.visibility(),
|
|
|
|
ModuleDef::Static(it) => it.source(db).value.visibility(),
|
|
|
|
ModuleDef::Trait(it) => it.source(db).value.visibility(),
|
|
|
|
ModuleDef::TypeAlias(it) => it.source(db).value.visibility(),
|
|
|
|
ModuleDef::EnumVariant(_) => None,
|
|
|
|
ModuleDef::BuiltinType(_) => None,
|
|
|
|
},
|
2020-02-19 13:56:22 +00:00
|
|
|
NameDefinition::SelfType(_) => None,
|
|
|
|
NameDefinition::Local(_) => None,
|
|
|
|
NameDefinition::TypeParam(_) => None,
|
2020-02-19 13:45:49 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-19 13:32:22 +00:00
|
|
|
}
|
|
|
|
|
2020-02-06 15:23:28 +00:00
|
|
|
pub fn classify_name(
|
|
|
|
sb: &mut SourceBinder<RootDatabase>,
|
|
|
|
name: InFile<&ast::Name>,
|
|
|
|
) -> Option<NameDefinition> {
|
|
|
|
let _p = profile("classify_name");
|
|
|
|
let parent = name.value.syntax().parent()?;
|
|
|
|
|
|
|
|
match_ast! {
|
|
|
|
match parent {
|
|
|
|
ast::BindPat(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let local = sb.to_def(src)?;
|
2020-02-19 13:56:22 +00:00
|
|
|
Some(NameDefinition::Local(local))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::RecordFieldDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let field: hir::StructField = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_struct_field(field))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::Module(it) => {
|
|
|
|
let def = sb.to_def(name.with_value(it))?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::StructDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Struct = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::EnumDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Enum = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::TraitDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Trait = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::StaticDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Static = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::EnumVariant(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::EnumVariant = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::FnDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Function = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::ConstDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::Const = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::TypeAliasDef(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def: hir::TypeAlias = sb.to_def(src)?;
|
2020-02-19 13:45:49 +00:00
|
|
|
Some(from_module_def(def.into()))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::MacroCall(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def = sb.to_def(src.clone())?;
|
|
|
|
|
2020-02-19 13:56:22 +00:00
|
|
|
Some(NameDefinition::Macro(def))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
ast::TypeParam(it) => {
|
|
|
|
let src = name.with_value(it);
|
|
|
|
let def = sb.to_def(src)?;
|
2020-02-19 13:56:22 +00:00
|
|
|
Some(NameDefinition::TypeParam(def))
|
2020-02-06 15:23:28 +00:00
|
|
|
},
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 13:45:49 +00:00
|
|
|
pub fn from_struct_field(field: StructField) -> NameDefinition {
|
2020-02-19 13:56:22 +00:00
|
|
|
NameDefinition::StructField(field)
|
2020-02-06 15:23:28 +00:00
|
|
|
}
|
|
|
|
|
2020-02-19 13:45:49 +00:00
|
|
|
pub fn from_module_def(def: ModuleDef) -> NameDefinition {
|
2020-02-19 13:56:22 +00:00
|
|
|
NameDefinition::ModuleDef(def)
|
2020-02-06 15:23:28 +00:00
|
|
|
}
|