aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references/name_definition.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/references/name_definition.rs')
-rw-r--r--crates/ra_ide_api/src/references/name_definition.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs
new file mode 100644
index 000000000..19702eba0
--- /dev/null
+++ b/crates/ra_ide_api/src/references/name_definition.rs
@@ -0,0 +1,104 @@
1use hir::{
2 db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef,
3 Module, ModuleDef, StructField, Ty, VariantDef,
4};
5use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr};
6
7use crate::db::RootDatabase;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum NameKind {
11 Macro(MacroDef),
12 Field(StructField),
13 AssocItem(AssocItem),
14 Def(ModuleDef),
15 SelfType(Ty),
16 Pat((DefWithBody, AstPtr<ast::BindPat>)),
17 SelfParam(AstPtr<ast::SelfParam>),
18 GenericParam(u32),
19}
20
21#[derive(PartialEq, Eq)]
22pub(crate) struct NameDefinition {
23 pub visibility: Option<ast::Visibility>,
24 pub container: Module,
25 pub item: NameKind,
26}
27
28pub(super) fn from_pat(
29 db: &RootDatabase,
30 file_id: HirFileId,
31 pat: AstPtr<ast::BindPat>,
32) -> Option<NameDefinition> {
33 let root = db.parse_or_expand(file_id)?;
34 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
35 match_ast! {
36 match node {
37 ast::FnDef(it) => {
38 let src = hir::Source { file_id, ast: it };
39 Some(hir::Function::from_source(db, src)?.into())
40 },
41 ast::ConstDef(it) => {
42 let src = hir::Source { file_id, ast: it };
43 Some(hir::Const::from_source(db, src)?.into())
44 },
45 ast::StaticDef(it) => {
46 let src = hir::Source { file_id, ast: it };
47 Some(hir::Static::from_source(db, src)?.into())
48 },
49 _ => None,
50 }
51 }
52 })?;
53 let item = NameKind::Pat((def, pat));
54 let container = def.module(db);
55 Some(NameDefinition { item, container, visibility: None })
56}
57
58pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition {
59 let container = item.module(db);
60 let visibility = match item {
61 AssocItem::Function(f) => f.source(db).ast.visibility(),
62 AssocItem::Const(c) => c.source(db).ast.visibility(),
63 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(),
64 };
65 let item = NameKind::AssocItem(item);
66 NameDefinition { item, container, visibility }
67}
68
69pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition {
70 let item = NameKind::Field(field);
71 let parent = field.parent_def(db);
72 let container = parent.module(db);
73 let visibility = match parent {
74 VariantDef::Struct(s) => s.source(db).ast.visibility(),
75 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(),
76 };
77 NameDefinition { item, container, visibility }
78}
79
80pub(super) fn from_module_def(db: &RootDatabase, def: ModuleDef) -> NameDefinition {
81 let item = NameKind::Def(def);
82 let (container, visibility) = match def {
83 ModuleDef::Module(it) => {
84 let container = it.parent(db).or_else(|| Some(it)).unwrap();
85 let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility());
86 (container, visibility)
87 }
88 ModuleDef::EnumVariant(it) => {
89 let container = it.module(db);
90 let visibility = it.source(db).ast.parent_enum().visibility();
91 (container, visibility)
92 }
93 ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()),
94 ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()),
95 ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()),
96 ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()),
97 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()),
98 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()),
99 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()),
100 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()),
101 ModuleDef::BuiltinType(..) => unreachable!(),
102 };
103 NameDefinition { item, container, visibility }
104}