1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#![feature(proc_macro_diagnostic)] use proc_macro::{TokenStream}; use proc_macro2::{TokenTree, Delimiter, Group}; use quote::{quote, quote_spanned}; use syn::parse::{Nothing, Parse, ParseStream, Result}; use syn::token; use syn::spanned::Spanned; use syn::{parse_macro_input, Expr, Ident, Token, Type, Visibility}; use syn::buffer::Cursor; // The below trait was copied from `yew-macro`, originally authored by Justin Starry // trait Peek<'a, T> { // fn peek(cursor: Cursor<'a>) -> Option<(T, Cursor<'a>)>; // } /// Parses the following syntax, which aligns with the input of the real /// `lazy_static` crate. /// /// lazy_static! { /// $VISIBILITY static ref $NAME: $TYPE = $EXPR; /// } /// /// For example: /// /// lazy_static! { /// static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); /// } struct PubCfgUse { } impl PubCfgUse { } struct PubCfgSemver { } impl Parse for PubCfgSemver { fn parse(input: ParseStream) -> Result<Self> { Ok(PubCfgSemver{}) } } // impl Peek<'_, Self> for PubCfgSemver { // fn peek(cursor: Cursor) -> Option<(Self, Cursor)> { // None // } // } // // om_use!(yew @ ^1.21 :: {self as foo, bar}); impl Parse for PubCfgUse { fn parse(input: ParseStream) -> Result<Self> { let scheme: Ident = input.parse()?; let (semver, cursor) = { let inner_cursor = input.fork().cursor(); if let Some((punct, cursor)) = inner_cursor.punct() { if punct.as_char() == '@' { (Some(PubCfgSemver::parse(input)), cursor) } else { (None, cursor) } } else { (None, inner_cursor) } }; //input.parse::<Token![::]>()?; // input.parse::<Token![ref]>()?; // let name: Ident = input.parse()?; // input.parse::<Token![:]>()?; // let ty: Type = input.parse()?; // input.parse::<Token![=]>()?; // let init: Expr = input.parse()?; // input.parse::<Token![;]>()?; input.parse::<Nothing>()?; Ok(PubCfgUse { }) } } #[macro_export] #[proc_macro] pub fn pubcfg_use(input: TokenStream) -> TokenStream { let PubCfgUse { } = parse_macro_input!(input as PubCfgUse); let expanded = quote! { // #visibility struct #name; // impl std::ops::Deref for #name { // type Target = #ty; // fn deref(&self) -> &#ty { // #assert_sync // #assert_sized // static ONCE: std::sync::Once = std::sync::Once::new(); // static mut VALUE: *mut #ty = 0 as *mut #ty; // unsafe { // ONCE.call_once(|| VALUE = #init_ptr); // &*VALUE // } // } // } }; TokenStream::from(expanded) } /////////// // macro_rules! om_use { // ($foo:ident @ ^1.21) => { // // The macro will expand into the contents of this block. // println!("{}", quote!($foo)); // }; // } // // // om_use!(yew @ ^1.21 :: {self as foo, bar}); // om_use!(bar @ ^1.21 :: {self as baz}); // // // om_declare!(baz, { // // fn foo() -> baz { // // // // } // // }) //