diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2021-10-19 13:40:27 +0200 |
|---|---|---|
| committer | Lukas Wirth <lukastw97@gmail.com> | 2021-10-19 13:42:36 +0200 |
| commit | aa9d0934887fced0437c1e09ea5255185cac5631 (patch) | |
| tree | fcf982997ef6cfe365d5ef34c0a7b54ad55a7954 | |
| parent | 401daa5f77fd9cfb79d16fe3a54bc576d60b4c82 (diff) | |
| download | rust-aa9d0934887fced0437c1e09ea5255185cac5631.tar.gz rust-aa9d0934887fced0437c1e09ea5255185cac5631.zip | |
Resolve derive attributes even when shadowed
| -rw-r--r-- | crates/hir/src/semantics.rs | 12 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 9 | ||||
| -rw-r--r-- | crates/ide_db/src/helpers.rs | 9 |
3 files changed, 23 insertions, 7 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index b6e5ee75313..ca23d85cb24 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -24,7 +24,7 @@ use syntax::{ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, - source_analyzer::{resolve_hir_path, SourceAnalyzer}, + source_analyzer::{resolve_hir_path, resolve_hir_path_as_macro, SourceAnalyzer}, Access, AssocItem, Callable, ConstParam, Crate, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, @@ -1134,4 +1134,14 @@ impl<'a> SemanticsScope<'a> { let path = Path::from_src(path.clone(), &ctx)?; resolve_hir_path(self.db, &self.resolver, &path) } + + /// Resolve a path as-if it was written at the given scope. This is + /// necessary a heuristic, as it doesn't take hygiene into account. + // FIXME: This special casing solely exists for attributes for now + // ideally we should have a path resolution infra that properly knows about overlapping namespaces + pub fn speculative_resolve_as_mac(&self, path: &ast::Path) -> Option<MacroDef> { + let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id); + let path = Path::from_src(path.clone(), &ctx)?; + resolve_hir_path_as_macro(self.db, &self.resolver, &path) + } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 960b290e266..08d0a02d796 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -502,6 +502,15 @@ pub(crate) fn resolve_hir_path( resolve_hir_path_(db, resolver, path, false) } +#[inline] +pub(crate) fn resolve_hir_path_as_macro( + db: &dyn HirDatabase, + resolver: &Resolver, + path: &Path, +) -> Option<MacroDef> { + resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(Into::into) +} + fn resolve_hir_path_( db: &dyn HirDatabase, resolver: &Resolver, diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index a8087d47fe2..173e55b33f6 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -53,12 +53,9 @@ pub fn try_resolve_derive_input_at( .take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,]) .collect(); let path = ast::Path::parse(&tokens.into_iter().rev().join("")).ok()?; - match sema.scope(tt.syntax()).speculative_resolve(&path) { - Some(hir::PathResolution::Macro(makro)) if makro.kind() == hir::MacroKind::Derive => { - Some(makro) - } - _ => None, - } + sema.scope(tt.syntax()) + .speculative_resolve_as_mac(&path) + .filter(|mac| mac.kind() == hir::MacroKind::Derive) } /// Picks the token with the highest rank returned by the passed in function. |
