blob: 49e3d21efa15cd816af648f5ebc7da6845f655a5 [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 Tolnayd66ecf62018-01-02 20:05:42 -080022#![cfg_attr(feature = "nightly", feature(proc_macro))]
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070023
Alex Crichton44bffbc2017-05-19 17:51:59 -070024extern crate proc_macro;
25
David Tolnayd66ecf62018-01-02 20:05:42 -080026#[cfg(not(feature = "nightly"))]
David Tolnayb1032662017-05-31 15:52:28 -070027extern crate unicode_xid;
Alex Crichton44bffbc2017-05-19 17:51:59 -070028
29use std::fmt;
Alex Crichton44bffbc2017-05-19 17:51:59 -070030use std::str::FromStr;
31use std::iter::FromIterator;
32
David Tolnayb1032662017-05-31 15:52:28 -070033#[macro_use]
David Tolnayd66ecf62018-01-02 20:05:42 -080034#[cfg(not(feature = "nightly"))]
David Tolnayb1032662017-05-31 15:52:28 -070035mod strnom;
36
Alex Crichton44bffbc2017-05-19 17:51:59 -070037#[path = "stable.rs"]
David Tolnayd66ecf62018-01-02 20:05:42 -080038#[cfg(not(feature = "nightly"))]
Alex Crichtonb15c6352017-05-19 19:36:36 -070039mod imp;
40#[path = "unstable.rs"]
David Tolnayd66ecf62018-01-02 20:05:42 -080041#[cfg(feature = "nightly")]
Alex Crichton44bffbc2017-05-19 17:51:59 -070042mod imp;
43
David Tolnaycb1b85f2017-06-03 16:40:35 -070044#[macro_use]
45mod macros;
46
47#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -070048pub struct TokenStream(imp::TokenStream);
49
Alex Crichton44bffbc2017-05-19 17:51:59 -070050pub struct LexError(imp::LexError);
51
52impl FromStr for TokenStream {
53 type Err = LexError;
54
55 fn from_str(src: &str) -> Result<TokenStream, LexError> {
56 match src.parse() {
57 Ok(e) => Ok(TokenStream(e)),
58 Err(e) => Err(LexError(e)),
59 }
60 }
61}
62
Alex Crichton44bffbc2017-05-19 17:51:59 -070063impl From<proc_macro::TokenStream> for TokenStream {
64 fn from(inner: proc_macro::TokenStream) -> TokenStream {
65 TokenStream(inner.into())
66 }
67}
68
69impl From<TokenStream> for proc_macro::TokenStream {
70 fn from(inner: TokenStream) -> proc_macro::TokenStream {
71 inner.0.into()
72 }
73}
74
75impl From<TokenTree> for TokenStream {
76 fn from(tree: TokenTree) -> TokenStream {
77 TokenStream(tree.into())
78 }
79}
80
Alex Crichton44bffbc2017-05-19 17:51:59 -070081impl<T: Into<TokenStream>> FromIterator<T> for TokenStream {
82 fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
83 TokenStream(streams.into_iter().map(|t| t.into().0).collect())
84 }
85}
86
87impl IntoIterator for TokenStream {
88 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -070089 type IntoIter = TokenTreeIter;
Alex Crichton44bffbc2017-05-19 17:51:59 -070090
Alex Crichton1a7f7622017-07-05 17:47:15 -070091 fn into_iter(self) -> TokenTreeIter {
92 TokenTreeIter(self.0.into_iter())
Alex Crichton44bffbc2017-05-19 17:51:59 -070093 }
94}
95
96impl TokenStream {
97 pub fn empty() -> TokenStream {
98 TokenStream(imp::TokenStream::empty())
99 }
100
101 pub fn is_empty(&self) -> bool {
102 self.0.is_empty()
103 }
104}
105
Nika Layzellb35a9a32017-12-30 14:34:35 -0500106// Returned by reference, so we can't easily wrap it.
David Tolnay1ebe3972018-01-02 20:14:20 -0800107#[cfg(procmacro2_semver_exempt)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500108pub use imp::FileName;
109
David Tolnay1ebe3972018-01-02 20:14:20 -0800110#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500111#[derive(Clone, PartialEq, Eq)]
112pub struct SourceFile(imp::SourceFile);
113
David Tolnay1ebe3972018-01-02 20:14:20 -0800114#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500115impl SourceFile {
116 /// Get the path to this source file as a string.
Nika Layzellb35a9a32017-12-30 14:34:35 -0500117 pub fn path(&self) -> &FileName {
118 self.0.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500119 }
120
121 pub fn is_real(&self) -> bool {
122 self.0.is_real()
123 }
124}
125
David Tolnay1ebe3972018-01-02 20:14:20 -0800126#[cfg(procmacro2_semver_exempt)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500127impl AsRef<FileName> for SourceFile {
128 fn as_ref(&self) -> &FileName {
129 self.0.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500130 }
131}
132
David Tolnay1ebe3972018-01-02 20:14:20 -0800133#[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500134impl fmt::Debug for SourceFile {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 self.0.fmt(f)
137 }
138}
139
David Tolnay1ebe3972018-01-02 20:14:20 -0800140#[cfg(procmacro2_semver_exempt)]
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500141pub struct LineColumn {
142 pub line: usize,
143 pub column: usize,
144}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500145
David Tolnaycb1b85f2017-06-03 16:40:35 -0700146#[derive(Copy, Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700147pub struct Span(imp::Span);
148
Alex Crichtone6085b72017-11-21 07:24:25 -0800149#[doc(hidden)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700150impl Default for Span {
151 fn default() -> Span {
Alex Crichtone6085b72017-11-21 07:24:25 -0800152 Span(imp::Span::def_site())
Alex Crichton44bffbc2017-05-19 17:51:59 -0700153 }
154}
155
156impl Span {
157 pub fn call_site() -> Span {
158 Span(imp::Span::call_site())
159 }
Alex Crichtone6085b72017-11-21 07:24:25 -0800160
161 pub fn def_site() -> Span {
162 Span(imp::Span::def_site())
163 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500164
David Tolnayd66ecf62018-01-02 20:05:42 -0800165 /// This method is only available when the `"nightly"` feature is enabled.
166 #[cfg(feature = "nightly")]
David Tolnay16a17202017-12-31 10:47:24 -0500167 pub fn unstable(self) -> proc_macro::Span {
168 self.0.unstable()
169 }
170
David Tolnay1ebe3972018-01-02 20:14:20 -0800171 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500172 pub fn source_file(&self) -> SourceFile {
173 SourceFile(self.0.source_file())
174 }
175
David Tolnay1ebe3972018-01-02 20:14:20 -0800176 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500177 pub fn start(&self) -> LineColumn {
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500178 let imp::LineColumn{ line, column } = self.0.start();
David Tolnay79105e52017-12-31 11:03:04 -0500179 LineColumn { line: line, column: column }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500180 }
181
David Tolnay1ebe3972018-01-02 20:14:20 -0800182 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500183 pub fn end(&self) -> LineColumn {
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500184 let imp::LineColumn{ line, column } = self.0.end();
David Tolnay79105e52017-12-31 11:03:04 -0500185 LineColumn { line: line, column: column }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500186 }
187
David Tolnay1ebe3972018-01-02 20:14:20 -0800188 #[cfg(procmacro2_semver_exempt)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500189 pub fn join(&self, other: Span) -> Option<Span> {
190 self.0.join(other.0).map(Span)
191 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700192}
193
David Tolnay977f8282017-05-31 17:41:33 -0700194#[derive(Clone, Debug)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700195pub struct TokenTree {
196 pub span: Span,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700197 pub kind: TokenNode,
198}
199
200impl From<TokenNode> for TokenTree {
201 fn from(kind: TokenNode) -> TokenTree {
202 TokenTree { span: Span::default(), kind: kind }
203 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700204}
205
Alex Crichton44bffbc2017-05-19 17:51:59 -0700206impl fmt::Display for TokenTree {
207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208 TokenStream::from(self.clone()).fmt(f)
209 }
210}
211
David Tolnay977f8282017-05-31 17:41:33 -0700212#[derive(Clone, Debug)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700213pub enum TokenNode {
214 Group(Delimiter, TokenStream),
215 Term(Term),
216 Op(char, Spacing),
Alex Crichton44bffbc2017-05-19 17:51:59 -0700217 Literal(Literal),
218}
219
Michael Layzell5372f4b2017-06-02 10:29:31 -0400220#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700221pub enum Delimiter {
222 Parenthesis,
223 Brace,
224 Bracket,
225 None,
226}
227
David Tolnaycb1b85f2017-06-03 16:40:35 -0700228#[derive(Copy, Clone)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700229pub struct Term(imp::Term);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700230
Alex Crichton1a7f7622017-07-05 17:47:15 -0700231impl Term {
232 pub fn intern(string: &str) -> Term {
233 Term(string.into())
Alex Crichton44bffbc2017-05-19 17:51:59 -0700234 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700235
Alex Crichton43881252017-05-26 08:51:06 -0700236 pub fn as_str(&self) -> &str {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700237 &self.0
238 }
239}
240
Lukas Kalbertodteb3f9302017-08-20 18:58:41 +0200241#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700242pub enum Spacing {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700243 Alone,
244 Joint,
245}
246
David Tolnaycb1b85f2017-06-03 16:40:35 -0700247#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700248pub struct Literal(imp::Literal);
249
Alex Crichton1a7f7622017-07-05 17:47:15 -0700250macro_rules! int_literals {
251 ($($kind:ident,)*) => ($(
252 pub fn $kind(n: $kind) -> Literal {
253 Literal(n.into())
254 }
255 )*)
256}
257
Alex Crichton852d53d2017-05-19 19:25:08 -0700258impl Literal {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700259 pub fn integer(s: i64) -> Literal {
260 Literal(imp::Literal::integer(s))
261 }
262
263 int_literals! {
Alex Crichton1a16c782017-07-05 18:06:36 -0700264 u8, u16, u32, u64, usize,
265 i8, i16, i32, i64, isize,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700266 }
267
268 pub fn float(f: f64) -> Literal {
269 Literal(imp::Literal::float(f))
270 }
271
272 pub fn f64(f: f64) -> Literal {
273 Literal(f.into())
274 }
275
276 pub fn f32(f: f32) -> Literal {
277 Literal(f.into())
278 }
279
280 pub fn string(string: &str) -> Literal {
281 Literal(string.into())
282 }
283
284 pub fn character(ch: char) -> Literal {
285 Literal(ch.into())
Alex Crichton76a5cc82017-05-23 07:01:44 -0700286 }
287
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700288 pub fn byte_string(s: &[u8]) -> Literal {
289 Literal(imp::Literal::byte_string(s))
Alex Crichton852d53d2017-05-19 19:25:08 -0700290 }
Alex Crichton76a5cc82017-05-23 07:01:44 -0700291
Alex Crichton1a7f7622017-07-05 17:47:15 -0700292 // =======================================================================
293 // Not present upstream in proc_macro yet
294
295 pub fn byte_char(b: u8) -> Literal {
296 Literal(imp::Literal::byte_char(b))
297 }
298
Alex Crichton76a5cc82017-05-23 07:01:44 -0700299 pub fn doccomment(s: &str) -> Literal {
300 Literal(imp::Literal::doccomment(s))
301 }
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700302
Alex Crichton31316622017-05-26 12:54:47 -0700303 pub fn raw_string(s: &str, pounds: usize) -> Literal {
304 Literal(imp::Literal::raw_string(s, pounds))
305 }
306
307 pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
308 Literal(imp::Literal::raw_byte_string(s, pounds))
309 }
Alex Crichton852d53d2017-05-19 19:25:08 -0700310}
311
Alex Crichton1a7f7622017-07-05 17:47:15 -0700312pub struct TokenTreeIter(imp::TokenTreeIter);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700313
Alex Crichton1a7f7622017-07-05 17:47:15 -0700314impl Iterator for TokenTreeIter {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700315 type Item = TokenTree;
316
317 fn next(&mut self) -> Option<TokenTree> {
318 self.0.next()
319 }
320}
David Tolnaycb1b85f2017-06-03 16:40:35 -0700321
322forward_fmt!(Debug for LexError);
323forward_fmt!(Debug for Literal);
324forward_fmt!(Debug for Span);
Alex Crichton1a7f7622017-07-05 17:47:15 -0700325forward_fmt!(Debug for Term);
326forward_fmt!(Debug for TokenTreeIter);
David Tolnaycb1b85f2017-06-03 16:40:35 -0700327forward_fmt!(Debug for TokenStream);
328forward_fmt!(Display for Literal);
329forward_fmt!(Display for TokenStream);