Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/semantics.rs12
-rw-r--r--crates/hir/src/source_analyzer.rs9
-rw-r--r--crates/ide_db/src/helpers.rs9
3 files changed, 23 insertions, 7 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b6e5ee7531..ca23d85cb2 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 960b290e26..08d0a02d79 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 a8087d47fe..173e55b33f 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.