diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 29 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 32 | ||||
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 57 | ||||
-rw-r--r-- | crates/ra_ide_db/src/search.rs | 20 |
4 files changed, 112 insertions, 26 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 55e634528..d982f6ffa 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -12,7 +12,8 @@ use hir_expand::ExpansionInfo; | |||
12 | use ra_db::{FileId, FileRange}; | 12 | use ra_db::{FileId, FileRange}; |
13 | use ra_prof::profile; | 13 | use ra_prof::profile; |
14 | use ra_syntax::{ | 14 | use ra_syntax::{ |
15 | algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, | 15 | algo::{find_node_at_offset, skip_trivia_token}, |
16 | ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, | ||
16 | }; | 17 | }; |
17 | use rustc_hash::{FxHashMap, FxHashSet}; | 18 | use rustc_hash::{FxHashMap, FxHashSet}; |
18 | 19 | ||
@@ -108,6 +109,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
108 | token.value | 109 | token.value |
109 | } | 110 | } |
110 | 111 | ||
112 | pub fn descend_node_at_offset<N: ast::AstNode>( | ||
113 | &self, | ||
114 | node: &SyntaxNode, | ||
115 | offset: TextUnit, | ||
116 | ) -> Option<N> { | ||
117 | // Handle macro token cases | ||
118 | node.token_at_offset(offset) | ||
119 | .map(|token| self.descend_into_macros(token)) | ||
120 | .find_map(|it| self.ancestors_with_macros(it.parent()).find_map(N::cast)) | ||
121 | } | ||
122 | |||
111 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | 123 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { |
112 | let node = self.find_file(node.clone()); | 124 | let node = self.find_file(node.clone()); |
113 | original_range(self.db, node.as_ref()) | 125 | original_range(self.db, node.as_ref()) |
@@ -129,6 +141,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
129 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 141 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
130 | } | 142 | } |
131 | 143 | ||
144 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | ||
145 | /// search up until it is of the target AstNode type | ||
132 | pub fn find_node_at_offset_with_macros<N: AstNode>( | 146 | pub fn find_node_at_offset_with_macros<N: AstNode>( |
133 | &self, | 147 | &self, |
134 | node: &SyntaxNode, | 148 | node: &SyntaxNode, |
@@ -137,6 +151,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
137 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | 151 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) |
138 | } | 152 | } |
139 | 153 | ||
154 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | ||
155 | /// descend it and find again | ||
156 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
157 | &self, | ||
158 | node: &SyntaxNode, | ||
159 | offset: TextUnit, | ||
160 | ) -> Option<N> { | ||
161 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
162 | return Some(it); | ||
163 | } | ||
164 | self.descend_node_at_offset(&node, offset) | ||
165 | } | ||
166 | |||
140 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 167 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
141 | self.analyze(expr.syntax()).type_of(self.db, &expr) | 168 | self.analyze(expr.syntax()).type_of(self.db, &expr) |
142 | } | 169 | } |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 3ea0ac230..746cc86ba 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -94,12 +94,16 @@ pub(crate) fn find_all_refs( | |||
94 | let sema = Semantics::new(db); | 94 | let sema = Semantics::new(db); |
95 | let syntax = sema.parse(position.file_id).syntax().clone(); | 95 | let syntax = sema.parse(position.file_id).syntax().clone(); |
96 | 96 | ||
97 | let (opt_name, search_kind) = | 97 | let (opt_name, search_kind) = if let Some(name) = |
98 | if let Some(name) = get_struct_def_name_for_struct_literal_search(&syntax, position) { | 98 | get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) |
99 | (Some(name), ReferenceKind::StructLiteral) | 99 | { |
100 | } else { | 100 | (Some(name), ReferenceKind::StructLiteral) |
101 | (find_node_at_offset::<ast::Name>(&syntax, position.offset), ReferenceKind::Other) | 101 | } else { |
102 | }; | 102 | ( |
103 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), | ||
104 | ReferenceKind::Other, | ||
105 | ) | ||
106 | }; | ||
103 | 107 | ||
104 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; | 108 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; |
105 | 109 | ||
@@ -131,7 +135,8 @@ fn find_name( | |||
131 | let range = name.syntax().text_range(); | 135 | let range = name.syntax().text_range(); |
132 | return Some(RangeInfo::new(range, def)); | 136 | return Some(RangeInfo::new(range, def)); |
133 | } | 137 | } |
134 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; | 138 | let name_ref = |
139 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; | ||
135 | let def = classify_name_ref(sema, &name_ref)?.definition(); | 140 | let def = classify_name_ref(sema, &name_ref)?.definition(); |
136 | let range = name_ref.syntax().text_range(); | 141 | let range = name_ref.syntax().text_range(); |
137 | Some(RangeInfo::new(range, def)) | 142 | Some(RangeInfo::new(range, def)) |
@@ -157,6 +162,7 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio | |||
157 | } | 162 | } |
158 | 163 | ||
159 | fn get_struct_def_name_for_struct_literal_search( | 164 | fn get_struct_def_name_for_struct_literal_search( |
165 | sema: &Semantics<RootDatabase>, | ||
160 | syntax: &SyntaxNode, | 166 | syntax: &SyntaxNode, |
161 | position: FilePosition, | 167 | position: FilePosition, |
162 | ) -> Option<ast::Name> { | 168 | ) -> Option<ast::Name> { |
@@ -164,10 +170,18 @@ fn get_struct_def_name_for_struct_literal_search( | |||
164 | if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { | 170 | if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { |
165 | return None; | 171 | return None; |
166 | } | 172 | } |
167 | if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, left.text_range().start()) { | 173 | if let Some(name) = |
174 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) | ||
175 | { | ||
168 | return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); | 176 | return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); |
169 | } | 177 | } |
170 | if find_node_at_offset::<ast::TypeParamList>(&syntax, left.text_range().start()).is_some() { | 178 | if sema |
179 | .find_node_at_offset_with_descend::<ast::TypeParamList>( | ||
180 | &syntax, | ||
181 | left.text_range().start(), | ||
182 | ) | ||
183 | .is_some() | ||
184 | { | ||
171 | return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); | 185 | return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); |
172 | } | 186 | } |
173 | } | 187 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 7d1190af9..9acc6158a 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -250,6 +250,63 @@ mod tests { | |||
250 | } | 250 | } |
251 | 251 | ||
252 | #[test] | 252 | #[test] |
253 | fn test_rename_for_macro_args_rev() { | ||
254 | test_rename( | ||
255 | r#" | ||
256 | macro_rules! foo {($i:ident) => {$i} } | ||
257 | fn main() { | ||
258 | let a = "test"; | ||
259 | foo!(a<|>); | ||
260 | }"#, | ||
261 | "b", | ||
262 | r#" | ||
263 | macro_rules! foo {($i:ident) => {$i} } | ||
264 | fn main() { | ||
265 | let b = "test"; | ||
266 | foo!(b); | ||
267 | }"#, | ||
268 | ); | ||
269 | } | ||
270 | |||
271 | #[test] | ||
272 | fn test_rename_for_macro_define_fn() { | ||
273 | test_rename( | ||
274 | r#" | ||
275 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | ||
276 | define_fn!(foo); | ||
277 | fn main() { | ||
278 | fo<|>o(); | ||
279 | }"#, | ||
280 | "bar", | ||
281 | r#" | ||
282 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | ||
283 | define_fn!(bar); | ||
284 | fn main() { | ||
285 | bar(); | ||
286 | }"#, | ||
287 | ); | ||
288 | } | ||
289 | |||
290 | #[test] | ||
291 | fn test_rename_for_macro_define_fn_rev() { | ||
292 | test_rename( | ||
293 | r#" | ||
294 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | ||
295 | define_fn!(fo<|>o); | ||
296 | fn main() { | ||
297 | foo(); | ||
298 | }"#, | ||
299 | "bar", | ||
300 | r#" | ||
301 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | ||
302 | define_fn!(bar); | ||
303 | fn main() { | ||
304 | bar(); | ||
305 | }"#, | ||
306 | ); | ||
307 | } | ||
308 | |||
309 | #[test] | ||
253 | fn test_rename_for_param_inside() { | 310 | fn test_rename_for_param_inside() { |
254 | test_rename( | 311 | test_rename( |
255 | r#" | 312 | r#" |
diff --git a/crates/ra_ide_db/src/search.rs b/crates/ra_ide_db/src/search.rs index cf78d3e41..117454695 100644 --- a/crates/ra_ide_db/src/search.rs +++ b/crates/ra_ide_db/src/search.rs | |||
@@ -10,9 +10,7 @@ use hir::{DefWithBody, HasSource, ModuleSource, Semantics}; | |||
10 | use once_cell::unsync::Lazy; | 10 | use once_cell::unsync::Lazy; |
11 | use ra_db::{FileId, FileRange, SourceDatabaseExt}; | 11 | use ra_db::{FileId, FileRange, SourceDatabaseExt}; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ast, match_ast, AstNode, TextRange, TextUnit}; |
14 | algo::find_node_at_offset, ast, match_ast, AstNode, TextRange, TextUnit, TokenAtOffset, | ||
15 | }; | ||
16 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
17 | use test_utils::tested_by; | 15 | use test_utils::tested_by; |
18 | 16 | ||
@@ -219,21 +217,11 @@ impl Definition { | |||
219 | continue; | 217 | continue; |
220 | } | 218 | } |
221 | 219 | ||
222 | let name_ref = | 220 | let name_ref: ast::NameRef = |
223 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&tree, offset) { | 221 | if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) { |
224 | name_ref | 222 | name_ref |
225 | } else { | 223 | } else { |
226 | // Handle macro token cases | 224 | continue; |
227 | let token = match tree.token_at_offset(offset) { | ||
228 | TokenAtOffset::None => continue, | ||
229 | TokenAtOffset::Single(t) => t, | ||
230 | TokenAtOffset::Between(_, t) => t, | ||
231 | }; | ||
232 | let expanded = sema.descend_into_macros(token); | ||
233 | match ast::NameRef::cast(expanded.parent()) { | ||
234 | Some(name_ref) => name_ref, | ||
235 | _ => continue, | ||
236 | } | ||
237 | }; | 225 | }; |
238 | 226 | ||
239 | // FIXME: reuse sb | 227 | // FIXME: reuse sb |