10899: ide: hack to make self not unresolved reference in async trait wrapped impl's r=Veykril a=jhgg

fixes #10708 

this is a bit hacky, but it "works". 

i'm not sure how to even write a test for this though, but i've confirmed it works via manual testing...

Co-authored-by: Jake Heinz <jh@discordapp.com>
This commit is contained in:
bors[bot] 2021-12-01 12:36:17 +00:00 committed by GitHub
commit 4691a0647b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -281,8 +281,18 @@ fn highlight_name_ref(
return if syntactic_name_ref_highlighting {
highlight_name_ref_by_syntax(name_ref, sema, krate)
} else {
HlTag::UnresolvedReference.into()
}
// FIXME: Workaround for https://github.com/rust-analyzer/rust-analyzer/issues/10708
//
// Some popular proc macros (namely async_trait) will rewrite `self` in such a way that it no
// longer resolves via NameRefClass. If we can't be resolved, but we know we're a self token,
// within a function with a self param, pretend to still be `self`, rather than
// an unresolved reference.
if name_ref.self_token().is_some() && is_in_fn_with_self_param(&name_ref) {
SymbolKind::SelfParam.into()
} else {
HlTag::UnresolvedReference.into()
}
};
}
};
let mut h = match name_class {
@ -751,3 +761,11 @@ fn is_child_of_impl(token: &SyntaxToken) -> bool {
_ => false,
}
}
fn is_in_fn_with_self_param<N: AstNode>(node: &N) -> bool {
node.syntax()
.ancestors()
.find_map(ast::Fn::cast)
.and_then(|s| s.param_list()?.self_param())
.is_some()
}