mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
give resolve_derive_ident
a more robust api
This commit is contained in:
parent
44b0fe8ec7
commit
19f1ff5c70
3 changed files with 39 additions and 22 deletions
|
@ -356,8 +356,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
self.imp.resolve_bind_pat_to_const(pat)
|
self.imp.resolve_bind_pat_to_const(pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_derive_ident(&self, ident: &ast::Ident) -> Option<PathResolution> {
|
pub fn resolve_derive_ident(
|
||||||
self.imp.resolve_derive_ident(ident)
|
&self,
|
||||||
|
derive: &ast::Attr,
|
||||||
|
ident: &ast::Ident,
|
||||||
|
) -> Option<PathResolution> {
|
||||||
|
self.imp.resolve_derive_ident(derive, ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use this instead?
|
// FIXME: use this instead?
|
||||||
|
@ -900,23 +904,26 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
|
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_derive_ident(&self, ident: &ast::Ident) -> Option<PathResolution> {
|
fn resolve_derive_ident(
|
||||||
|
&self,
|
||||||
|
derive: &ast::Attr,
|
||||||
|
ident: &ast::Ident,
|
||||||
|
) -> Option<PathResolution> {
|
||||||
|
debug_assert!(ident.syntax().parent().and_then(ast::TokenTree::cast).is_some());
|
||||||
|
debug_assert!(ident.syntax().ancestors().any(|anc| anc == *derive.syntax()));
|
||||||
// derive macros are always at depth 2, tokentree -> meta -> attribute
|
// derive macros are always at depth 2, tokentree -> meta -> attribute
|
||||||
let syntax = ident.syntax();
|
let syntax = ident.syntax();
|
||||||
let attr = syntax.ancestors().nth(2).and_then(ast::Attr::cast)?;
|
|
||||||
|
|
||||||
let tt = attr.token_tree()?;
|
let tt = derive.token_tree()?;
|
||||||
if !tt.syntax().text_range().contains_range(ident.syntax().text_range()) {
|
let file = self.find_file(derive.syntax());
|
||||||
return None;
|
let adt = derive.syntax().parent().and_then(ast::Adt::cast)?;
|
||||||
}
|
|
||||||
|
|
||||||
let file = self.find_file(attr.syntax());
|
|
||||||
let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
|
|
||||||
|
|
||||||
let res = self.with_ctx(|ctx| {
|
let res = self.with_ctx(|ctx| {
|
||||||
let attr_def = ctx.attr_to_def(file.with_value(attr.clone()))?;
|
let attr_def = ctx.attr_to_def(file.with_value(derive.clone()))?;
|
||||||
let derives = ctx
|
let derives = ctx.attr_to_derive_macro_call(
|
||||||
.attr_to_derive_macro_call(file.with_value(&adt), file.with_value(attr.clone()))?;
|
file.with_value(&adt),
|
||||||
|
file.with_value(derive.clone()),
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut derive_paths = attr_def.parse_path_comma_token_tree()?;
|
let mut derive_paths = attr_def.parse_path_comma_token_tree()?;
|
||||||
|
|
||||||
|
@ -951,7 +958,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
match res {
|
match res {
|
||||||
Either::Left(path) => resolve_hir_path(
|
Either::Left(path) => resolve_hir_path(
|
||||||
self.db,
|
self.db,
|
||||||
&self.scope(attr.syntax()).resolver,
|
&self.scope(derive.syntax()).resolver,
|
||||||
&Path::from_known_path(path, []),
|
&Path::from_known_path(path, []),
|
||||||
)
|
)
|
||||||
.filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
|
.filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
|
||||||
|
|
|
@ -39,11 +39,17 @@ pub(super) fn token(
|
||||||
INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
|
INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
|
||||||
BYTE => HlTag::ByteLiteral.into(),
|
BYTE => HlTag::ByteLiteral.into(),
|
||||||
CHAR => HlTag::CharLiteral.into(),
|
CHAR => HlTag::CharLiteral.into(),
|
||||||
IDENT if parent_matches::<ast::TokenTree>(&token) => {
|
IDENT => {
|
||||||
match sema.resolve_derive_ident(&ast::Ident::cast(token).unwrap()) {
|
let tt = ast::TokenTree::cast(token.parent()?)?;
|
||||||
Some(res) => highlight_def(sema, krate, Definition::from(res)),
|
let ident = ast::Ident::cast(token)?;
|
||||||
None => HlTag::None.into(),
|
// from this point on we are inside a token tree, this only happens for identifiers
|
||||||
}
|
// that were not mapped down into macro invocations
|
||||||
|
(|| {
|
||||||
|
let attr = tt.parent_meta()?.parent_attr()?;
|
||||||
|
let res = sema.resolve_derive_ident(&attr, &ident)?;
|
||||||
|
Some(highlight_def(sema, krate, Definition::from(res)))
|
||||||
|
})()
|
||||||
|
.unwrap_or_else(|| HlTag::None.into())
|
||||||
}
|
}
|
||||||
p if p.is_punct() => punctuation(sema, token, p),
|
p if p.is_punct() => punctuation(sema, token, p),
|
||||||
k if k.is_keyword() => keyword(sema, token, k)?,
|
k if k.is_keyword() => keyword(sema, token, k)?,
|
||||||
|
|
|
@ -55,8 +55,12 @@ impl Definition {
|
||||||
let attr = ast::TokenTree::cast(parent.clone())
|
let attr = ast::TokenTree::cast(parent.clone())
|
||||||
.and_then(|tt| tt.parent_meta())
|
.and_then(|tt| tt.parent_meta())
|
||||||
.and_then(|meta| meta.parent_attr());
|
.and_then(|meta| meta.parent_attr());
|
||||||
if let Some(_) = attr {
|
if let Some(attr) = attr {
|
||||||
return sema.resolve_derive_ident(&ident).map(Into::into).into_iter().collect();
|
return sema
|
||||||
|
.resolve_derive_ident(&attr, &ident)
|
||||||
|
.map(Into::into)
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::from_node(sema, &parent)
|
Self::from_node(sema, &parent)
|
||||||
|
|
Loading…
Reference in a new issue