Skip to content

Commit a2f7ca2

Browse files
authored
Merge pull request #3678 from edwin0cheng/refactor-rename
Fix rename argument in macro call
2 parents 851a034 + af8c37c commit a2f7ca2

File tree

4 files changed

+112
-26
lines changed

4 files changed

+112
-26
lines changed

crates/ra_hir/src/semantics.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use hir_expand::ExpansionInfo;
1212
use ra_db::{FileId, FileRange};
1313
use ra_prof::profile;
1414
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,
1617
};
1718
use rustc_hash::{FxHashMap, FxHashSet};
1819

@@ -108,6 +109,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
108109
token.value
109110
}
110111

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+
111123
pub fn original_range(&self, node: &SyntaxNode) -> FileRange {
112124
let node = self.find_file(node.clone());
113125
original_range(self.db, node.as_ref())
@@ -129,6 +141,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
129141
.kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
130142
}
131143

144+
/// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
145+
/// search up until it is of the target AstNode type
132146
pub fn find_node_at_offset_with_macros<N: AstNode>(
133147
&self,
134148
node: &SyntaxNode,
@@ -137,6 +151,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
137151
self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast)
138152
}
139153

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+
140167
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
141168
self.analyze(expr.syntax()).type_of(self.db, &expr)
142169
}

crates/ra_ide/src/references.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,16 @@ pub(crate) fn find_all_refs(
9494
let sema = Semantics::new(db);
9595
let syntax = sema.parse(position.file_id).syntax().clone();
9696

97-
let (opt_name, search_kind) =
98-
if let Some(name) = get_struct_def_name_for_struct_literal_search(&syntax, position) {
99-
(Some(name), ReferenceKind::StructLiteral)
100-
} else {
101-
(find_node_at_offset::<ast::Name>(&syntax, position.offset), ReferenceKind::Other)
102-
};
97+
let (opt_name, search_kind) = if let Some(name) =
98+
get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
99+
{
100+
(Some(name), ReferenceKind::StructLiteral)
101+
} else {
102+
(
103+
sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset),
104+
ReferenceKind::Other,
105+
)
106+
};
103107

104108
let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?;
105109

@@ -131,7 +135,8 @@ fn find_name(
131135
let range = name.syntax().text_range();
132136
return Some(RangeInfo::new(range, def));
133137
}
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)?;
135140
let def = classify_name_ref(sema, &name_ref)?.definition();
136141
let range = name_ref.syntax().text_range();
137142
Some(RangeInfo::new(range, def))
@@ -157,17 +162,26 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio
157162
}
158163

159164
fn get_struct_def_name_for_struct_literal_search(
165+
sema: &Semantics<RootDatabase>,
160166
syntax: &SyntaxNode,
161167
position: FilePosition,
162168
) -> Option<ast::Name> {
163169
if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) {
164170
if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN {
165171
return None;
166172
}
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+
{
168176
return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name());
169177
}
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+
{
171185
return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name());
172186
}
173187
}

crates/ra_ide/src/references/rename.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,63 @@ mod tests {
249249
);
250250
}
251251

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+
252309
#[test]
253310
fn test_rename_for_param_inside() {
254311
test_rename(

crates/ra_ide_db/src/search.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ use hir::{DefWithBody, HasSource, ModuleSource, Semantics};
1010
use once_cell::unsync::Lazy;
1111
use ra_db::{FileId, FileRange, SourceDatabaseExt};
1212
use ra_prof::profile;
13-
use ra_syntax::{
14-
algo::find_node_at_offset, ast, match_ast, AstNode, TextRange, TextUnit, TokenAtOffset,
15-
};
13+
use ra_syntax::{ast, match_ast, AstNode, TextRange, TextUnit};
1614
use rustc_hash::FxHashMap;
1715
use test_utils::tested_by;
1816

@@ -219,21 +217,11 @@ impl Definition {
219217
continue;
220218
}
221219

222-
let name_ref =
223-
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&tree, offset) {
220+
let name_ref: ast::NameRef =
221+
if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) {
224222
name_ref
225223
} else {
226-
// Handle macro token cases
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-
}
224+
continue;
237225
};
238226

239227
// FIXME: reuse sb

0 commit comments

Comments
 (0)