const_source_position/
lib.rs1#![allow(incomplete_features)]
2#![feature(adt_const_params)]
3#![feature(proc_macro_span)]
4extern crate proc_macro;
5
6use proc_macro::{TokenStream, Span};
7use quote::quote;
8use syn::spanned::Spanned;
9use syn::{parse_macro_input, Path};
10
11#[proc_macro]
44pub fn source_line (item: TokenStream) -> TokenStream {
45 let path = parse_macro_input!(item as Path);
46
47 let span = Span::call_site();
48 let mut file_source =
49 (*span
50 .source_file()
51 .path()
52 .to_string_lossy()
53 )
54 .to_string();
55
56 let line_column = span.source().start();
57
58 file_source.push_str(&format!(":{}:{}", line_column.line, line_column.column));
59 let lit = syn::LitStr::new(&file_source, span.into());
60
61 let gen_arg = syn::GenericArgument::Const(syn::Expr::Lit(syn::ExprLit { attrs: vec![], lit: syn::Lit::Str(lit) }));
62
63 let mut segments = path.segments.clone();
64
65 let mut gen_args = syn::punctuated::Punctuated::<syn::GenericArgument, syn::token::Comma>::new();
66
67 gen_args.push(gen_arg);
68
69 segments.last_mut().unwrap().arguments = syn::PathArguments::AngleBracketed(
70 syn::AngleBracketedGenericArguments {
71 colon2_token: Some(
72 syn::token::Colon2(path.span())
73 ),
74 lt_token: syn::token::Lt(path.span()),
75 args: gen_args,
76 gt_token: syn::token::Gt(path.span())
77 }
78 );
79
80 let c = syn::Type::Path(syn::TypePath { qself: None, path: Path {
81 leading_colon: path.leading_colon,
82 segments,
83 }});
84
85 quote!(#c).into()
86}