Allow name querying for derive helpers

This commit is contained in:
Lukas Wirth 2022-07-24 14:32:39 +02:00
parent aa1491ecde
commit ddad2847ab
8 changed files with 53 additions and 18 deletions

View File

@ -12,7 +12,7 @@
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 @@ pub(crate) fn macro_rules_data_query(
#[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 @@ pub(crate) fn proc_macro_data_query(
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 })
}
}

View File

@ -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;

View File

@ -2255,12 +2255,27 @@ pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::S
#[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

View File

@ -35,6 +35,7 @@
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 @@ pub(crate) fn resolve_path(
{
// 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,
}));
}
}
}
}

View File

@ -121,7 +121,7 @@ pub fn name(&self, db: &RootDatabase) -> Option<Name> {
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)
}

View File

@ -278,16 +278,16 @@ fn search_scope(&self, db: &RootDatabase) -> SearchScope {
}
}
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());

View File

@ -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 {

View File

@ -432,6 +432,13 @@ fn item(&self) -> &ast::Item {
// 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
}