3064: Handle macro token cases for rename r=matklad a=edwin0cheng

Fixes #2957

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-02-11 15:46:05 +00:00 committed by GitHub
commit 305d921982
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 23 deletions

View File

@ -13,6 +13,7 @@ mod classify;
mod rename; mod rename;
mod search_scope; mod search_scope;
use crate::expand::descend_into_macros_with_analyzer;
use hir::{InFile, SourceBinder}; use hir::{InFile, SourceBinder};
use once_cell::unsync::Lazy; use once_cell::unsync::Lazy;
use ra_db::{SourceDatabase, SourceDatabaseExt}; use ra_db::{SourceDatabase, SourceDatabaseExt};
@ -192,39 +193,62 @@ fn process_definition(
let parse = Lazy::new(|| SourceFile::parse(&text)); let parse = Lazy::new(|| SourceFile::parse(&text));
let mut sb = Lazy::new(|| SourceBinder::new(db)); let mut sb = Lazy::new(|| SourceBinder::new(db));
let mut analyzer = None;
for (idx, _) in text.match_indices(pat) { for (idx, _) in text.match_indices(pat) {
let offset = TextUnit::from_usize(idx); let offset = TextUnit::from_usize(idx);
if let Some(name_ref) = let (name_ref, range) = if let Some(name_ref) =
find_node_at_offset::<ast::NameRef>(parse.tree().syntax(), offset) find_node_at_offset::<ast::NameRef>(parse.tree().syntax(), offset)
{ {
let range = name_ref.syntax().text_range(); let range = name_ref.syntax().text_range();
if let Some(search_range) = search_range { (InFile::new(file_id.into(), name_ref), range)
if !range.is_subrange(&search_range) { } else {
continue; // Handle macro token cases
} let t = match parse.tree().syntax().token_at_offset(offset) {
TokenAtOffset::None => continue,
TokenAtOffset::Single(t) => t,
TokenAtOffset::Between(_, t) => t,
};
let range = t.text_range();
let analyzer = analyzer.get_or_insert_with(|| {
sb.analyze(InFile::new(file_id.into(), parse.tree().syntax()), None)
});
let expanded = descend_into_macros_with_analyzer(
db,
&analyzer,
InFile::new(file_id.into(), t),
);
if let Some(token) = ast::NameRef::cast(expanded.value.parent()) {
(expanded.with_value(token), range)
} else {
continue;
} }
// FIXME: reuse sb };
// See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
if let Some(d) = classify_name_ref(&mut sb, InFile::new(file_id.into(), &name_ref)) if let Some(search_range) = search_range {
{ if !range.is_subrange(&search_range) {
if d == def { continue;
let kind = if is_record_lit_name_ref(&name_ref) }
|| is_call_expr_name_ref(&name_ref) }
{ // FIXME: reuse sb
ReferenceKind::StructLiteral // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
} else {
ReferenceKind::Other
};
refs.push(Reference { if let Some(d) = classify_name_ref(&mut sb, name_ref.as_ref()) {
file_range: FileRange { file_id, range }, if d == def {
kind, let kind = if is_record_lit_name_ref(&name_ref.value)
access: reference_access(&d.kind, &name_ref), || is_call_expr_name_ref(&name_ref.value)
}); {
} ReferenceKind::StructLiteral
} else {
ReferenceKind::Other
};
refs.push(Reference {
file_range: FileRange { file_id, range },
kind,
access: reference_access(&d.kind, &name_ref.value),
});
} }
} }
} }

View File

@ -210,6 +210,25 @@ mod tests {
); );
} }
#[test]
fn test_rename_for_macro_args() {
test_rename(
r#"
macro_rules! foo {($i:ident) => {$i} }
fn main() {
let a<|> = "test";
foo!(a);
}"#,
"b",
r#"
macro_rules! foo {($i:ident) => {$i} }
fn main() {
let b = "test";
foo!(b);
}"#,
);
}
#[test] #[test]
fn test_rename_for_param_inside() { fn test_rename_for_param_inside() {
test_rename( test_rename(