rocket_codegen/
proc_macro_ext.rs1use std::ops::RangeBounds;
2
3use devise::Diagnostic;
4use proc_macro2::{Span, Literal};
5
6pub struct Diagnostics(Vec<Diagnostic>);
8
9impl Diagnostics {
10 pub fn new() -> Self {
11 Diagnostics(vec![])
12 }
13
14 pub fn push(&mut self, diag: Diagnostic) {
15 self.0.push(diag);
16 }
17
18 pub fn emit_head(self) -> Diagnostic {
19 let mut iter = self.0.into_iter();
20 let mut last = iter.next().expect("Diagnostic::emit_head empty");
21 for diag in iter {
22 last.emit_as_item_tokens();
24 last = diag;
25 }
26
27 last
28 }
29
30 pub fn head_err_or<T>(self, ok: T) -> devise::Result<T> {
31 match self.0.is_empty() {
32 true => Ok(ok),
33 false => Err(self.emit_head())
34 }
35 }
36}
37
38impl From<Diagnostic> for Diagnostics {
39 fn from(diag: Diagnostic) -> Self {
40 Diagnostics(vec![diag])
41 }
42}
43
44impl From<Vec<Diagnostic>> for Diagnostics {
45 fn from(diags: Vec<Diagnostic>) -> Self {
46 Diagnostics(diags)
47 }
48}
49
50pub struct StringLit(pub String, pub Literal);
51
52impl StringLit {
53 pub fn new<S: Into<String>>(string: S, span: Span) -> Self {
54 let string = string.into();
55 let mut lit = Literal::string(&string);
56 lit.set_span(span);
57 StringLit(string, lit)
58 }
59
60 pub fn span(&self) -> Span {
61 self.1.span()
62 }
63
64 pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Span {
68 self.1.subspan(range).unwrap_or_else(|| self.span())
69 }
70}
71
72impl syn::parse::Parse for StringLit {
73 fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
74 let lit = input.parse::<syn::LitStr>()?;
75 Ok(StringLit::new(lit.value(), lit.span()))
76 }
77}
78
79impl devise::FromMeta for StringLit {
80 fn from_meta(meta: &devise::MetaItem) -> devise::Result<Self> {
81 Ok(StringLit::new(String::from_meta(meta)?, meta.value_span()))
82 }
83}
84
85impl std::ops::Deref for StringLit {
86 type Target = str;
87
88 fn deref(&self) -> &str {
89 &self.0
90 }
91}