diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 9a1a893650c..ee423573d5c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2064,37 +2064,75 @@ impl Local { } } +// FIXME: Wrong name? This is could also be a registered attribute #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct BuiltinAttr(usize); +pub struct BuiltinAttr { + krate: Option, + idx: usize, +} impl BuiltinAttr { - pub(crate) fn by_name(name: &str) -> Option { - // FIXME: def maps registered attrs? - hir_def::builtin_attr::find_builtin_attr_idx(name).map(Self) + // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs? + pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option { + if let builtin @ Some(_) = Self::builtin(name) { + return builtin; + } + let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?; + Some(BuiltinAttr { krate: Some(krate.id), idx }) } - pub fn name(&self, _: &dyn HirDatabase) -> &str { + pub(crate) fn builtin(name: &str) -> Option { + hir_def::builtin_attr::INERT_ATTRIBUTES + .iter() + .position(|tool| tool.name == name) + .map(|idx| BuiltinAttr { krate: None, idx }) + } + + pub fn name(&self, db: &dyn HirDatabase) -> SmolStr { // FIXME: Return a `Name` here - hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].name + match self.krate { + Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(), + None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name), + } } - pub fn template(&self, _: &dyn HirDatabase) -> AttributeTemplate { - hir_def::builtin_attr::INERT_ATTRIBUTES[self.0].template + pub fn template(&self, _: &dyn HirDatabase) -> Option { + match self.krate { + Some(_) => None, + None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template), + } } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct ToolModule(usize); +pub struct ToolModule { + krate: Option, + idx: usize, +} impl ToolModule { - pub(crate) fn by_name(name: &str) -> Option { - // FIXME: def maps registered tools - hir_def::builtin_attr::TOOL_MODULES.iter().position(|&tool| tool == name).map(Self) + // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs? + pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option { + if let builtin @ Some(_) = Self::builtin(name) { + return builtin; + } + let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?; + Some(ToolModule { krate: Some(krate.id), idx }) } - pub fn name(&self, _: &dyn HirDatabase) -> &str { + pub(crate) fn builtin(name: &str) -> Option { + hir_def::builtin_attr::TOOL_MODULES + .iter() + .position(|&tool| tool == name) + .map(|idx| ToolModule { krate: None, idx }) + } + + pub fn name(&self, db: &dyn HirDatabase) -> SmolStr { // FIXME: Return a `Name` here - hir_def::builtin_attr::TOOL_MODULES[self.0] + match self.krate { + Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(), + None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]), + } } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 233c814809a..ef3dfa1f335 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -346,7 +346,11 @@ impl SourceAnalyzer { return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path) { None if is_path_of_attr => { path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| { - ToolModule::by_name(&name_ref.text()).map(PathResolution::ToolModule) + match self.resolver.krate() { + Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()), + None => ToolModule::builtin(&name_ref.text()), + } + .map(PathResolution::ToolModule) }) } res => res, @@ -356,8 +360,10 @@ impl SourceAnalyzer { // in this case we have to check for inert/builtin attributes and tools and prioritize // resolution of attributes over other namespaces let name_ref = path.as_single_name_ref(); - let builtin = - name_ref.as_ref().map(ast::NameRef::text).as_deref().and_then(BuiltinAttr::by_name); + let builtin = name_ref.as_ref().and_then(|name_ref| match self.resolver.krate() { + Some(krate) => BuiltinAttr::by_name(db, krate.into(), &name_ref.text()), + None => BuiltinAttr::builtin(&name_ref.text()), + }); if let builtin @ Some(_) = builtin { return builtin.map(PathResolution::BuiltinAttr); } @@ -366,7 +372,11 @@ impl SourceAnalyzer { // this labels any path that starts with a tool module as the tool itself, this is technically wrong // but there is no benefit in differentiating these two cases for the time being _ => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| { - ToolModule::by_name(&name_ref.text()).map(PathResolution::ToolModule) + match self.resolver.krate() { + Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()), + None => ToolModule::builtin(&name_ref.text()), + } + .map(PathResolution::ToolModule) }), }; } diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index f793f0e0023..64929c02b40 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -296,6 +296,12 @@ impl DefMap { pub fn exported_proc_macros(&self) -> impl Iterator + '_ { self.exported_proc_macros.iter().map(|(id, def)| (*id, def.name.clone())) } + pub fn registered_tools(&self) -> &[SmolStr] { + &self.registered_tools + } + pub fn registered_attrs(&self) -> &[SmolStr] { + &self.registered_attrs + } pub fn root(&self) -> LocalModuleId { self.root } diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 9ae122d8a41..d29833a65b3 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -393,7 +393,10 @@ fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option template, + None => return Some(Markup::fenced_block(&attr.name(db))), + }; let mut docs = "Valid forms are:".to_owned(); if word { format_to!(docs, "\n - #\\[{}]", name);