about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 43094114193..35c8708955a 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 25fb302e875..45f631936d2 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 86b5bd3c2c8..d4925455d7b 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 d57a73ade3a..1eb51b20c35 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 a9a78e67290..aeaca00ec65 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 eb4fc364381..bd038cdaa06 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 fcdb23fa18a..6c50a4e6adc 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 eef717c16f2..d013d6f4b19 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
             }