c2rust_ast_printer/
pprust.rs1#[cfg(test)]
2mod tests;
3
4#[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Copy, Clone)]
5pub struct BytePos(pub u32);
6
7pub mod comments {
8 #[derive(Clone)]
9 pub struct Comment {
10 pub lines: Vec<String>,
11 pub pos: super::BytePos,
12 }
13}
14
15pub enum MacHeader<'a> {
16 Path(&'a syn::Path),
17 Keyword(&'static str),
18}
19
20pub struct Comments {
21 comments: Vec<comments::Comment>,
23 current: usize,
24}
25
26impl Comments {
27 pub fn new(
28 comments: Vec<comments::Comment>,
30 ) -> Comments {
31 Comments {
32 comments,
34 current: 0,
35 }
36 }
37
38 pub fn next(&self) -> Option<comments::Comment> {
53 self.comments.get(self.current).cloned()
54 }
55
56 pub fn trailing_comment(
57 &mut self,
58 _span: proc_macro2::Span,
59 _next_pos: Option<usize>,
60 ) -> Option<String> {
61 None
72 }
73}
74
75impl Extend<comments::Comment> for Comments {
76 fn extend<I>(&mut self, iter: I)
77 where
78 I: IntoIterator<Item = comments::Comment>,
79 {
80 self.comments.extend(iter);
81 }
82}
83
84fn strip_main_fn(s: &str) -> &str {
85 s.trim_start()
86 .trim_start_matches("fn main()")
87 .trim_start()
88 .trim_start_matches('{')
89 .trim_start()
90 .trim_end()
91 .trim_end_matches('}')
92 .trim_end()
93}
94
95fn minimal_file(stmt: syn::Stmt) -> syn::File {
96 let item = syn::Item::Fn(main_fn(stmt));
97 syn::File {
98 shebang: None,
99 attrs: vec![],
100 items: vec![item],
101 }
102}
103
104fn main_fn(stmt: syn::Stmt) -> syn::ItemFn {
105 let generics = syn::Generics {
106 lt_token: None,
107 params: Default::default(),
108 gt_token: None,
109 where_clause: None,
110 };
111 let ident = syn::Ident::new("main", proc_macro2::Span::call_site());
112 let sig = syn::Signature {
113 constness: None,
114 asyncness: None,
115 unsafety: None,
116 abi: None,
117 fn_token: Default::default(),
118 ident,
119 generics,
120 paren_token: Default::default(),
121 inputs: Default::default(),
122 variadic: None,
123 output: syn::ReturnType::Default,
124 };
125 let block = Box::new(syn::Block {
126 brace_token: Default::default(),
127 stmts: vec![stmt],
128 });
129 syn::ItemFn {
130 attrs: vec![],
131 vis: syn::Visibility::Inherited,
132 sig,
133 block,
134 }
135}
136
137fn ret_expr() -> syn::Expr {
138 syn::Expr::Return(syn::ExprReturn {
139 attrs: vec![],
140 return_token: Default::default(),
141 expr: None,
142 })
143}
144
145pub fn expr_to_string(e: &syn::Expr) -> String {
146 let s = to_string(move || minimal_file(syn::Stmt::Expr(e.clone(), None)));
147 strip_main_fn(&s).trim_end_matches(';').to_owned()
148}
149
150pub fn path_to_string(p: &syn::Path) -> String {
151 let e = syn::Expr::Path(syn::ExprPath {
152 attrs: vec![],
153 qself: None,
154 path: p.clone(),
155 });
156 expr_to_string(&e)
157}
158
159pub fn pat_to_string(p: &syn::Pat) -> String {
160 let ret_expr = Box::new(ret_expr());
161 let e = syn::Expr::Let(syn::ExprLet {
162 attrs: vec![],
163 let_token: Default::default(),
164 pat: Box::new(p.clone()),
165 eq_token: Default::default(),
166 expr: ret_expr,
167 });
168 let expr_str = expr_to_string(&e);
169 expr_str
170 .trim_start_matches("(let")
171 .trim_start()
172 .trim_end()
173 .trim_end_matches(';')
174 .trim_end_matches("return)")
175 .trim_end()
176 .trim_end_matches('=')
177 .trim_end()
178 .to_owned()
179}
180
181pub fn stmt_to_string(s: &syn::Stmt) -> String {
182 let s = to_string(move || minimal_file(s.clone()));
183 strip_main_fn(&s).to_owned()
184}
185
186pub fn to_string<F>(f: F) -> String
187where
188 F: FnOnce() -> syn::File,
189{
190 prettyplease::unparse(&f())
191}