mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 05:46:48 +00:00
Extend Require macro to support impl block
This commit is contained in:
parent
1ae1881240
commit
dba89b508d
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -6,5 +6,6 @@
|
||||
"x86_64-custom.json",
|
||||
"-Zbuild-std=core,alloc,compiler_builtins",
|
||||
"-Zbuild-std-features=compiler-builtins-mem"
|
||||
]
|
||||
],
|
||||
"rust-analyzer.showUnlinkedFileNotification": false
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
//! Below is a simple example.
|
||||
//! Suppose we have a channel that may have read and write capability.
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```ignore
|
||||
//! /// A simple channel, only for demonstration.
|
||||
//! struct Channel<R: RightSet> {
|
||||
//! rights: PhantomData<R>,
|
||||
@ -42,7 +42,7 @@
|
||||
//! ```
|
||||
//! When we initialize channels with different rights, it can check whether the function
|
||||
//! are wrongly used due to lack of capabilities at compilation time.
|
||||
//! ```rust
|
||||
//! ```ignore
|
||||
//! let read_channel = Channel::<R>::new();
|
||||
//! read_channel.read();
|
||||
//! // read_channel.write(); // compilation error!
|
||||
@ -73,20 +73,21 @@
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use require_item::RequireItem;
|
||||
use syn::parse_macro_input;
|
||||
use syn::ItemFn;
|
||||
|
||||
use crate::require_attr::expand_require;
|
||||
use crate::require_attr::RequireAttr;
|
||||
|
||||
mod require_attr;
|
||||
mod require_item;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn require(
|
||||
attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let item_fn = parse_macro_input!(item as ItemFn);
|
||||
let require_item = parse_macro_input!(item as RequireItem);
|
||||
let require_attr = parse_macro_input!(attr as RequireAttr);
|
||||
expand_require(item_fn, require_attr).into()
|
||||
expand_require(require_item, require_attr).into()
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ use proc_macro2::{Ident, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
fold::Fold, parse::Parse, parse_quote, punctuated::Punctuated, token::Comma, GenericParam,
|
||||
Generics, ItemFn, Token, Type, WhereClause,
|
||||
Generics, Token, Type, WhereClause,
|
||||
};
|
||||
|
||||
use super::require_item::RequireItem;
|
||||
|
||||
pub struct RequireAttr {
|
||||
type_set: Type,
|
||||
required_types: Punctuated<Ident, Token![|]>,
|
||||
@ -61,11 +63,19 @@ impl Fold for RequireAttr {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_require(item_fn: ItemFn, mut require_attr: RequireAttr) -> TokenStream {
|
||||
let new_item_fn = require_attr.fold_item_fn(item_fn);
|
||||
quote!(
|
||||
#new_item_fn
|
||||
)
|
||||
pub fn expand_require(item: RequireItem, mut require_attr: RequireAttr) -> TokenStream {
|
||||
match item {
|
||||
RequireItem::Impl(item_impl) => {
|
||||
let new_item_impl = require_attr.fold_item_impl(item_impl);
|
||||
quote!(#new_item_impl)
|
||||
}
|
||||
RequireItem::Fn(item_fn) => {
|
||||
let new_item_fn = require_attr.fold_item_fn(item_fn);
|
||||
quote!(
|
||||
#new_item_fn
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_generic_param(ident: Ident, generic_params: &Punctuated<GenericParam, Comma>) -> bool {
|
||||
|
18
services/libs/jinux-rights-proc/src/require_item.rs
Normal file
18
services/libs/jinux-rights-proc/src/require_item.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use syn::{parse::Parse, ItemFn, ItemImpl, Token};
|
||||
|
||||
pub enum RequireItem {
|
||||
Impl(ItemImpl),
|
||||
Fn(ItemFn),
|
||||
}
|
||||
|
||||
impl Parse for RequireItem {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let token = input.lookahead1();
|
||||
if token.peek(Token!(impl)) {
|
||||
// FIXME: is there any possible token before impl?
|
||||
input.parse().map(RequireItem::Impl)
|
||||
} else {
|
||||
input.parse().map(RequireItem::Fn)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user