Skip to content

Commit

Permalink
Allow name querying for derive helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Jul 26, 2022
1 parent aa1491e commit ddad284
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 18 deletions.
19 changes: 13 additions & 6 deletions crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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 })
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/hir-def/src/nameres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 15 additions & 0 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 10 additions & 3 deletions crates/hir/src/source_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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,
}));
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ide-db/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions crates/ide-db/src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
3 changes: 1 addition & 2 deletions crates/ide/src/hover/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions crates/ide/src/syntax_highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit ddad284

Please sign in to comment.