aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references/classify.rs
diff options
context:
space:
mode:
authorEkaterina Babshukova <[email protected]>2019-10-12 18:30:53 +0100
committerEkaterina Babshukova <[email protected]>2019-10-22 21:47:31 +0100
commit835173d065dbe1fdd7369ea49336c0b785be8cb8 (patch)
treee19916b78f4fff145ec59b790c626e2a9f538bbb /crates/ra_ide_api/src/references/classify.rs
parentd26d0ada50fd0063c03e28bc2673f9f63fd23d95 (diff)
replace trait by a bunch of functions
Diffstat (limited to 'crates/ra_ide_api/src/references/classify.rs')
-rw-r--r--crates/ra_ide_api/src/references/classify.rs196
1 files changed, 111 insertions, 85 deletions
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index 0b604a5cf..2ba1cf71c 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -1,47 +1,90 @@
1use hir::{ 1use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer};
2 AssocItem, Either, EnumVariant, FromSource, Module, ModuleDef, ModuleSource, Path,
3 PathResolution, Source, SourceAnalyzer, StructField,
4};
5use ra_db::FileId; 2use ra_db::FileId;
6use ra_syntax::{ast, match_ast, AstNode, AstPtr}; 3use ra_syntax::{ast, match_ast, AstNode, AstPtr};
7 4
8use super::{definition::HasDefinition, Definition, NameKind}; 5use super::{
6 name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field},
7 NameDefinition, NameKind,
8};
9use crate::db::RootDatabase; 9use crate::db::RootDatabase;
10 10
11use hir::{db::AstDatabase, HirFileId};
12
13pub(crate) fn classify_name( 11pub(crate) fn classify_name(
14 db: &RootDatabase, 12 db: &RootDatabase,
15 file_id: FileId, 13 file_id: FileId,
16 name: &ast::Name, 14 name: &ast::Name,
17) -> Option<Definition> { 15) -> Option<NameDefinition> {
18 let parent = name.syntax().parent()?; 16 let parent = name.syntax().parent()?;
19 let file_id = file_id.into(); 17 let file_id = file_id.into();
20 18
19 // FIXME: add ast::MacroCall(it)
21 match_ast! { 20 match_ast! {
22 match parent { 21 match parent {
23 ast::BindPat(it) => { 22 ast::BindPat(it) => {
24 decl_from_pat(db, file_id, AstPtr::new(&it)) 23 from_pat(db, file_id, AstPtr::new(&it))
25 }, 24 },
26 ast::RecordFieldDef(it) => { 25 ast::RecordFieldDef(it) => {
27 StructField::from_def(db, file_id, it) 26 let ast = hir::FieldSource::Named(it);
27 let src = hir::Source { file_id, ast };
28 let field = hir::StructField::from_source(db, src)?;
29 Some(from_struct_field(db, field))
30 },
31 ast::Module(it) => {
32 let ast = hir::ModuleSource::Module(it);
33 let src = hir::Source { file_id, ast };
34 let def = hir::Module::from_definition(db, src)?;
35 Some(from_module_def(db, def.into()))
28 }, 36 },
29 ast::ImplItem(it) => { 37 ast::StructDef(it) => {
30 AssocItem::from_def(db, file_id, it.clone()).or_else(|| { 38 let src = hir::Source { file_id, ast: it };
31 match it { 39 let def = hir::Struct::from_source(db, src)?;
32 ast::ImplItem::FnDef(f) => ModuleDef::from_def(db, file_id, f.into()), 40 Some(from_module_def(db, def.into()))
33 ast::ImplItem::ConstDef(c) => ModuleDef::from_def(db, file_id, c.into()), 41 },
34 ast::ImplItem::TypeAliasDef(a) => ModuleDef::from_def(db, file_id, a.into()), 42 ast::EnumDef(it) => {
35 } 43 let src = hir::Source { file_id, ast: it };
36 }) 44 let def = hir::Enum::from_source(db, src)?;
45 Some(from_module_def(db, def.into()))
46 },
47 ast::TraitDef(it) => {
48 let src = hir::Source { file_id, ast: it };
49 let def = hir::Trait::from_source(db, src)?;
50 Some(from_module_def(db, def.into()))
51 },
52 ast::StaticDef(it) => {
53 let src = hir::Source { file_id, ast: it };
54 let def = hir::Static::from_source(db, src)?;
55 Some(from_module_def(db, def.into()))
37 }, 56 },
38 ast::EnumVariant(it) => { 57 ast::EnumVariant(it) => {
39 let src = hir::Source { file_id, ast: it.clone() }; 58 let src = hir::Source { file_id, ast: it };
40 let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); 59 let def = hir::EnumVariant::from_source(db, src)?;
41 Some(def.definition(db)) 60 Some(from_module_def(db, def.into()))
61 },
62 ast::FnDef(it) => {
63 let src = hir::Source { file_id, ast: it };
64 let def = hir::Function::from_source(db, src)?;
65 if parent.parent().and_then(ast::ItemList::cast).is_some() {
66 Some(from_assoc_item(db, def.into()))
67 } else {
68 Some(from_module_def(db, def.into()))
69 }
70 },
71 ast::ConstDef(it) => {
72 let src = hir::Source { file_id, ast: it };
73 let def = hir::Const::from_source(db, src)?;
74 if parent.parent().and_then(ast::ItemList::cast).is_some() {
75 Some(from_assoc_item(db, def.into()))
76 } else {
77 Some(from_module_def(db, def.into()))
78 }
42 }, 79 },
43 ast::ModuleItem(it) => { 80 ast::TypeAliasDef(it) => {
44 ModuleDef::from_def(db, file_id, it) 81 let src = hir::Source { file_id, ast: it };
82 let def = hir::TypeAlias::from_source(db, src)?;
83 if parent.parent().and_then(ast::ItemList::cast).is_some() {
84 Some(from_assoc_item(db, def.into()))
85 } else {
86 Some(from_module_def(db, def.into()))
87 }
45 }, 88 },
46 _ => None, 89 _ => None,
47 } 90 }
@@ -52,92 +95,75 @@ pub(crate) fn classify_name_ref(
52 db: &RootDatabase, 95 db: &RootDatabase,
53 file_id: FileId, 96 file_id: FileId,
54 name_ref: &ast::NameRef, 97 name_ref: &ast::NameRef,
55) -> Option<Definition> { 98) -> Option<NameDefinition> {
56 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); 99 use PathResolution::*;
100
57 let parent = name_ref.syntax().parent()?; 101 let parent = name_ref.syntax().parent()?;
58 match_ast! { 102 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
59 match parent { 103
60 ast::MethodCallExpr(it) => { 104 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
61 return AssocItem::from_ref(db, &analyzer, it); 105 let func = analyzer.resolve_method_call(&method_call)?;
62 }, 106 return Some(from_assoc_item(db, func.into()));
63 ast::FieldExpr(it) => { 107 }
64 if let Some(field) = analyzer.resolve_field(&it) { 108
65 return Some(field.definition(db)); 109 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
66 } 110 if let Some(field) = analyzer.resolve_field(&field_expr) {
67 }, 111 return Some(from_struct_field(db, field));
68 ast::RecordField(it) => { 112 }
69 if let Some(record_lit) = it.syntax().ancestors().find_map(ast::RecordLit::cast) { 113 }
70 let variant_def = analyzer.resolve_record_literal(&record_lit)?; 114
71 let hir_path = Path::from_name_ref(name_ref); 115 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
72 let hir_name = hir_path.as_ident()?; 116 if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) {
73 let field = variant_def.field(db, hir_name)?; 117 let variant_def = analyzer.resolve_record_literal(&record_lit)?;
74 return Some(field.definition(db)); 118 let hir_path = Path::from_name_ref(name_ref);
75 } 119 let hir_name = hir_path.as_ident()?;
76 }, 120 let field = variant_def.field(db, hir_name)?;
77 _ => (), 121 return Some(from_struct_field(db, field));
78 } 122 }
79 } 123 }
80 124
81 let ast = ModuleSource::from_child_node(db, file_id, &parent); 125 let ast = ModuleSource::from_child_node(db, file_id, &parent);
82 let file_id = file_id.into(); 126 let file_id = file_id.into();
127 // FIXME: find correct container and visibility for each case
83 let container = Module::from_definition(db, Source { file_id, ast })?; 128 let container = Module::from_definition(db, Source { file_id, ast })?;
84 let visibility = None; 129 let visibility = None;
85 130
86 if let Some(macro_call) = 131 if let Some(macro_call) =
87 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) 132 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast)
88 { 133 {
89 if let Some(mac) = analyzer.resolve_macro_call(db, &macro_call) { 134 if let Some(macro_def) = analyzer.resolve_macro_call(db, &macro_call) {
90 return Some(Definition { item: NameKind::Macro(mac), container, visibility }); 135 return Some(NameDefinition {
136 item: NameKind::Macro(macro_def),
137 container,
138 visibility,
139 });
91 } 140 }
92 } 141 }
93 142
94 // General case, a path or a local:
95 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 143 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
96 let resolved = analyzer.resolve_path(db, &path)?; 144 let resolved = analyzer.resolve_path(db, &path)?;
97 match resolved { 145 match resolved {
98 PathResolution::Def(def) => Some(def.definition(db)), 146 Def(def) => Some(from_module_def(db, def)),
99 PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), 147 AssocItem(item) => Some(from_assoc_item(db, item)),
100 PathResolution::LocalBinding(Either::B(par)) => { 148 LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat),
101 Some(Definition { item: NameKind::SelfParam(par), container, visibility }) 149 LocalBinding(Either::B(par)) => {
150 let item = NameKind::SelfParam(par);
151 Some(NameDefinition { item, container, visibility })
102 } 152 }
103 PathResolution::GenericParam(par) => { 153 GenericParam(par) => {
104 // FIXME: get generic param def 154 // FIXME: get generic param def
105 Some(Definition { item: NameKind::GenericParam(par), container, visibility }) 155 let item = NameKind::GenericParam(par);
156 Some(NameDefinition { item, container, visibility })
106 } 157 }
107 PathResolution::Macro(def) => { 158 Macro(def) => {
108 Some(Definition { item: NameKind::Macro(def), container, visibility }) 159 let item = NameKind::Macro(def);
160 Some(NameDefinition { item, container, visibility })
109 } 161 }
110 PathResolution::SelfType(impl_block) => { 162 SelfType(impl_block) => {
111 let ty = impl_block.target_ty(db); 163 let ty = impl_block.target_ty(db);
164 let item = NameKind::SelfType(ty);
112 let container = impl_block.module(); 165 let container = impl_block.module();
113 Some(Definition { item: NameKind::SelfType(ty), container, visibility }) 166 Some(NameDefinition { item, container, visibility })
114 } 167 }
115 PathResolution::AssocItem(assoc) => Some(assoc.definition(db)),
116 } 168 }
117} 169}
118
119fn decl_from_pat(
120 db: &RootDatabase,
121 file_id: HirFileId,
122 pat: AstPtr<ast::BindPat>,
123) -> Option<Definition> {
124 let root = db.parse_or_expand(file_id)?;
125 // FIXME: use match_ast!
126 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
127 if let Some(it) = ast::FnDef::cast(node.clone()) {
128 let src = hir::Source { file_id, ast: it };
129 Some(hir::Function::from_source(db, src)?.into())
130 } else if let Some(it) = ast::ConstDef::cast(node.clone()) {
131 let src = hir::Source { file_id, ast: it };
132 Some(hir::Const::from_source(db, src)?.into())
133 } else if let Some(it) = ast::StaticDef::cast(node.clone()) {
134 let src = hir::Source { file_id, ast: it };
135 Some(hir::Static::from_source(db, src)?.into())
136 } else {
137 None
138 }
139 })?;
140 let item = NameKind::Pat((def, pat));
141 let container = def.module(db);
142 Some(Definition { item, container, visibility: None })
143}