mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Implement dummy expansions for builtin attributes
This commit is contained in:
parent
5f592f4f58
commit
ae8d74ab2c
10 changed files with 176 additions and 11 deletions
|
@ -1344,6 +1344,7 @@ impl MacroDef {
|
||||||
MacroDefKind::Declarative(_) => MacroKind::Declarative,
|
MacroDefKind::Declarative(_) => MacroKind::Declarative,
|
||||||
MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
|
MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
|
||||||
MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
|
MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
|
||||||
|
MacroDefKind::BuiltInAttr(_, _) => MacroKind::Attr,
|
||||||
MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
|
MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
|
||||||
MacroKind::Derive
|
MacroKind::Derive
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
ast_id_map::FileAstId,
|
ast_id_map::FileAstId,
|
||||||
|
builtin_attr::find_builtin_attr,
|
||||||
builtin_derive::find_builtin_derive,
|
builtin_derive::find_builtin_derive,
|
||||||
builtin_macro::find_builtin_macro,
|
builtin_macro::find_builtin_macro,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
|
@ -1836,7 +1837,8 @@ impl ModCollector<'_, '_> {
|
||||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
||||||
if attrs.by_key("rustc_builtin_macro").exists() {
|
if attrs.by_key("rustc_builtin_macro").exists() {
|
||||||
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
|
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
|
||||||
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
|
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
|
||||||
|
.or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
|
||||||
|
|
||||||
match macro_id {
|
match macro_id {
|
||||||
Some(macro_id) => {
|
Some(macro_id) => {
|
||||||
|
|
115
crates/hir_expand/src/builtin_attr.rs
Normal file
115
crates/hir_expand/src/builtin_attr.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
//! Builtin derives.
|
||||||
|
|
||||||
|
use syntax::ast;
|
||||||
|
|
||||||
|
use crate::{db::AstDatabase, name, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind};
|
||||||
|
|
||||||
|
macro_rules! register_builtin {
|
||||||
|
( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum BuiltinAttrExpander {
|
||||||
|
$($variant),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinAttrExpander {
|
||||||
|
pub fn expand(
|
||||||
|
&self,
|
||||||
|
db: &dyn AstDatabase,
|
||||||
|
id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
let expander = match *self {
|
||||||
|
$( BuiltinAttrExpander::$variant => $expand, )*
|
||||||
|
};
|
||||||
|
expander(db, id, tt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||||
|
match name {
|
||||||
|
$( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
register_builtin! {
|
||||||
|
(bench, Bench) => bench_expand,
|
||||||
|
(cfg_accessible, CfgAccessible) => cfg_accessible_expand,
|
||||||
|
(cfg_eval, CfgEval) => cfg_eval_expand,
|
||||||
|
(derive, Derive) => derive_expand,
|
||||||
|
(global_allocator, GlobalAllocator) => global_allocator_expand,
|
||||||
|
(test, Test) => test_expand,
|
||||||
|
(test_case, TestCase) => test_case_expand
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_builtin_attr(
|
||||||
|
ident: &name::Name,
|
||||||
|
krate: CrateId,
|
||||||
|
ast_id: AstId<ast::Macro>,
|
||||||
|
) -> Option<MacroDefId> {
|
||||||
|
let expander = BuiltinAttrExpander::find_by_name(ident)?;
|
||||||
|
Some(MacroDefId {
|
||||||
|
krate,
|
||||||
|
kind: MacroDefKind::BuiltInAttr(expander, ast_id),
|
||||||
|
local_inner: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cfg_accessible_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cfg_eval_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_allocator_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_case_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_id: MacroCallId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||||
|
Ok(tt.clone())
|
||||||
|
}
|
|
@ -12,9 +12,9 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander,
|
ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinAttrExpander,
|
||||||
BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc,
|
BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId,
|
||||||
MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
|
MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Total limit on the number of tokens produced by any macro invocation.
|
/// Total limit on the number of tokens produced by any macro invocation.
|
||||||
|
@ -31,6 +31,8 @@ pub enum TokenExpander {
|
||||||
MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
|
MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
|
||||||
/// Stuff like `line!` and `file!`.
|
/// Stuff like `line!` and `file!`.
|
||||||
Builtin(BuiltinFnLikeExpander),
|
Builtin(BuiltinFnLikeExpander),
|
||||||
|
/// `global_allocator` and such.
|
||||||
|
BuiltinAttr(BuiltinAttrExpander),
|
||||||
/// `derive(Copy)` and such.
|
/// `derive(Copy)` and such.
|
||||||
BuiltinDerive(BuiltinDeriveExpander),
|
BuiltinDerive(BuiltinDeriveExpander),
|
||||||
/// The thing we love the most here in rust-analyzer -- procedural macros.
|
/// The thing we love the most here in rust-analyzer -- procedural macros.
|
||||||
|
@ -49,6 +51,7 @@ impl TokenExpander {
|
||||||
TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
|
TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
|
||||||
TokenExpander::Builtin(it) => it.expand(db, id, tt),
|
TokenExpander::Builtin(it) => it.expand(db, id, tt),
|
||||||
// FIXME switch these to ExpandResult as well
|
// FIXME switch these to ExpandResult as well
|
||||||
|
TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt).into(),
|
||||||
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
|
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
|
||||||
TokenExpander::ProcMacro(_) => {
|
TokenExpander::ProcMacro(_) => {
|
||||||
// We store the result in salsa db to prevent non-deterministic behavior in
|
// We store the result in salsa db to prevent non-deterministic behavior in
|
||||||
|
@ -64,6 +67,7 @@ impl TokenExpander {
|
||||||
TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
|
TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
|
||||||
TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
|
TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
|
||||||
TokenExpander::Builtin(..)
|
TokenExpander::Builtin(..)
|
||||||
|
| TokenExpander::BuiltinAttr(..)
|
||||||
| TokenExpander::BuiltinDerive(..)
|
| TokenExpander::BuiltinDerive(..)
|
||||||
| TokenExpander::ProcMacro(..) => id,
|
| TokenExpander::ProcMacro(..) => id,
|
||||||
}
|
}
|
||||||
|
@ -74,6 +78,7 @@ impl TokenExpander {
|
||||||
TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
|
TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
|
||||||
TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
|
TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
|
||||||
TokenExpander::Builtin(..)
|
TokenExpander::Builtin(..)
|
||||||
|
| TokenExpander::BuiltinAttr(..)
|
||||||
| TokenExpander::BuiltinDerive(..)
|
| TokenExpander::BuiltinDerive(..)
|
||||||
| TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
|
| TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
|
||||||
}
|
}
|
||||||
|
@ -299,6 +304,9 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
|
MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
|
||||||
|
MacroDefKind::BuiltInAttr(expander, _) => {
|
||||||
|
Some(Arc::new(TokenExpander::BuiltinAttr(expander)))
|
||||||
|
}
|
||||||
MacroDefKind::BuiltInDerive(expander, _) => {
|
MacroDefKind::BuiltInDerive(expander, _) => {
|
||||||
Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
|
Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,6 +224,7 @@ fn eager_macro_recur(
|
||||||
}
|
}
|
||||||
MacroDefKind::Declarative(_)
|
MacroDefKind::Declarative(_)
|
||||||
| MacroDefKind::BuiltIn(..)
|
| MacroDefKind::BuiltIn(..)
|
||||||
|
| MacroDefKind::BuiltInAttr(..)
|
||||||
| MacroDefKind::BuiltInDerive(..)
|
| MacroDefKind::BuiltInDerive(..)
|
||||||
| MacroDefKind::ProcMacro(..) => {
|
| MacroDefKind::ProcMacro(..) => {
|
||||||
let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);
|
let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);
|
||||||
|
|
|
@ -192,6 +192,7 @@ impl HygieneFrame {
|
||||||
(info, Some(loc.def.krate), loc.def.local_inner)
|
(info, Some(loc.def.krate), loc.def.local_inner)
|
||||||
}
|
}
|
||||||
MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
|
MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
|
||||||
|
MacroDefKind::BuiltInAttr(..) => (info, None, false),
|
||||||
MacroDefKind::BuiltInDerive(..) => (info, None, false),
|
MacroDefKind::BuiltInDerive(..) => (info, None, false),
|
||||||
MacroDefKind::BuiltInEager(..) => (info, None, false),
|
MacroDefKind::BuiltInEager(..) => (info, None, false),
|
||||||
MacroDefKind::ProcMacro(..) => (info, None, false),
|
MacroDefKind::ProcMacro(..) => (info, None, false),
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub mod db;
|
||||||
pub mod ast_id_map;
|
pub mod ast_id_map;
|
||||||
pub mod name;
|
pub mod name;
|
||||||
pub mod hygiene;
|
pub mod hygiene;
|
||||||
|
pub mod builtin_attr;
|
||||||
pub mod builtin_derive;
|
pub mod builtin_derive;
|
||||||
pub mod builtin_macro;
|
pub mod builtin_macro;
|
||||||
pub mod proc_macro;
|
pub mod proc_macro;
|
||||||
|
@ -32,6 +33,7 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast_id_map::FileAstId;
|
use crate::ast_id_map::FileAstId;
|
||||||
|
use crate::builtin_attr::BuiltinAttrExpander;
|
||||||
use crate::builtin_derive::BuiltinDeriveExpander;
|
use crate::builtin_derive::BuiltinDeriveExpander;
|
||||||
use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
|
use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
|
||||||
use crate::proc_macro::ProcMacroExpander;
|
use crate::proc_macro::ProcMacroExpander;
|
||||||
|
@ -206,6 +208,7 @@ impl MacroDefId {
|
||||||
let id = match &self.kind {
|
let id = match &self.kind {
|
||||||
MacroDefKind::Declarative(id) => id,
|
MacroDefKind::Declarative(id) => id,
|
||||||
MacroDefKind::BuiltIn(_, id) => id,
|
MacroDefKind::BuiltIn(_, id) => id,
|
||||||
|
MacroDefKind::BuiltInAttr(_, id) => id,
|
||||||
MacroDefKind::BuiltInDerive(_, id) => id,
|
MacroDefKind::BuiltInDerive(_, id) => id,
|
||||||
MacroDefKind::BuiltInEager(_, id) => id,
|
MacroDefKind::BuiltInEager(_, id) => id,
|
||||||
MacroDefKind::ProcMacro(.., id) => return Either::Right(*id),
|
MacroDefKind::ProcMacro(.., id) => return Either::Right(*id),
|
||||||
|
@ -223,6 +226,7 @@ pub enum MacroDefKind {
|
||||||
Declarative(AstId<ast::Macro>),
|
Declarative(AstId<ast::Macro>),
|
||||||
BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
|
BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
|
||||||
// FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
|
// FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
|
||||||
|
BuiltInAttr(BuiltinAttrExpander, AstId<ast::Macro>),
|
||||||
BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
|
BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
|
||||||
BuiltInEager(EagerExpander, AstId<ast::Macro>),
|
BuiltInEager(EagerExpander, AstId<ast::Macro>),
|
||||||
ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>),
|
ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>),
|
||||||
|
|
|
@ -160,7 +160,6 @@ pub mod known {
|
||||||
str,
|
str,
|
||||||
// Special names
|
// Special names
|
||||||
macro_rules,
|
macro_rules,
|
||||||
derive,
|
|
||||||
doc,
|
doc,
|
||||||
cfg,
|
cfg,
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
|
@ -240,6 +239,14 @@ pub mod known {
|
||||||
PartialOrd,
|
PartialOrd,
|
||||||
Eq,
|
Eq,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
|
// Builtin attributes
|
||||||
|
bench,
|
||||||
|
cfg_accessible,
|
||||||
|
cfg_eval,
|
||||||
|
derive,
|
||||||
|
global_allocator,
|
||||||
|
test,
|
||||||
|
test_case,
|
||||||
// Safe intrinsics
|
// Safe intrinsics
|
||||||
abort,
|
abort,
|
||||||
size_of,
|
size_of,
|
||||||
|
|
|
@ -656,6 +656,32 @@ fn main() { let _ = crate::$0 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn does_not_complete_non_fn_macros() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
mod m {
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
pub macro Clone {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {m::$0}
|
||||||
|
"#,
|
||||||
|
expect![[r#""#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
mod m {
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
pub macro bench {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {m::$0}
|
||||||
|
"#,
|
||||||
|
expect![[r#""#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn completes_in_assoc_item_list() {
|
fn completes_in_assoc_item_list() {
|
||||||
check(
|
check(
|
||||||
|
|
|
@ -481,14 +481,14 @@ impl S {
|
||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
mod m {
|
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Clone {}
|
pub macro bench {}
|
||||||
}
|
|
||||||
|
|
||||||
fn f() {m::$0}
|
fn f() {$0}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#""#]],
|
expect![[r#"
|
||||||
|
fn f() fn()
|
||||||
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue