]>
Commit | Line | Data |
---|---|---|
a1dfa0c6 XL |
1 | // force-host |
2 | // no-prefer-dynamic | |
3 | ||
4 | #![crate_type = "proc-macro"] | |
5 | #![feature(proc_macro_diagnostic, proc_macro_span)] | |
6 | ||
7 | extern crate proc_macro; | |
8 | ||
9 | use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; | |
10 | ||
11 | fn parse(input: TokenStream) -> Result<(), Diagnostic> { | |
12 | if let Some(TokenTree::Literal(lit)) = input.into_iter().next() { | |
13 | let mut spans = vec![]; | |
14 | let string = lit.to_string(); | |
15 | for hi in string.matches("hi") { | |
16 | let index = hi.as_ptr() as usize - string.as_ptr() as usize; | |
17 | let subspan = lit.subspan(index..(index + hi.len())).unwrap(); | |
18 | spans.push(subspan); | |
19 | } | |
20 | ||
21 | if !spans.is_empty() { | |
22 | Err(Span::call_site().error("found 'hi's").span_note(spans, "here")) | |
23 | } else { | |
24 | Ok(()) | |
25 | } | |
26 | } else { | |
27 | Err(Span::call_site().error("invalid input: expected string literal")) | |
28 | } | |
29 | } | |
30 | ||
31 | #[proc_macro] | |
32 | pub fn subspan(input: TokenStream) -> TokenStream { | |
33 | if let Err(diag) = parse(input) { | |
34 | diag.emit(); | |
35 | } | |
36 | ||
37 | TokenStream::new() | |
38 | } |