mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-12 06: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",
|
"x86_64-custom.json",
|
||||||
"-Zbuild-std=core,alloc,compiler_builtins",
|
"-Zbuild-std=core,alloc,compiler_builtins",
|
||||||
"-Zbuild-std-features=compiler-builtins-mem"
|
"-Zbuild-std-features=compiler-builtins-mem"
|
||||||
]
|
],
|
||||||
|
"rust-analyzer.showUnlinkedFileNotification": false
|
||||||
}
|
}
|
@ -15,7 +15,7 @@
|
|||||||
//! Below is a simple example.
|
//! Below is a simple example.
|
||||||
//! Suppose we have a channel that may have read and write capability.
|
//! Suppose we have a channel that may have read and write capability.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```ignore
|
||||||
//! /// A simple channel, only for demonstration.
|
//! /// A simple channel, only for demonstration.
|
||||||
//! struct Channel<R: RightSet> {
|
//! struct Channel<R: RightSet> {
|
||||||
//! rights: PhantomData<R>,
|
//! rights: PhantomData<R>,
|
||||||
@ -42,7 +42,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! When we initialize channels with different rights, it can check whether the function
|
//! When we initialize channels with different rights, it can check whether the function
|
||||||
//! are wrongly used due to lack of capabilities at compilation time.
|
//! are wrongly used due to lack of capabilities at compilation time.
|
||||||
//! ```rust
|
//! ```ignore
|
||||||
//! let read_channel = Channel::<R>::new();
|
//! let read_channel = Channel::<R>::new();
|
||||||
//! read_channel.read();
|
//! read_channel.read();
|
||||||
//! // read_channel.write(); // compilation error!
|
//! // read_channel.write(); // compilation error!
|
||||||
@ -73,20 +73,21 @@
|
|||||||
#![feature(proc_macro_diagnostic)]
|
#![feature(proc_macro_diagnostic)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use require_item::RequireItem;
|
||||||
use syn::parse_macro_input;
|
use syn::parse_macro_input;
|
||||||
use syn::ItemFn;
|
|
||||||
|
|
||||||
use crate::require_attr::expand_require;
|
use crate::require_attr::expand_require;
|
||||||
use crate::require_attr::RequireAttr;
|
use crate::require_attr::RequireAttr;
|
||||||
|
|
||||||
mod require_attr;
|
mod require_attr;
|
||||||
|
mod require_item;
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn require(
|
pub fn require(
|
||||||
attr: proc_macro::TokenStream,
|
attr: proc_macro::TokenStream,
|
||||||
item: proc_macro::TokenStream,
|
item: proc_macro::TokenStream,
|
||||||
) -> 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);
|
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 quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
fold::Fold, parse::Parse, parse_quote, punctuated::Punctuated, token::Comma, GenericParam,
|
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 {
|
pub struct RequireAttr {
|
||||||
type_set: Type,
|
type_set: Type,
|
||||||
required_types: Punctuated<Ident, Token![|]>,
|
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 {
|
pub fn expand_require(item: RequireItem, mut require_attr: RequireAttr) -> TokenStream {
|
||||||
let new_item_fn = require_attr.fold_item_fn(item_fn);
|
match item {
|
||||||
quote!(
|
RequireItem::Impl(item_impl) => {
|
||||||
#new_item_fn
|
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 {
|
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