Don't classify attribute macros as their path unless it's a function with the proc_macro_attribute attribute

This commit is contained in:
Lukas Wirth 2021-02-13 22:11:31 +01:00
parent 205e72f34d
commit 403a63d2b4
2 changed files with 46 additions and 3 deletions

View file

@ -1127,4 +1127,39 @@ impl Foo {
"#]],
);
}
#[test]
fn test_attr_differs_from_fn_with_same_name() {
check(
r#"
#[test]
fn test$0() {
test();
}
"#,
expect![[r#"
test Function FileId(0) 0..33 11..15
FileId(0) 24..28
"#]],
);
}
#[test]
fn test_attr_matches_proc_macro_fn() {
check(
r#"
#[proc_macro_attribute]
fn my_proc_macro() {}
#[my_proc_macro$0]
fn test() {}
"#,
expect![[r#"
my_proc_macro Function FileId(0) 0..45 27..40
FileId(0) 49..62
"#]],
);
}
}

View file

@ -6,8 +6,8 @@
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
use hir::{
db::HirDatabase, Crate, Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef,
Module, ModuleDef, Name, PathResolution, Semantics, Visibility,
db::HirDatabase, Crate, Field, GenericParam, HasAttrs, HasVisibility, Impl, Label, Local,
MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, Visibility,
};
use syntax::{
ast::{self, AstNode, PathSegmentKind},
@ -366,7 +366,15 @@ impl NameRefClass {
if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
if let Some(resolved) = sema.resolve_path(&path) {
return Some(NameRefClass::Definition(resolved.into()));
if path.syntax().parent().and_then(ast::Attr::cast).is_some() {
if let PathResolution::Def(ModuleDef::Function(func)) = resolved {
if func.attrs(sema.db).by_key("proc_macro_attribute").exists() {
return Some(NameRefClass::Definition(resolved.into()));
}
}
} else {
return Some(NameRefClass::Definition(resolved.into()));
}
}
}