safety_parser/
split_attrs.rs1use proc_macro2::TokenStream;
2use quote::ToTokens;
3use std::mem::take;
4use syn::*;
5
6pub fn split_attrs_and_rest(ts: TokenStream) -> Input {
10 if let Ok(stmt) = parse2::<Stmt>(ts.clone()) {
11 match stmt {
12 Stmt::Item(item) => parse_item(item),
13 Stmt::Expr(expr, _) => parse_expr(expr),
14 Stmt::Local(mut local) => Input::new(take(&mut local.attrs), local),
15 Stmt::Macro(mut macro_) => Input::new(take(&mut macro_.attrs), macro_),
16 }
17 } else {
18 Input::new(Vec::new(), ts)
19 }
20}
21
22fn parse_item(mut item: Item) -> Input {
23 let attrs = match &mut item {
24 Item::Fn(fun) => take(&mut fun.attrs),
25 Item::Impl(imp) => take(&mut imp.attrs),
26 Item::Trait(trait_) => take(&mut trait_.attrs),
27 _ => Vec::new(),
28 };
29 Input::new(attrs, item).set_gen_doc()
30}
31
32fn parse_expr(mut expr: Expr) -> Input {
33 let attrs = match &mut expr {
34 Expr::Unsafe(unsafe_) => take(&mut unsafe_.attrs),
35 Expr::Let(let_) => take(&mut let_.attrs),
36 Expr::Assign(assign) => take(&mut assign.attrs),
37 Expr::Block(block) => take(&mut block.attrs),
38 Expr::Call(call) => take(&mut call.attrs),
39 Expr::MethodCall(call) => take(&mut call.attrs),
40 Expr::Match(match_) => take(&mut match_.attrs),
41 Expr::If(if_) => take(&mut if_.attrs),
42 Expr::While(while_) => take(&mut while_.attrs),
43 Expr::Loop(loop_) => take(&mut loop_.attrs),
44 Expr::ForLoop(for_) => take(&mut for_.attrs),
45 Expr::Macro(macro_) => take(&mut macro_.attrs),
46 Expr::Struct(struct_) => take(&mut struct_.attrs),
47 Expr::Array(array) => take(&mut array.attrs),
48 Expr::Closure(closure) => take(&mut closure.attrs),
49 Expr::Path(path) => take(&mut path.attrs),
50 Expr::Async(async_) => take(&mut async_.attrs),
51 Expr::Await(await_) => take(&mut await_.attrs),
52 Expr::Const(const_) => take(&mut const_.attrs),
53 Expr::Break(break_) => take(&mut break_.attrs),
54 Expr::Continue(continue_) => take(&mut continue_.attrs),
55 Expr::Repeat(repeat) => take(&mut repeat.attrs),
56 Expr::Return(return_) => take(&mut return_.attrs),
57 Expr::Try(try_) => take(&mut try_.attrs),
58 Expr::TryBlock(block) => take(&mut block.attrs),
59 Expr::Yield(yield_) => take(&mut yield_.attrs),
60 _ => Vec::new(),
61 };
62 Input::new(attrs, expr)
63}
64
65#[derive(Debug)]
66pub struct Input {
67 pub attrs: TokenStream,
68 pub rest: TokenStream,
69 pub gen_doc: bool,
71}
72
73impl Input {
74 fn new(attrs: Vec<Attribute>, rest: impl ToTokens) -> Input {
75 let attrs = attrs.into_iter().map(|attr| attr.into_token_stream()).collect();
76 Input { attrs, rest: rest.into_token_stream(), gen_doc: false }
77 }
78
79 fn set_gen_doc(mut self) -> Self {
80 self.gen_doc = true;
81 self
82 }
83}
84
85#[test]
86fn split_attrs_on_item() {
87 let ts = quote::quote! {
88 #[a]
89 unsafe fn f() {}
90 };
91 let input = dbg!(split_attrs_and_rest(ts));
92 assert!(!input.attrs.is_empty());
93}
94
95#[test]
96fn split_attrs_on_expr() {
97 let ts = quote::quote! {
98 #[a]
99 unsafe { call() };
100 };
101 dbg!(split_attrs_and_rest(ts));
102}