Unnamed repository; edit this file 'description' to name the repository.
give `resolve_derive_ident` a more robust api
Lukas Wirth 2022-01-03
parent 44b0fe8 · commit 19f1ff5
-rw-r--r--crates/hir/src/semantics.rs37
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs16
-rw-r--r--crates/ide_db/src/defs.rs8
3 files changed, 39 insertions, 22 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 33cbf74f5e..b685d26081 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -356,8 +356,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.resolve_bind_pat_to_const(pat)
}
- pub fn resolve_derive_ident(&self, ident: &ast::Ident) -> Option<PathResolution> {
- self.imp.resolve_derive_ident(ident)
+ pub fn resolve_derive_ident(
+ &self,
+ derive: &ast::Attr,
+ ident: &ast::Ident,
+ ) -> Option<PathResolution> {
+ self.imp.resolve_derive_ident(derive, ident)
}
// FIXME: use this instead?
@@ -900,23 +904,26 @@ impl<'db> SemanticsImpl<'db> {
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
let syntax = ident.syntax();
- let attr = syntax.ancestors().nth(2).and_then(ast::Attr::cast)?;
- let tt = attr.token_tree()?;
- if !tt.syntax().text_range().contains_range(ident.syntax().text_range()) {
- return None;
- }
-
- let file = self.find_file(attr.syntax());
- let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
+ let tt = derive.token_tree()?;
+ let file = self.find_file(derive.syntax());
+ let adt = derive.syntax().parent().and_then(ast::Adt::cast)?;
let res = self.with_ctx(|ctx| {
- let attr_def = ctx.attr_to_def(file.with_value(attr.clone()))?;
- let derives = ctx
- .attr_to_derive_macro_call(file.with_value(&adt), file.with_value(attr.clone()))?;
+ let attr_def = ctx.attr_to_def(file.with_value(derive.clone()))?;
+ let derives = ctx.attr_to_derive_macro_call(
+ file.with_value(&adt),
+ file.with_value(derive.clone()),
+ )?;
let mut derive_paths = attr_def.parse_path_comma_token_tree()?;
@@ -951,7 +958,7 @@ impl<'db> SemanticsImpl<'db> {
match res {
Either::Left(path) => resolve_hir_path(
self.db,
- &self.scope(attr.syntax()).resolver,
+ &self.scope(derive.syntax()).resolver,
&Path::from_known_path(path, []),
)
.filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index f82ccaa1c7..688f181d91 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -39,11 +39,17 @@ pub(super) fn token(
INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
BYTE => HlTag::ByteLiteral.into(),
CHAR => HlTag::CharLiteral.into(),
- IDENT if parent_matches::<ast::TokenTree>(&token) => {
- match sema.resolve_derive_ident(&ast::Ident::cast(token).unwrap()) {
- Some(res) => highlight_def(sema, krate, Definition::from(res)),
- None => HlTag::None.into(),
- }
+ IDENT => {
+ let tt = ast::TokenTree::cast(token.parent()?)?;
+ let ident = ast::Ident::cast(token)?;
+ // 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),
k if k.is_keyword() => keyword(sema, token, k)?,
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index d69fd9bd21..1501c4eda5 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -55,8 +55,12 @@ impl Definition {
let attr = ast::TokenTree::cast(parent.clone())
.and_then(|tt| tt.parent_meta())
.and_then(|meta| meta.parent_attr());
- if let Some(_) = attr {
- return sema.resolve_derive_ident(&ident).map(Into::into).into_iter().collect();
+ if let Some(attr) = attr {
+ return sema
+ .resolve_derive_ident(&attr, &ident)
+ .map(Into::into)
+ .into_iter()
+ .collect();
}
}
Self::from_node(sema, &parent)