Unnamed repository; edit this file 'description' to name the repository.
feat: Resolve builtin-attr and tools in ide layer
| -rw-r--r-- | crates/hir/src/lib.rs | 20 | ||||
| -rw-r--r-- | crates/hir/src/semantics.rs | 26 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 66 | ||||
| -rw-r--r-- | crates/hir_def/src/builtin_attr.rs | 104 | ||||
| -rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 8 | ||||
| -rw-r--r-- | crates/ide/src/doc_links.rs | 12 | ||||
| -rw-r--r-- | crates/ide/src/hover/render.rs | 2 | ||||
| -rw-r--r-- | crates/ide/src/hover/tests.rs | 1 | ||||
| -rw-r--r-- | crates/ide/src/navigation_target.rs | 2 | ||||
| -rw-r--r-- | crates/ide/src/static_index.rs | 1 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/highlight.rs | 2 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 2 | ||||
| -rw-r--r-- | crates/ide_db/src/defs.rs | 50 | ||||
| -rw-r--r-- | crates/ide_db/src/path_transform.rs | 4 | ||||
| -rw-r--r-- | crates/ide_db/src/rename.rs | 6 |
15 files changed, 208 insertions, 98 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e0dc921c9f..c0c2cc7818 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2024,6 +2024,26 @@ impl Local { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct BuiltinAttr(usize); + +impl BuiltinAttr { + pub(crate) fn by_name(name: &str) -> Option<Self> { + // TODO: def maps registered attrs? + hir_def::builtin_attr::find_builtin_attr_idx(name).map(Self) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Tool(usize); + +impl Tool { + pub(crate) fn by_name(name: &str) -> Option<Self> { + // TODO: def maps registered tools + hir_def::builtin_attr::TOOL_MODULES.iter().position(|&tool| tool == name).map(Self) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Label { pub(crate) parent: DefWithBodyId, pub(crate) label_id: LabelId, diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 27ba42ce1a..c48bd1b053 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -25,9 +25,9 @@ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, resolve_hir_path_as_macro, SourceAnalyzer}, - Access, AssocItem, Callable, ConstParam, Crate, Field, Function, HasSource, HirFileId, Impl, - InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, - Type, TypeAlias, TypeParam, VariantDef, + Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasSource, + HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, + ScopeDef, Tool, Trait, Type, TypeAlias, TypeParam, VariantDef, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -43,6 +43,8 @@ pub enum PathResolution { SelfType(Impl), Macro(MacroDef), AssocItem(AssocItem), + BuiltinAttr(BuiltinAttr), + Tool(Tool), } impl PathResolution { @@ -63,9 +65,11 @@ impl PathResolution { PathResolution::Def(ModuleDef::TypeAlias(alias)) => { Some(TypeNs::TypeAliasId((*alias).into())) } - PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => { - None - } + PathResolution::BuiltinAttr(_) + | PathResolution::Tool(_) + | PathResolution::Local(_) + | PathResolution::Macro(_) + | PathResolution::ConstParam(_) => None, PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None, @@ -334,10 +338,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_path(path) } - pub fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> { - self.imp.resolve_path_as_macro(path) - } - pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { self.imp.resolve_extern_crate(extern_crate) } @@ -860,12 +860,6 @@ impl<'db> SemanticsImpl<'db> { self.analyze(path.syntax()).resolve_path(self.db, path) } - // FIXME: This shouldn't exist, but is currently required to always resolve attribute paths in - // the IDE layer due to namespace collisions - fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> { - self.analyze(path.syntax()).resolve_path_as_macro(self.db, path) - } - fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { let krate = self.scope(extern_crate.syntax()).krate()?; krate.dependencies(self.db).into_iter().find_map(|dep| { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 23fcd02b57..8f6c3d995f 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -29,8 +29,9 @@ use syntax::{ }; use crate::{ - db::HirDatabase, semantics::PathResolution, Adt, BuiltinType, Const, Field, Function, Local, - MacroDef, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Variant, + db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field, + Function, Local, MacroDef, ModuleDef, Static, Struct, Tool, Trait, Type, TypeAlias, TypeParam, + Variant, }; use base_db::CrateId; @@ -246,18 +247,6 @@ impl SourceAnalyzer { } } - pub(crate) fn resolve_path_as_macro( - &self, - db: &dyn HirDatabase, - path: &ast::Path, - ) -> Option<MacroDef> { - // This must be a normal source file rather than macro file. - let hygiene = Hygiene::new(db.upcast(), self.file_id); - let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene); - let hir_path = Path::from_src(path.clone(), &ctx)?; - resolve_hir_path_as_macro(db, &self.resolver, &hir_path) - } - pub(crate) fn resolve_path( &self, db: &dyn HirDatabase, @@ -318,29 +307,60 @@ impl SourceAnalyzer { let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene); let hir_path = Path::from_src(path.clone(), &ctx)?; - // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are + // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are // trying to resolve foo::bar. - if let Some(outer_path) = parent().and_then(ast::Path::cast) { - if let Some(qualifier) = outer_path.qualifier() { - if path == &qualifier { + if let Some(use_tree) = parent().and_then(ast::UseTree::cast) { + if let Some(qualifier) = use_tree.path() { + if path == &qualifier && use_tree.coloncolon_token().is_some() { return resolve_hir_path_qualifier(db, &self.resolver, &hir_path); } } } - // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are + + let is_path_of_attr = path + .top_path() + .syntax() + .ancestors() + .nth(2) // Path -> Meta -> Attr + .map_or(false, |it| ast::Attr::can_cast(it.kind())); + + // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are // trying to resolve foo::bar. - if let Some(use_tree) = parent().and_then(ast::UseTree::cast) { - if let Some(qualifier) = use_tree.path() { - if path == &qualifier && use_tree.coloncolon_token().is_some() { + if let Some(outer_path) = path.parent_path() { + if let Some(qualifier) = outer_path.qualifier() { + if path == &qualifier { return resolve_hir_path_qualifier(db, &self.resolver, &hir_path); } } + } else if is_path_of_attr { + let res = resolve_hir_path_as_macro(db, &self.resolver, &hir_path); + return match res { + Some(_) => res.map(PathResolution::Macro), + None => path.as_single_name_ref().and_then(|name_ref| { + if let Some(builtin) = BuiltinAttr::by_name(&name_ref.text()) { + Some(PathResolution::BuiltinAttr(builtin)) + } else if let Some(tool) = Tool::by_name(&name_ref.text()) { + Some(PathResolution::Tool(tool)) + } else { + None + } + }), + }; } - if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) { + let res = if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) { resolve_hir_path_qualifier(db, &self.resolver, &hir_path) } else { resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns) + }; + match res { + Some(_) => res, + None if is_path_of_attr => path + .first_segment() + .and_then(|seg| seg.name_ref()) + .and_then(|name_ref| Tool::by_name(&name_ref.text())) + .map(PathResolution::Tool), + None => None, } } diff --git a/crates/hir_def/src/builtin_attr.rs b/crates/hir_def/src/builtin_attr.rs index 6cd185ceeb..cd3a8a8605 100644 --- a/crates/hir_def/src/builtin_attr.rs +++ b/crates/hir_def/src/builtin_attr.rs @@ -2,35 +2,98 @@ //! //! The actual definitions were copied from rustc's `compiler/rustc_feature/src/builtin_attrs.rs`. //! -//! It was last synchronized with upstream commit 835150e70288535bc57bb624792229b9dc94991d. +//! It was last synchronized with upstream commit ae90dcf0207c57c3034f00b07048d63f8b2363c8. //! //! The macros were adjusted to only expand to the attribute name, since that is all we need to do //! name resolution, and `BUILTIN_ATTRIBUTES` is almost entirely unchanged from the original, to //! ease updating. +use once_cell::sync::OnceCell; +use rustc_hash::FxHashMap; + /// Ignored attribute namespaces used by tools. pub const TOOL_MODULES: &[&str] = &["rustfmt", "clippy"]; -type BuiltinAttribute = &'static str; +pub struct BuiltinAttribute { + pub name: &'static str, + pub template: AttributeTemplate, +} + +/// A template that the attribute input must match. +/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. +pub struct AttributeTemplate { + pub word: bool, + pub list: Option<&'static str>, + pub name_value_str: Option<&'static str>, +} + +static BUILTIN_LOOKUP_TABLE: OnceCell<FxHashMap<&'static str, usize>> = OnceCell::new(); + +pub fn find_builtin_attr_idx(name: &str) -> Option<usize> { + BUILTIN_LOOKUP_TABLE + .get_or_init(|| { + INERT_ATTRIBUTES.iter().map(|attr| attr.name).enumerate().map(|(a, b)| (b, a)).collect() + }) + .get(name) + .copied() +} + +// impl AttributeTemplate { +// const DEFAULT: AttributeTemplate = +// AttributeTemplate { word: false, list: None, name_value_str: None }; +// } + +/// A convenience macro for constructing attribute templates. +/// E.g., `template!(Word, List: "description")` means that the attribute +/// supports forms `#[attr]` and `#[attr(description)]`. +macro_rules! template { + (Word) => { template!(@ true, None, None) }; + (List: $descr: expr) => { template!(@ false, Some($descr), None) }; + (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; + (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; + (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; + (List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ false, Some($descr1), Some($descr2)) + }; + (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { + template!(@ true, Some($descr1), Some($descr2)) + }; + (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { + word: $word, list: $list, name_value_str: $name_value_str + } }; +} macro_rules! ungated { ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { - stringify!($attr) + BuiltinAttribute { name: stringify!($attr), template: $tpl } }; } macro_rules! gated { - ($attr:ident $($rest:tt)*) => { - stringify!($attr) + ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { + BuiltinAttribute { name: stringify!($attr), template: $tpl } + }; + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + BuiltinAttribute { name: stringify!($attr), template: $tpl } }; } macro_rules! rustc_attr { - (TEST, $attr:ident $($rest:tt)*) => { - stringify!($attr) + (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { + rustc_attr!( + $attr, + $typ, + $tpl, + concat!( + "the `#[", + stringify!($attr), + "]` attribute is just used for rustc unit tests \ + and will never be stable", + ), + ) }; - ($attr:ident $($rest:tt)*) => { - stringify!($attr) + ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + BuiltinAttribute { name: stringify!($attr), template: $tpl } }; } @@ -158,8 +221,8 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ // Plugins: // XXX Modified for use in rust-analyzer - gated!(plugin_registrar), - gated!(plugin), + gated!(plugin_registrar, Normal, template!(Word), experimental!()), + gated!(plugin, CrateLevel, template!(Word), experimental!()), // Testing: gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), @@ -195,6 +258,12 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)), + // RFC 2632 + gated!( + default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl, + "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \ + as `const`, which may be removed or renamed in the future." + ), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: @@ -259,10 +328,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ gated!(panic_runtime, AssumedUsed, template!(Word), experimental!(panic_runtime)), gated!(needs_panic_runtime, AssumedUsed, template!(Word), experimental!(needs_panic_runtime)), gated!( - unwind, AssumedUsed, template!(List: "allowed|aborts"), unwind_attributes, - experimental!(unwind), - ), - gated!( compiler_builtins, AssumedUsed, template!(Word), "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", @@ -287,7 +352,11 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Macro related: // ========================================================================== - rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), + rustc_attr!( + rustc_builtin_macro, AssumedUsed, + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + IMPL_DETAIL, + ), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, AssumedUsed, @@ -344,7 +413,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ lang, Normal, template!(NameValueStr: "name"), lang_items, "language items are subject to change", ), - gated!(rustc_diagnostic_item), // XXX modified in rust-analyzer + gated!(rustc_diagnostic_item, Normal, template!(NameValueStr: "name"), experimental!()), // XXX Modified for use in rust-analyzer gated!( // Used in resolve: prelude_import, AssumedUsed, template!(Word), @@ -428,6 +497,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)), + rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), gated!( omit_gdb_pretty_printer_section, AssumedUsed, template!(Word), diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d7a35caf29..ad4a4aa752 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -1798,14 +1798,18 @@ impl ModCollector<'_, '_> { let registered = self.def_collector.registered_tools.iter().map(SmolStr::as_str); let is_tool = builtin_attr::TOOL_MODULES.iter().copied().chain(registered).any(pred); + // FIXME: tool modules can be shadowed by actual modules if is_tool { return true; } if segments.len() == 1 { let registered = self.def_collector.registered_attrs.iter().map(SmolStr::as_str); - let is_inert = - builtin_attr::INERT_ATTRIBUTES.iter().copied().chain(registered).any(pred); + let is_inert = builtin_attr::INERT_ATTRIBUTES + .iter() + .map(|it| it.name) + .chain(registered) + .any(pred); return is_inert; } } diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index d5dca95fba..edcea7aace 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -181,7 +181,9 @@ pub(crate) fn resolve_doc_path_for_def( Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns), Definition::Macro(it) => it.resolve_doc_path(db, link, ns), Definition::Field(it) => it.resolve_doc_path(db, link, ns), - Definition::BuiltinType(_) + Definition::BuiltinAttr(_) + | Definition::Tool(_) + | Definition::BuiltinType(_) | Definition::SelfType(_) | Definition::Local(_) | Definition::GenericParam(_) @@ -492,9 +494,11 @@ fn filename_and_frag_for_def( // FIXME fragment numbering return Some((adt, file, Some(String::from("impl")))); } - Definition::Local(_) => return None, - Definition::GenericParam(_) => return None, - Definition::Label(_) => return None, + Definition::Local(_) + | Definition::GenericParam(_) + | Definition::Label(_) + | Definition::BuiltinAttr(_) + | Definition::Tool(_) => return None, }; Some((def, res, None)) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index dd4a961d31..e72ed8c2b2 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -369,6 +369,8 @@ pub(super) fn definition( } Definition::GenericParam(it) => label_and_docs(db, it), Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db))), + Definition::BuiltinAttr(_) => return None, // FIXME + Definition::Tool(_) => return None, // FIXME }; markup(docs.filter(|_| config.documentation.is_some()).map(Into::into), label, mod_path) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 5718b9097c..4187e9ca36 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -3678,7 +3678,6 @@ fn hover_clippy_lint() { #[test] fn hover_attr_path_qualifier() { - cov_mark::check!(name_ref_classify_attr_path_qualifier); check( r#" //- /foo.rs crate:foo diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 7deb6cae38..aa865ddc21 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -214,6 +214,8 @@ impl TryToNav for Definition { Definition::Trait(it) => it.try_to_nav(db), Definition::TypeAlias(it) => it.try_to_nav(db), Definition::BuiltinType(_) => None, + Definition::Tool(_) => None, + Definition::BuiltinAttr(_) => None, } } } diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index cf98bc32fa..77d202cc39 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -299,6 +299,7 @@ pub func() { r#" //- minicore:derive #[rustc_builtin_macro] +//^^^^^^^^^^^^^^^^^^^ pub macro Copy {} //^^^^ #[derive(Copy)] diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index b8177b4ab6..52e729ee68 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -542,6 +542,8 @@ fn highlight_def( h } Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), + Definition::BuiltinAttr(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), // FIXME + Definition::Tool(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), // FIXME }; let famous_defs = FamousDefs(sema, krate); diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 686fd5baa7..d4dba50834 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -263,6 +263,8 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, }, Definition::Label(_) => SymbolKind::Label, + Definition::BuiltinAttr(_) => SymbolKind::Label, // FIXME + Definition::Tool(_) => SymbolKind::Label, // FIXME }; HlTag::Symbol(symbol) } diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 1d7f4392dd..26cdaa1ac1 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -7,9 +7,9 @@ use arrayvec::ArrayVec; use hir::{ - Adt, AsAssocItem, AssocItem, BuiltinType, Const, Field, Function, GenericParam, HasVisibility, - Impl, ItemInNs, Label, Local, MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, - Static, Trait, TypeAlias, Variant, Visibility, + Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Field, Function, GenericParam, + HasVisibility, Impl, ItemInNs, Label, Local, MacroDef, Module, ModuleDef, Name, PathResolution, + Semantics, Static, Tool, Trait, TypeAlias, Variant, Visibility, }; use stdx::impl_from; use syntax::{ @@ -37,6 +37,8 @@ pub enum Definition { Local(Local), GenericParam(GenericParam), Label(Label), + BuiltinAttr(BuiltinAttr), + Tool(Tool), } impl Definition { @@ -48,10 +50,9 @@ impl Definition { Some(parent) => parent, None => return Default::default(), }; + // resolve derives if possible if let Some(ident) = ast::Ident::cast(token.clone()) { - let attr = parent - .ancestors() - .find_map(ast::TokenTree::cast) + let attr = ast::TokenTree::cast(parent.clone()) .and_then(|tt| tt.parent_meta()) .and_then(|meta| meta.parent_attr()); if let Some(attr) = attr { @@ -128,7 +129,9 @@ impl Definition { Definition::Local(it) => it.module(db), Definition::GenericParam(it) => it.module(db), Definition::Label(it) => it.module(db), - Definition::BuiltinType(_) => return None, + Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::Tool(_) => { + return None + } }; Some(module) } @@ -146,7 +149,9 @@ impl Definition { Definition::Variant(it) => it.visibility(db), Definition::BuiltinType(_) => Visibility::Public, Definition::Macro(_) => return None, - Definition::SelfType(_) + Definition::BuiltinAttr(_) + | Definition::Tool(_) + | Definition::SelfType(_) | Definition::Local(_) | Definition::GenericParam(_) | Definition::Label(_) => return None, @@ -171,6 +176,8 @@ impl Definition { Definition::Local(it) => it.name(db)?, Definition::GenericParam(it) => it.name(db), Definition::Label(it) => it.name(db), + Definition::BuiltinAttr(_) => return None, // FIXME + Definition::Tool(_) => return None, // FIXME }; Some(name) } @@ -450,30 +457,7 @@ impl NameRefClass { } } } - let top_path = path.top_path(); - let is_attribute_path = top_path - .syntax() - .ancestors() - .find_map(ast::Attr::cast) - .map(|attr| attr.path().as_ref() == Some(&top_path)); - return match is_attribute_path { - Some(true) if path == top_path => sema - .resolve_path_as_macro(&path) - .filter(|mac| mac.kind() == hir::MacroKind::Attr) - .map(Definition::Macro) - .map(NameRefClass::Definition), - // in case of the path being a qualifier, don't resolve to anything but a module - Some(true) => match sema.resolve_path(&path)? { - PathResolution::Def(ModuleDef::Module(module)) => { - cov_mark::hit!(name_ref_classify_attr_path_qualifier); - Some(NameRefClass::Definition(Definition::Module(module))) - } - _ => None, - }, - // inside attribute, but our path isn't part of the attribute's path(might be in its expression only) - Some(false) => None, - None => sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition), - }; + return sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition); } let extern_crate = ast::ExternCrate::cast(parent)?; @@ -566,6 +550,8 @@ impl From<PathResolution> for Definition { PathResolution::Macro(def) => Definition::Macro(def), PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), PathResolution::ConstParam(par) => Definition::GenericParam(par.into()), + PathResolution::BuiltinAttr(attr) => Definition::BuiltinAttr(attr), + PathResolution::Tool(tool) => Definition::Tool(tool), } } } diff --git a/crates/ide_db/src/path_transform.rs b/crates/ide_db/src/path_transform.rs index b8b1307a3c..a4db8b3848 100644 --- a/crates/ide_db/src/path_transform.rs +++ b/crates/ide_db/src/path_transform.rs @@ -164,7 +164,9 @@ impl<'a> Ctx<'a> { | hir::PathResolution::ConstParam(_) | hir::PathResolution::SelfType(_) | hir::PathResolution::Macro(_) - | hir::PathResolution::AssocItem(_) => (), + | hir::PathResolution::AssocItem(_) + | hir::PathResolution::BuiltinAttr(_) + | hir::PathResolution::Tool(_) => (), } Some(()) } diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs index 678153c6e1..35bd4d02a6 100644 --- a/crates/ide_db/src/rename.rs +++ b/crates/ide_db/src/rename.rs @@ -115,8 +115,6 @@ impl Definition { Definition::Static(it) => name_range(it, sema), Definition::Trait(it) => name_range(it, sema), Definition::TypeAlias(it) => name_range(it, sema), - Definition::BuiltinType(_) => return None, - Definition::SelfType(_) => return None, Definition::Local(local) => { let src = local.source(sema.db); let name = match &src.value { @@ -146,6 +144,10 @@ impl Definition { let lifetime = src.value.lifetime()?; src.with_value(lifetime.syntax()).original_file_range_opt(sema.db) } + Definition::BuiltinType(_) => return None, + Definition::SelfType(_) => return None, + Definition::BuiltinAttr(_) => return None, + Definition::Tool(_) => return None, }; return res; |