aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references/name_definition.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-10-23 09:20:18 +0100
committerGitHub <[email protected]>2019-10-23 09:20:18 +0100
commit4f4fe14fab96c8b40763f9ed5bef51942fd7e504 (patch)
treecdf5a5b39600b41a9eee301b9760cde1282aeb33 /crates/ra_ide_api/src/references/name_definition.rs
parentc15ee97fff4324981d03f65210d794664c28f0e4 (diff)
parentdecfd28bd14b56befa17257694caacc57a090939 (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.rs113
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
6use hir::{
7 db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef,
8 Module, ModuleDef, StructField, Ty, VariantDef,
9};
10use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr};
11
12use crate::db::RootDatabase;
13
14#[derive(Debug, PartialEq, Eq)]
15pub 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)]
27pub(crate) struct NameDefinition {
28 pub visibility: Option<ast::Visibility>,
29 pub container: Module,
30 pub kind: NameKind,
31}
32
33pub(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
63pub(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
74pub(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
85pub(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}