feat: Resolve builtin-attr and tools in ide layer

This commit is contained in:
Lukas Wirth 2021-12-03 16:32:14 +01:00
parent 4691a0647b
commit e58af219a4
15 changed files with 209 additions and 99 deletions

View file

@ -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:
@ -258,10 +327,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 \
@ -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),