diff options
Diffstat (limited to 'crates/ra_ide/src/references')
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 106 | ||||
-rw-r--r-- | crates/ra_ide/src/references/name_definition.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 2 |
3 files changed, 53 insertions, 57 deletions
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 3483a7176..46cba30a3 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceAnalyzer}; | 3 | use hir::{InFile, PathResolution, SourceBinder}; |
4 | use ra_prof::profile; | 4 | use ra_prof::profile; |
5 | use ra_syntax::{ast, match_ast, AstNode}; | 5 | use ra_syntax::{ast, match_ast, AstNode}; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -11,7 +11,10 @@ use super::{ | |||
11 | }; | 11 | }; |
12 | use crate::db::RootDatabase; | 12 | use crate::db::RootDatabase; |
13 | 13 | ||
14 | pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Option<NameDefinition> { | 14 | pub(crate) fn classify_name( |
15 | sb: &mut SourceBinder<RootDatabase>, | ||
16 | name: InFile<&ast::Name>, | ||
17 | ) -> Option<NameDefinition> { | ||
15 | let _p = profile("classify_name"); | 18 | let _p = profile("classify_name"); |
16 | let parent = name.value.syntax().parent()?; | 19 | let parent = name.value.syntax().parent()?; |
17 | 20 | ||
@@ -19,90 +22,79 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti | |||
19 | match parent { | 22 | match parent { |
20 | ast::BindPat(it) => { | 23 | ast::BindPat(it) => { |
21 | let src = name.with_value(it); | 24 | let src = name.with_value(it); |
22 | let local = hir::Local::from_source(db, src)?; | 25 | let local = sb.to_def(src)?; |
23 | Some(NameDefinition { | 26 | Some(NameDefinition { |
24 | visibility: None, | 27 | visibility: None, |
25 | container: local.module(db), | 28 | container: local.module(sb.db), |
26 | kind: NameKind::Local(local), | 29 | kind: NameKind::Local(local), |
27 | }) | 30 | }) |
28 | }, | 31 | }, |
29 | ast::RecordFieldDef(it) => { | 32 | ast::RecordFieldDef(it) => { |
30 | let ast = hir::FieldSource::Named(it); | 33 | let src = name.with_value(it); |
31 | let src = name.with_value(ast); | 34 | let field: hir::StructField = sb.to_def(src)?; |
32 | let field = hir::StructField::from_source(db, src)?; | 35 | Some(from_struct_field(sb.db, field)) |
33 | Some(from_struct_field(db, field)) | ||
34 | }, | 36 | }, |
35 | ast::Module(it) => { | 37 | ast::Module(it) => { |
36 | let def = { | 38 | let def = sb.to_def(name.with_value(it))?; |
37 | if !it.has_semi() { | 39 | Some(from_module_def(sb.db, def.into(), None)) |
38 | let ast = hir::ModuleSource::Module(it); | ||
39 | let src = name.with_value(ast); | ||
40 | hir::Module::from_definition(db, src) | ||
41 | } else { | ||
42 | let src = name.with_value(it); | ||
43 | hir::Module::from_declaration(db, src) | ||
44 | } | ||
45 | }?; | ||
46 | Some(from_module_def(db, def.into(), None)) | ||
47 | }, | 40 | }, |
48 | ast::StructDef(it) => { | 41 | ast::StructDef(it) => { |
49 | let src = name.with_value(it); | 42 | let src = name.with_value(it); |
50 | let def = hir::Struct::from_source(db, src)?; | 43 | let def: hir::Struct = sb.to_def(src)?; |
51 | Some(from_module_def(db, def.into(), None)) | 44 | Some(from_module_def(sb.db, def.into(), None)) |
52 | }, | 45 | }, |
53 | ast::EnumDef(it) => { | 46 | ast::EnumDef(it) => { |
54 | let src = name.with_value(it); | 47 | let src = name.with_value(it); |
55 | let def = hir::Enum::from_source(db, src)?; | 48 | let def: hir::Enum = sb.to_def(src)?; |
56 | Some(from_module_def(db, def.into(), None)) | 49 | Some(from_module_def(sb.db, def.into(), None)) |
57 | }, | 50 | }, |
58 | ast::TraitDef(it) => { | 51 | ast::TraitDef(it) => { |
59 | let src = name.with_value(it); | 52 | let src = name.with_value(it); |
60 | let def = hir::Trait::from_source(db, src)?; | 53 | let def: hir::Trait = sb.to_def(src)?; |
61 | Some(from_module_def(db, def.into(), None)) | 54 | Some(from_module_def(sb.db, def.into(), None)) |
62 | }, | 55 | }, |
63 | ast::StaticDef(it) => { | 56 | ast::StaticDef(it) => { |
64 | let src = name.with_value(it); | 57 | let src = name.with_value(it); |
65 | let def = hir::Static::from_source(db, src)?; | 58 | let def: hir::Static = sb.to_def(src)?; |
66 | Some(from_module_def(db, def.into(), None)) | 59 | Some(from_module_def(sb.db, def.into(), None)) |
67 | }, | 60 | }, |
68 | ast::EnumVariant(it) => { | 61 | ast::EnumVariant(it) => { |
69 | let src = name.with_value(it); | 62 | let src = name.with_value(it); |
70 | let def = hir::EnumVariant::from_source(db, src)?; | 63 | let def: hir::EnumVariant = sb.to_def(src)?; |
71 | Some(from_module_def(db, def.into(), None)) | 64 | Some(from_module_def(sb.db, def.into(), None)) |
72 | }, | 65 | }, |
73 | ast::FnDef(it) => { | 66 | ast::FnDef(it) => { |
74 | let src = name.with_value(it); | 67 | let src = name.with_value(it); |
75 | let def = hir::Function::from_source(db, src)?; | 68 | let def: hir::Function = sb.to_def(src)?; |
76 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | 69 | if parent.parent().and_then(ast::ItemList::cast).is_some() { |
77 | Some(from_assoc_item(db, def.into())) | 70 | Some(from_assoc_item(sb.db, def.into())) |
78 | } else { | 71 | } else { |
79 | Some(from_module_def(db, def.into(), None)) | 72 | Some(from_module_def(sb.db, def.into(), None)) |
80 | } | 73 | } |
81 | }, | 74 | }, |
82 | ast::ConstDef(it) => { | 75 | ast::ConstDef(it) => { |
83 | let src = name.with_value(it); | 76 | let src = name.with_value(it); |
84 | let def = hir::Const::from_source(db, src)?; | 77 | let def: hir::Const = sb.to_def(src)?; |
85 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | 78 | if parent.parent().and_then(ast::ItemList::cast).is_some() { |
86 | Some(from_assoc_item(db, def.into())) | 79 | Some(from_assoc_item(sb.db, def.into())) |
87 | } else { | 80 | } else { |
88 | Some(from_module_def(db, def.into(), None)) | 81 | Some(from_module_def(sb.db, def.into(), None)) |
89 | } | 82 | } |
90 | }, | 83 | }, |
91 | ast::TypeAliasDef(it) => { | 84 | ast::TypeAliasDef(it) => { |
92 | let src = name.with_value(it); | 85 | let src = name.with_value(it); |
93 | let def = hir::TypeAlias::from_source(db, src)?; | 86 | let def: hir::TypeAlias = sb.to_def(src)?; |
94 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | 87 | if parent.parent().and_then(ast::ItemList::cast).is_some() { |
95 | Some(from_assoc_item(db, def.into())) | 88 | Some(from_assoc_item(sb.db, def.into())) |
96 | } else { | 89 | } else { |
97 | Some(from_module_def(db, def.into(), None)) | 90 | Some(from_module_def(sb.db, def.into(), None)) |
98 | } | 91 | } |
99 | }, | 92 | }, |
100 | ast::MacroCall(it) => { | 93 | ast::MacroCall(it) => { |
101 | let src = name.with_value(it); | 94 | let src = name.with_value(it); |
102 | let def = hir::MacroDef::from_source(db, src.clone())?; | 95 | let def = sb.to_def(src.clone())?; |
103 | 96 | ||
104 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); | 97 | let module = sb.to_module_def(src.file_id.original_file(sb.db))?; |
105 | let module = Module::from_definition(db, src.with_value(module_src))?; | ||
106 | 98 | ||
107 | Some(NameDefinition { | 99 | Some(NameDefinition { |
108 | visibility: None, | 100 | visibility: None, |
@@ -112,10 +104,10 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti | |||
112 | }, | 104 | }, |
113 | ast::TypeParam(it) => { | 105 | ast::TypeParam(it) => { |
114 | let src = name.with_value(it); | 106 | let src = name.with_value(it); |
115 | let def = hir::TypeParam::from_source(db, src)?; | 107 | let def = sb.to_def(src)?; |
116 | Some(NameDefinition { | 108 | Some(NameDefinition { |
117 | visibility: None, | 109 | visibility: None, |
118 | container: def.module(db), | 110 | container: def.module(sb.db), |
119 | kind: NameKind::TypeParam(def), | 111 | kind: NameKind::TypeParam(def), |
120 | }) | 112 | }) |
121 | }, | 113 | }, |
@@ -125,25 +117,25 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti | |||
125 | } | 117 | } |
126 | 118 | ||
127 | pub(crate) fn classify_name_ref( | 119 | pub(crate) fn classify_name_ref( |
128 | db: &RootDatabase, | 120 | sb: &mut SourceBinder<RootDatabase>, |
129 | name_ref: InFile<&ast::NameRef>, | 121 | name_ref: InFile<&ast::NameRef>, |
130 | ) -> Option<NameDefinition> { | 122 | ) -> Option<NameDefinition> { |
131 | let _p = profile("classify_name_ref"); | 123 | let _p = profile("classify_name_ref"); |
132 | 124 | ||
133 | let parent = name_ref.value.syntax().parent()?; | 125 | let parent = name_ref.value.syntax().parent()?; |
134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); | 126 | let analyzer = sb.analyze(name_ref.map(|it| it.syntax()), None); |
135 | 127 | ||
136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 128 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
137 | tested_by!(goto_def_for_methods); | 129 | tested_by!(goto_def_for_methods); |
138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 130 | if let Some(func) = analyzer.resolve_method_call(&method_call) { |
139 | return Some(from_assoc_item(db, func.into())); | 131 | return Some(from_assoc_item(sb.db, func.into())); |
140 | } | 132 | } |
141 | } | 133 | } |
142 | 134 | ||
143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 135 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
144 | tested_by!(goto_def_for_fields); | 136 | tested_by!(goto_def_for_fields); |
145 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 137 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
146 | return Some(from_struct_field(db, field)); | 138 | return Some(from_struct_field(sb.db, field)); |
147 | } | 139 | } |
148 | } | 140 | } |
149 | 141 | ||
@@ -151,35 +143,37 @@ pub(crate) fn classify_name_ref( | |||
151 | tested_by!(goto_def_for_record_fields); | 143 | tested_by!(goto_def_for_record_fields); |
152 | tested_by!(goto_def_for_field_init_shorthand); | 144 | tested_by!(goto_def_for_field_init_shorthand); |
153 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | 145 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { |
154 | return Some(from_struct_field(db, field_def)); | 146 | return Some(from_struct_field(sb.db, field_def)); |
155 | } | 147 | } |
156 | } | 148 | } |
157 | 149 | ||
158 | let ast = ModuleSource::from_child_node(db, name_ref.with_value(&parent)); | ||
159 | // FIXME: find correct container and visibility for each case | 150 | // FIXME: find correct container and visibility for each case |
160 | let container = Module::from_definition(db, name_ref.with_value(ast))?; | ||
161 | let visibility = None; | 151 | let visibility = None; |
152 | let container = sb.to_module_def(name_ref.file_id.original_file(sb.db))?; | ||
162 | 153 | ||
163 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 154 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
164 | tested_by!(goto_def_for_macros); | 155 | tested_by!(goto_def_for_macros); |
165 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { | 156 | if let Some(macro_def) = |
157 | analyzer.resolve_macro_call(sb.db, name_ref.with_value(¯o_call)) | ||
158 | { | ||
166 | let kind = NameKind::Macro(macro_def); | 159 | let kind = NameKind::Macro(macro_def); |
167 | return Some(NameDefinition { kind, container, visibility }); | 160 | return Some(NameDefinition { kind, container, visibility }); |
168 | } | 161 | } |
169 | } | 162 | } |
170 | 163 | ||
171 | let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; | 164 | let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; |
172 | let resolved = analyzer.resolve_path(db, &path)?; | 165 | let resolved = analyzer.resolve_path(sb.db, &path)?; |
173 | match resolved { | 166 | match resolved { |
174 | PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), | 167 | PathResolution::Def(def) => Some(from_module_def(sb.db, def, Some(container))), |
175 | PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)), | 168 | PathResolution::AssocItem(item) => Some(from_assoc_item(sb.db, item)), |
176 | PathResolution::Local(local) => { | 169 | PathResolution::Local(local) => { |
177 | let container = local.module(db); | ||
178 | let kind = NameKind::Local(local); | 170 | let kind = NameKind::Local(local); |
171 | let container = local.module(sb.db); | ||
179 | Some(NameDefinition { kind, container, visibility: None }) | 172 | Some(NameDefinition { kind, container, visibility: None }) |
180 | } | 173 | } |
181 | PathResolution::TypeParam(par) => { | 174 | PathResolution::TypeParam(par) => { |
182 | let kind = NameKind::TypeParam(par); | 175 | let kind = NameKind::TypeParam(par); |
176 | let container = par.module(sb.db); | ||
183 | Some(NameDefinition { kind, container, visibility }) | 177 | Some(NameDefinition { kind, container, visibility }) |
184 | } | 178 | } |
185 | PathResolution::Macro(def) => { | 179 | PathResolution::Macro(def) => { |
@@ -188,7 +182,7 @@ pub(crate) fn classify_name_ref( | |||
188 | } | 182 | } |
189 | PathResolution::SelfType(impl_block) => { | 183 | PathResolution::SelfType(impl_block) => { |
190 | let kind = NameKind::SelfType(impl_block); | 184 | let kind = NameKind::SelfType(impl_block); |
191 | let container = impl_block.module(db); | 185 | let container = impl_block.module(sb.db); |
192 | Some(NameDefinition { kind, container, visibility }) | 186 | Some(NameDefinition { kind, container, visibility }) |
193 | } | 187 | } |
194 | } | 188 | } |
diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs index 8c67c8863..1e4226ab9 100644 --- a/crates/ra_ide/src/references/name_definition.rs +++ b/crates/ra_ide/src/references/name_definition.rs | |||
@@ -25,6 +25,8 @@ pub enum NameKind { | |||
25 | #[derive(PartialEq, Eq)] | 25 | #[derive(PartialEq, Eq)] |
26 | pub(crate) struct NameDefinition { | 26 | pub(crate) struct NameDefinition { |
27 | pub visibility: Option<ast::Visibility>, | 27 | pub visibility: Option<ast::Visibility>, |
28 | /// FIXME: this doesn't really make sense. For example, builtin types don't | ||
29 | /// really have a module. | ||
28 | pub container: Module, | 30 | pub container: Module, |
29 | pub kind: NameKind, | 31 | pub kind: NameKind, |
30 | } | 32 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index e02985dcd..626efb603 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -63,7 +63,7 @@ fn rename_mod( | |||
63 | let mut source_file_edits = Vec::new(); | 63 | let mut source_file_edits = Vec::new(); |
64 | let mut file_system_edits = Vec::new(); | 64 | let mut file_system_edits = Vec::new(); |
65 | let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; | 65 | let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; |
66 | if let Some(module) = hir::Module::from_declaration(db, module_src) { | 66 | if let Some(module) = hir::SourceBinder::new(db).to_def(module_src) { |
67 | let src = module.definition_source(db); | 67 | let src = module.definition_source(db); |
68 | let file_id = src.file_id.original_file(db); | 68 | let file_id = src.file_id.original_file(db); |
69 | match src.value { | 69 | match src.value { |