diff options
Diffstat (limited to 'crates/ra_ide_api/src/references/name_definition.rs')
-rw-r--r-- | crates/ra_ide_api/src/references/name_definition.rs | 104 |
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 @@ | |||
1 | use hir::{ | ||
2 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | ||
3 | Module, ModuleDef, StructField, Ty, VariantDef, | ||
4 | }; | ||
5 | use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; | ||
6 | |||
7 | use crate::db::RootDatabase; | ||
8 | |||
9 | #[derive(Debug, PartialEq, Eq)] | ||
10 | pub 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)] | ||
22 | pub(crate) struct NameDefinition { | ||
23 | pub visibility: Option<ast::Visibility>, | ||
24 | pub container: Module, | ||
25 | pub item: NameKind, | ||
26 | } | ||
27 | |||
28 | pub(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 | |||
58 | pub(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 | |||
69 | pub(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 | |||
80 | pub(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 | } | ||