diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-10-23 09:20:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-10-23 09:20:18 +0100 |
commit | 4f4fe14fab96c8b40763f9ed5bef51942fd7e504 (patch) | |
tree | cdf5a5b39600b41a9eee301b9760cde1282aeb33 /crates/ra_ide_api/src/references/name_definition.rs | |
parent | c15ee97fff4324981d03f65210d794664c28f0e4 (diff) | |
parent | decfd28bd14b56befa17257694caacc57a090939 (diff) |
Merge #1892
1892: Find usages r=matklad a=viorina
Fixes #1622.
Co-authored-by: Ekaterina Babshukova <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/references/name_definition.rs')
-rw-r--r-- | crates/ra_ide_api/src/references/name_definition.rs | 113 |
1 files changed, 113 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..4580bc789 --- /dev/null +++ b/crates/ra_ide_api/src/references/name_definition.rs | |||
@@ -0,0 +1,113 @@ | |||
1 | //! `NameDefinition` keeps information about the element we want to search references for. | ||
2 | //! The element is represented by `NameKind`. It's located inside some `container` and | ||
3 | //! has a `visibility`, which defines a search scope. | ||
4 | //! Note that the reference search is possible for not all of the classified items. | ||
5 | |||
6 | use hir::{ | ||
7 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | ||
8 | Module, ModuleDef, StructField, Ty, VariantDef, | ||
9 | }; | ||
10 | use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; | ||
11 | |||
12 | use crate::db::RootDatabase; | ||
13 | |||
14 | #[derive(Debug, PartialEq, Eq)] | ||
15 | pub enum NameKind { | ||
16 | Macro(MacroDef), | ||
17 | Field(StructField), | ||
18 | AssocItem(AssocItem), | ||
19 | Def(ModuleDef), | ||
20 | SelfType(Ty), | ||
21 | Pat((DefWithBody, AstPtr<ast::BindPat>)), | ||
22 | SelfParam(AstPtr<ast::SelfParam>), | ||
23 | GenericParam(u32), | ||
24 | } | ||
25 | |||
26 | #[derive(PartialEq, Eq)] | ||
27 | pub(crate) struct NameDefinition { | ||
28 | pub visibility: Option<ast::Visibility>, | ||
29 | pub container: Module, | ||
30 | pub kind: NameKind, | ||
31 | } | ||
32 | |||
33 | pub(super) fn from_pat( | ||
34 | db: &RootDatabase, | ||
35 | file_id: HirFileId, | ||
36 | pat: AstPtr<ast::BindPat>, | ||
37 | ) -> Option<NameDefinition> { | ||
38 | let root = db.parse_or_expand(file_id)?; | ||
39 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | ||
40 | match_ast! { | ||
41 | match node { | ||
42 | ast::FnDef(it) => { | ||
43 | let src = hir::Source { file_id, ast: it }; | ||
44 | Some(hir::Function::from_source(db, src)?.into()) | ||
45 | }, | ||
46 | ast::ConstDef(it) => { | ||
47 | let src = hir::Source { file_id, ast: it }; | ||
48 | Some(hir::Const::from_source(db, src)?.into()) | ||
49 | }, | ||
50 | ast::StaticDef(it) => { | ||
51 | let src = hir::Source { file_id, ast: it }; | ||
52 | Some(hir::Static::from_source(db, src)?.into()) | ||
53 | }, | ||
54 | _ => None, | ||
55 | } | ||
56 | } | ||
57 | })?; | ||
58 | let kind = NameKind::Pat((def, pat)); | ||
59 | let container = def.module(db); | ||
60 | Some(NameDefinition { kind, container, visibility: None }) | ||
61 | } | ||
62 | |||
63 | pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { | ||
64 | let container = item.module(db); | ||
65 | let visibility = match item { | ||
66 | AssocItem::Function(f) => f.source(db).ast.visibility(), | ||
67 | AssocItem::Const(c) => c.source(db).ast.visibility(), | ||
68 | AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), | ||
69 | }; | ||
70 | let kind = NameKind::AssocItem(item); | ||
71 | NameDefinition { kind, container, visibility } | ||
72 | } | ||
73 | |||
74 | pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition { | ||
75 | let kind = NameKind::Field(field); | ||
76 | let parent = field.parent_def(db); | ||
77 | let container = parent.module(db); | ||
78 | let visibility = match parent { | ||
79 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | ||
80 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), | ||
81 | }; | ||
82 | NameDefinition { kind, container, visibility } | ||
83 | } | ||
84 | |||
85 | pub(super) fn from_module_def( | ||
86 | db: &RootDatabase, | ||
87 | def: ModuleDef, | ||
88 | module: Option<Module>, | ||
89 | ) -> NameDefinition { | ||
90 | let kind = NameKind::Def(def); | ||
91 | let (container, visibility) = match def { | ||
92 | ModuleDef::Module(it) => { | ||
93 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); | ||
94 | let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); | ||
95 | (container, visibility) | ||
96 | } | ||
97 | ModuleDef::EnumVariant(it) => { | ||
98 | let container = it.module(db); | ||
99 | let visibility = it.source(db).ast.parent_enum().visibility(); | ||
100 | (container, visibility) | ||
101 | } | ||
102 | ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), | ||
103 | ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), | ||
104 | ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), | ||
105 | ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), | ||
106 | ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), | ||
107 | ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
108 | ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
109 | ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
110 | ModuleDef::BuiltinType(..) => (module.unwrap(), None), | ||
111 | }; | ||
112 | NameDefinition { kind, container, visibility } | ||
113 | } | ||