Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/data.rs19
-rw-r--r--crates/hir-def/src/nameres.rs4
-rw-r--r--crates/hir/src/lib.rs15
-rw-r--r--crates/hir/src/source_analyzer.rs13
-rw-r--r--crates/ide-db/src/defs.rs2
-rw-r--r--crates/ide-db/src/search.rs8
-rw-r--r--crates/ide/src/hover/render.rs3
-rw-r--r--crates/ide/src/syntax_highlighting.rs7
8 files changed, 53 insertions, 18 deletions
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 4309411419..35c8708955 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -12,7 +12,7 @@ use crate::{
db::DefDatabase,
intern::Interned,
item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
- nameres::{attr_resolution::ResolvedAttr, DefMap},
+ nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap},
type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -348,7 +348,8 @@ impl MacroRulesData {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProcMacroData {
pub name: Name,
- // FIXME: Record deriver helper here?
+ /// Derive helpers, if this is a derive
+ pub helpers: Option<Box<[Name]>>,
}
impl ProcMacroData {
@@ -360,17 +361,23 @@ impl ProcMacroData {
let item_tree = loc.id.item_tree(db);
let makro = &item_tree[loc.id.value];
- let name = if let Some(def) = item_tree
+ let (name, helpers) = if let Some(def) = item_tree
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
.parse_proc_macro_decl(&makro.name)
{
- def.name
+ (
+ def.name,
+ match def.kind {
+ ProcMacroKind::CustomDerive { helpers } => Some(helpers),
+ ProcMacroKind::FnLike | ProcMacroKind::Attr => None,
+ },
+ )
} else {
// eeeh...
stdx::never!("proc macro declaration is not a proc macro");
- makro.name.clone()
+ (makro.name.clone(), None)
};
- Arc::new(ProcMacroData { name })
+ Arc::new(ProcMacroData { name, helpers })
}
}
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 25fb302e87..45f631936d 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -48,11 +48,11 @@
//! the result
pub mod attr_resolution;
-mod collector;
+pub mod proc_macro;
pub mod diagnostics;
+mod collector;
mod mod_resolution;
mod path_resolution;
-mod proc_macro;
#[cfg(test)]
mod tests;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 86b5bd3c2c..d4925455d7 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2255,12 +2255,27 @@ impl Local {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DeriveHelper {
pub(crate) derive: MacroId,
+ pub(crate) idx: usize,
}
impl DeriveHelper {
pub fn derive(&self) -> Macro {
Macro { id: self.derive.into() }
}
+
+ pub fn name(&self, db: &dyn HirDatabase) -> Name {
+ match self.derive {
+ MacroId::Macro2Id(_) => None,
+ MacroId::MacroRulesId(_) => None,
+ MacroId::ProcMacroId(proc_macro) => db
+ .proc_macro_data(proc_macro)
+ .helpers
+ .as_ref()
+ .and_then(|it| it.get(self.idx))
+ .cloned(),
+ }
+ .unwrap_or_else(|| Name::missing())
+ }
}
// FIXME: Wrong name? This is could also be a registered attribute
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index d57a73ade3..1eb51b20c3 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -35,6 +35,7 @@ use hir_ty::{
method_resolution, Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution,
TyExt, TyKind, TyLoweringContext,
};
+use itertools::Itertools;
use smallvec::SmallVec;
use syntax::{
ast::{self, AstNode},
@@ -487,10 +488,16 @@ impl SourceAnalyzer {
{
// FIXME: Multiple derives can have the same helper
let name_ref = name_ref.as_name();
- if let Some(&(_, derive, _)) =
- helpers.iter().find(|(name, ..)| *name == name_ref)
+ for (macro_id, mut helpers) in
+ helpers.iter().group_by(|(_, macro_id, ..)| macro_id).into_iter()
{
- return Some(PathResolution::DeriveHelper(DeriveHelper { derive }));
+ if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref)
+ {
+ return Some(PathResolution::DeriveHelper(DeriveHelper {
+ derive: *macro_id,
+ idx,
+ }));
+ }
}
}
}
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index a9a78e6729..aeaca00ec6 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -121,7 +121,7 @@ impl Definition {
Definition::Label(it) => it.name(db),
Definition::BuiltinAttr(_) => return None, // FIXME
Definition::ToolModule(_) => return None, // FIXME
- Definition::DeriveHelper(_) => return None, // FIXME
+ Definition::DeriveHelper(it) => it.name(db),
};
Some(name)
}
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index eb4fc36438..bd038cdaa0 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -278,16 +278,16 @@ impl Definition {
}
}
hir::MacroKind::BuiltIn => SearchScope::crate_graph(db),
- // FIXME: We don't actually see derives in derive attributes as these do not
- // expand to something that references the derive macro in the output.
- // We could get around this by doing pseudo expansions for proc_macro_derive like we
- // do for the derive attribute
hir::MacroKind::Derive | hir::MacroKind::Attr | hir::MacroKind::ProcMacro => {
SearchScope::reverse_dependencies(db, module.krate())
}
};
}
+ if let Definition::DeriveHelper(_) = self {
+ return SearchScope::reverse_dependencies(db, module.krate());
+ }
+
let vis = self.visibility(db);
if let Some(Visibility::Public) = vis {
return SearchScope::reverse_dependencies(db, module.krate());
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index fcdb23fa18..6c50a4e6ad 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -370,8 +370,7 @@ pub(super) fn definition(
// FIXME: We should be able to show more info about these
Definition::BuiltinAttr(it) => return render_builtin_attr(db, it),
Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))),
- // FIXME: it.name(db)
- Definition::DeriveHelper(_it) => ("derive-helper".to_owned(), None),
+ Definition::DeriveHelper(it) => (format!("derive_helper {}", it.name(db)), None),
};
let docs = match config.documentation {
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index eef717c16f..d013d6f4b1 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -432,6 +432,13 @@ fn traverse(
// let the editor do its highlighting for these tokens instead
continue;
}
+ if highlight.tag == HlTag::UnresolvedReference
+ && matches!(attr_or_derive_item, Some(AttrOrDerive::Derive(_)) if inside_attribute)
+ {
+ // do not emit unresolved references in derive helpers if the token mapping maps to
+ // something unresolvable. FIXME: There should be a way to prevent that
+ continue;
+ }
if inside_attribute {
highlight |= HlMod::Attribute
}