blob: 87708eef547767d3ff4c5244a89b9451c2175a27 [file] [log] [blame]
Alex Crichtonbabc99e2017-07-05 18:00:29 -07001//! A "shim crate" intended to multiplex the `proc_macro` API on to stable Rust.
2//!
3//! Procedural macros in Rust operate over the upstream
4//! `proc_macro::TokenStream` type. This type currently is quite conservative
5//! and exposed no internal implementation details. Nightly compilers, however,
6//! contain a much richer interface. This richer interface allows fine-grained
7//! inspection of the token stream which avoids stringification/re-lexing and
8//! also preserves span information.
9//!
10//! The upcoming APIs added to `proc_macro` upstream are the foundation for
11//! productive procedural macros in the ecosystem. To help prepare the ecosystem
12//! for using them this crate serves to both compile on stable and nightly and
13//! mirrors the API-to-be. The intention is that procedural macros which switch
14//! to use this crate will be trivially able to switch to the upstream
15//! `proc_macro` crate once its API stabilizes.
16//!
David Tolnayd66ecf62018-01-02 20:05:42 -080017//! In the meantime this crate also has a `nightly` Cargo feature which
Alex Crichtonbabc99e2017-07-05 18:00:29 -070018//! enables it to reimplement itself with the unstable API of `proc_macro`.
19//! This'll allow immediate usage of the beneficial upstream API, particularly
20//! around preserving span information.
21
David Tolnay15cc4982018-01-08 08:03:27 -080022// Proc-macro2 types in rustdoc of other crates get linked to here.
23#![doc(html_root_url = "https://docs.rs/proc-macro2/0.1.10")]
24
David Tolnayd66ecf62018-01-02 20:05:42 -080025#![cfg_attr(feature = "nightly", feature(proc_macro))]
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070026
Alex Crichton44bffbc2017-05-19 17:51:59 -070027extern crate proc_macro;
28
David Tolnayd66ecf62018-01-02 20:05:42 -080029#[cfg(not(feature = "nightly"))]
David Tolnayb1032662017-05-31 15:52:28 -070030extern crate unicode_xid;
Alex Crichton44bffbc2017-05-19 17:51:59 -070031
32use std::fmt;
Alex Crichton44bffbc2017-05-19 17:51:59 -070033use std::str::FromStr;
34use std::iter::FromIterator;
35
David Tolnayb1032662017-05-31 15:52:28 -070036#[macro_use]
David Tolnayd66ecf62018-01-02 20:05:42 -080037#[cfg(not(feature = "nightly"))]
David Tolnayb1032662017-05-31 15:52:28 -070038mod strnom;
39
Alex Crichton44bffbc2017-05-19 17:51:59 -070040#[path = "stable.rs"]
David Tolnayd66ecf62018-01-02 20:05:42 -080041#[cfg(not(feature = "nightly"))]
Alex Crichtonb15c6352017-05-19 19:36:36 -070042mod imp;
43#[path = "unstable.rs"]
David Tolnayd66ecf62018-01-02 20:05:42 -080044#[cfg(feature = "nightly")]
Alex Crichton44bffbc2017-05-19 17:51:59 -070045mod imp;
46
David Tolnaycb1b85f2017-06-03 16:40:35 -070047#[macro_use]
48mod macros;
49
50#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -070051pub struct TokenStream(imp::TokenStream);
52
Alex Crichton44bffbc2017-05-19 17:51:59 -070053pub struct LexError(imp::LexError);
54
55impl FromStr for TokenStream {
56 type Err = LexError;
57
58 fn from_str(src: &str) -> Result<TokenStream, LexError> {
59 match src.parse() {
60 Ok(e) => Ok(TokenStream(e)),
61 Err(e) => Err(LexError(e)),
62 }
63 }
64}
65
Alex Crichton44bffbc2017-05-19 17:51:59 -070066impl From<proc_macro::TokenStream> for TokenStream {
67 fn from(inner: proc_macro::TokenStream) -> TokenStream {
68 TokenStream(inner.into())
69 }
70}
71
72impl From<TokenStream> for proc_macro::TokenStream {
73 fn from(inner: TokenStream) -> proc_macro::TokenStream {
74 inner.0.into()
75 }
76}
77
78impl From<TokenTree> for TokenStream {
79 fn from(tree: TokenTree) -> TokenStream {
80 TokenStream(tree.into())
81 }
82}
83
Alex Crichton44bffbc2017-05-19 17:51:59 -070084impl<T: Into<TokenStream>> FromIterator<T> for TokenStream {
85 fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
86 TokenStream(streams.into_iter().map(|t| t.into().0).collect())
87 }
88}
89
90impl IntoIterator for TokenStream {
91 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -070092 type IntoIter = TokenTreeIter;
Alex Crichton44bffbc2017-05-19 17:51:59 -070093
Alex Crichton1a7f7622017-07-05 17:47:15 -070094 fn into_iter(self) -> TokenTreeIter {
95 TokenTreeIter(self.0.into_iter())
Alex Crichton44bffbc2017-05-19 17:51:59 -070096 }
97}
98
99impl TokenStream {
100 pub fn empty() -> TokenStream {
101 TokenStream(imp::TokenStream::empty())
102 }
103
104 pub fn is_empty(&self) -> bool {
105 self.0.is_empty()
106 }
107}
108
Nika Layzellb35a9a32017-12-30 14:34:35 -0500109// Returned by reference, so we can't easily wrap it.
David Tolnay1ebe3972018-01-02 20:14:20 -0800110#[cfg(procmacro2_semver_exempt)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500111pub use imp::FileName;
112
David Tolnay1ebe3972018-01-02 20:14:20 -0800113#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500114#[derive(Clone, PartialEq, Eq)]
115pub struct SourceFile(imp::SourceFile);
116
David Tolnay1ebe3972018-01-02 20:14:20 -0800117#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500118impl SourceFile {
119 /// Get the path to this source file as a string.
Nika Layzellb35a9a32017-12-30 14:34:35 -0500120 pub fn path(&self) -> &FileName {
121 self.0.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500122 }
123
124 pub fn is_real(&self) -> bool {
125 self.0.is_real()
126 }
127}
128
David Tolnay1ebe3972018-01-02 20:14:20 -0800129#[cfg(procmacro2_semver_exempt)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500130impl AsRef<FileName> for SourceFile {
131 fn as_ref(&self) -> &FileName {
132 self.0.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500133 }
134}
135
David Tolnay1ebe3972018-01-02 20:14:20 -0800136#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500137impl fmt::Debug for SourceFile {
138 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139 self.0.fmt(f)
140 }
141}
142
David Tolnay1ebe3972018-01-02 20:14:20 -0800143#[cfg(procmacro2_semver_exempt)]
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500144pub struct LineColumn {
145 pub line: usize,
146 pub column: usize,
147}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500148
David Tolnaycb1b85f2017-06-03 16:40:35 -0700149#[derive(Copy, Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700150pub struct Span(imp::Span);
151
Alex Crichton44bffbc2017-05-19 17:51:59 -0700152impl Span {
153 pub fn call_site() -> Span {
154 Span(imp::Span::call_site())
155 }
Alex Crichtone6085b72017-11-21 07:24:25 -0800156
157 pub fn def_site() -> Span {
158 Span(imp::Span::def_site())
159 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500160
David Tolnay4e8e3972018-01-05 18:10:22 -0800161 /// Creates a new span with the same line/column information as `self` but
162 /// that resolves symbols as though it were at `other`.
163 pub fn resolved_at(&self, other: Span) -> Span {
164 Span(self.0.resolved_at(other.0))
165 }
166
167 /// Creates a new span with the same name resolution behavior as `self` but
168 /// with the line/column information of `other`.
169 pub fn located_at(&self, other: Span) -> Span {
170 Span(self.0.located_at(other.0))
171 }
172
David Tolnayd66ecf62018-01-02 20:05:42 -0800173 /// This method is only available when the `"nightly"` feature is enabled.
174 #[cfg(feature = "nightly")]
David Tolnay16a17202017-12-31 10:47:24 -0500175 pub fn unstable(self) -> proc_macro::Span {
176 self.0.unstable()
177 }
178
David Tolnay1ebe3972018-01-02 20:14:20 -0800179 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500180 pub fn source_file(&self) -> SourceFile {
181 SourceFile(self.0.source_file())
182 }
183
David Tolnay1ebe3972018-01-02 20:14:20 -0800184 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500185 pub fn start(&self) -> LineColumn {
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500186 let imp::LineColumn{ line, column } = self.0.start();
David Tolnay79105e52017-12-31 11:03:04 -0500187 LineColumn { line: line, column: column }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500188 }
189
David Tolnay1ebe3972018-01-02 20:14:20 -0800190 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500191 pub fn end(&self) -> LineColumn {
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500192 let imp::LineColumn{ line, column } = self.0.end();
David Tolnay79105e52017-12-31 11:03:04 -0500193 LineColumn { line: line, column: column }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500194 }
195
David Tolnay1ebe3972018-01-02 20:14:20 -0800196 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500197 pub fn join(&self, other: Span) -> Option<Span> {
198 self.0.join(other.0).map(Span)
199 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700200}
201
David Tolnay977f8282017-05-31 17:41:33 -0700202#[derive(Clone, Debug)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700203pub struct TokenTree {
204 pub span: Span,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700205 pub kind: TokenNode,
206}
207
208impl From<TokenNode> for TokenTree {
209 fn from(kind: TokenNode) -> TokenTree {
David Tolnay1ce3a792018-01-07 12:21:03 -0800210 TokenTree { span: Span::def_site(), kind: kind }
Alex Crichton1a7f7622017-07-05 17:47:15 -0700211 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700212}
213
Alex Crichton44bffbc2017-05-19 17:51:59 -0700214impl fmt::Display for TokenTree {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 TokenStream::from(self.clone()).fmt(f)
217 }
218}
219
David Tolnay977f8282017-05-31 17:41:33 -0700220#[derive(Clone, Debug)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700221pub enum TokenNode {
222 Group(Delimiter, TokenStream),
223 Term(Term),
224 Op(char, Spacing),
Alex Crichton44bffbc2017-05-19 17:51:59 -0700225 Literal(Literal),
226}
227
Michael Layzell5372f4b2017-06-02 10:29:31 -0400228#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700229pub enum Delimiter {
230 Parenthesis,
231 Brace,
232 Bracket,
233 None,
234}
235
David Tolnaycb1b85f2017-06-03 16:40:35 -0700236#[derive(Copy, Clone)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700237pub struct Term(imp::Term);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700238
Alex Crichton1a7f7622017-07-05 17:47:15 -0700239impl Term {
240 pub fn intern(string: &str) -> Term {
David Tolnay10effeb2018-01-06 11:07:49 -0800241 Term(imp::Term::intern(string))
Alex Crichton44bffbc2017-05-19 17:51:59 -0700242 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700243
Alex Crichton43881252017-05-26 08:51:06 -0700244 pub fn as_str(&self) -> &str {
David Tolnay10effeb2018-01-06 11:07:49 -0800245 self.0.as_str()
Alex Crichton44bffbc2017-05-19 17:51:59 -0700246 }
247}
248
Lukas Kalbertodteb3f9302017-08-20 18:58:41 +0200249#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700250pub enum Spacing {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700251 Alone,
252 Joint,
253}
254
David Tolnaycb1b85f2017-06-03 16:40:35 -0700255#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700256pub struct Literal(imp::Literal);
257
Alex Crichton1a7f7622017-07-05 17:47:15 -0700258macro_rules! int_literals {
259 ($($kind:ident,)*) => ($(
260 pub fn $kind(n: $kind) -> Literal {
261 Literal(n.into())
262 }
263 )*)
264}
265
Alex Crichton852d53d2017-05-19 19:25:08 -0700266impl Literal {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700267 pub fn integer(s: i64) -> Literal {
268 Literal(imp::Literal::integer(s))
269 }
270
271 int_literals! {
Alex Crichton1a16c782017-07-05 18:06:36 -0700272 u8, u16, u32, u64, usize,
273 i8, i16, i32, i64, isize,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700274 }
275
276 pub fn float(f: f64) -> Literal {
277 Literal(imp::Literal::float(f))
278 }
279
280 pub fn f64(f: f64) -> Literal {
281 Literal(f.into())
282 }
283
284 pub fn f32(f: f32) -> Literal {
285 Literal(f.into())
286 }
287
288 pub fn string(string: &str) -> Literal {
289 Literal(string.into())
290 }
291
292 pub fn character(ch: char) -> Literal {
293 Literal(ch.into())
Alex Crichton76a5cc82017-05-23 07:01:44 -0700294 }
295
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700296 pub fn byte_string(s: &[u8]) -> Literal {
297 Literal(imp::Literal::byte_string(s))
Alex Crichton852d53d2017-05-19 19:25:08 -0700298 }
Alex Crichton76a5cc82017-05-23 07:01:44 -0700299
Alex Crichton1a7f7622017-07-05 17:47:15 -0700300 // =======================================================================
301 // Not present upstream in proc_macro yet
302
303 pub fn byte_char(b: u8) -> Literal {
304 Literal(imp::Literal::byte_char(b))
305 }
306
Alex Crichton76a5cc82017-05-23 07:01:44 -0700307 pub fn doccomment(s: &str) -> Literal {
308 Literal(imp::Literal::doccomment(s))
309 }
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700310
Alex Crichton31316622017-05-26 12:54:47 -0700311 pub fn raw_string(s: &str, pounds: usize) -> Literal {
312 Literal(imp::Literal::raw_string(s, pounds))
313 }
314
315 pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
316 Literal(imp::Literal::raw_byte_string(s, pounds))
317 }
Alex Crichton852d53d2017-05-19 19:25:08 -0700318}
319
Alex Crichton1a7f7622017-07-05 17:47:15 -0700320pub struct TokenTreeIter(imp::TokenTreeIter);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700321
Alex Crichton1a7f7622017-07-05 17:47:15 -0700322impl Iterator for TokenTreeIter {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700323 type Item = TokenTree;
324
325 fn next(&mut self) -> Option<TokenTree> {
326 self.0.next()
327 }
328}
David Tolnaycb1b85f2017-06-03 16:40:35 -0700329
330forward_fmt!(Debug for LexError);
331forward_fmt!(Debug for Literal);
332forward_fmt!(Debug for Span);
Alex Crichton1a7f7622017-07-05 17:47:15 -0700333forward_fmt!(Debug for Term);
334forward_fmt!(Debug for TokenTreeIter);
David Tolnaycb1b85f2017-06-03 16:40:35 -0700335forward_fmt!(Debug for TokenStream);
336forward_fmt!(Display for Literal);
337forward_fmt!(Display for TokenStream);