]> git.lizzy.rs Git - rust.git/blob - src/libproc_macro/lib.rs
Add doc attributes to proc_macro crate
[rust.git] / src / libproc_macro / lib.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A support library for macro authors when defining new macros.
12 //!
13 //! This library, provided by the standard distribution, provides the types
14 //! consumed in the interfaces of procedurally defined macro definitions.
15 //! Currently the primary use of this crate is to provide the ability to define
16 //! new custom derive modes through `#[proc_macro_derive]`.
17 //!
18 //! Note that this crate is intentionally very bare-bones currently. The main
19 //! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
20 //! implementations, indicating that it can only go to and come from a string.
21 //! This functionality is intended to be expanded over time as more surface
22 //! area for macro authors is stabilized.
23 //!
24 //! See [the book](../book/procedural-macros.html) for more.
25
26 #![crate_name = "proc_macro"]
27 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
28 #![crate_type = "rlib"]
29 #![crate_type = "dylib"]
30 #![deny(warnings)]
31 #![deny(missing_docs)]
32 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
33        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
34        html_root_url = "https://doc.rust-lang.org/nightly/",
35        html_playground_url = "https://play.rust-lang.org/",
36        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
37        test(no_crate_inject, attr(deny(warnings))),
38        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
39
40 #![feature(rustc_private)]
41 #![feature(staged_api)]
42 #![feature(lang_items)]
43
44 extern crate syntax;
45
46 use std::fmt;
47 use std::str::FromStr;
48
49 use syntax::errors::DiagnosticBuilder;
50 use syntax::parse;
51 use syntax::tokenstream::TokenStream as TokenStream_;
52
53 /// The main type provided by this crate, representing an abstract stream of
54 /// tokens.
55 ///
56 /// This is both the input and output of `#[proc_macro_derive]` definitions.
57 /// Currently it's required to be a list of valid Rust items, but this
58 /// restriction may be lifted in the future.
59 ///
60 /// The API of this type is intentionally bare-bones, but it'll be expanded over
61 /// time!
62 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
63 pub struct TokenStream {
64     inner: TokenStream_,
65 }
66
67 /// Error returned from `TokenStream::from_str`.
68 #[derive(Debug)]
69 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
70 pub struct LexError {
71     _inner: (),
72 }
73
74 /// Permanently unstable internal implementation details of this crate. This
75 /// should not be used.
76 ///
77 /// These methods are used by the rest of the compiler to generate instances of
78 /// `TokenStream` to hand to macro definitions, as well as consume the output.
79 ///
80 /// Note that this module is also intentionally separate from the rest of the
81 /// crate. This allows the `#[unstable]` directive below to naturally apply to
82 /// all of the contents.
83 #[unstable(feature = "proc_macro_internals", issue = "27812")]
84 #[doc(hidden)]
85 pub mod __internal {
86     use std::cell::Cell;
87     use std::rc::Rc;
88
89     use syntax::ast;
90     use syntax::ptr::P;
91     use syntax::parse::{self, token, ParseSess};
92     use syntax::tokenstream::{TokenTree, TokenStream as TokenStream_};
93
94     use super::{TokenStream, LexError};
95
96     pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
97         TokenStream {
98             inner: TokenTree::Token(item.span, token::Interpolated(Rc::new(token::NtItem(item))))
99                 .into()
100         }
101     }
102
103     pub fn token_stream_wrap(inner: TokenStream_) -> TokenStream {
104         TokenStream {
105             inner: inner
106         }
107     }
108
109     pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
110         with_parse_sess(move |sess| {
111             let mut parser = parse::stream_to_parser(sess, stream.inner);
112             let mut items = Vec::new();
113
114             while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) {
115                 items.push(item)
116             }
117
118             Ok(items)
119         })
120     }
121
122     pub fn token_stream_inner(stream: TokenStream) -> TokenStream_ {
123         stream.inner
124     }
125
126     pub trait Registry {
127         fn register_custom_derive(&mut self,
128                                   trait_name: &str,
129                                   expand: fn(TokenStream) -> TokenStream,
130                                   attributes: &[&'static str]);
131
132         fn register_attr_proc_macro(&mut self,
133                                     name: &str,
134                                     expand: fn(TokenStream, TokenStream) -> TokenStream);
135
136         fn register_bang_proc_macro(&mut self,
137                                     name: &str,
138                                     expand: fn(TokenStream) -> TokenStream);
139     }
140
141     // Emulate scoped_thread_local!() here essentially
142     thread_local! {
143         static CURRENT_SESS: Cell<*const ParseSess> = Cell::new(0 as *const _);
144     }
145
146     pub fn set_parse_sess<F, R>(sess: &ParseSess, f: F) -> R
147         where F: FnOnce() -> R
148     {
149         struct Reset { prev: *const ParseSess }
150
151         impl Drop for Reset {
152             fn drop(&mut self) {
153                 CURRENT_SESS.with(|p| p.set(self.prev));
154             }
155         }
156
157         CURRENT_SESS.with(|p| {
158             let _reset = Reset { prev: p.get() };
159             p.set(sess);
160             f()
161         })
162     }
163
164     pub fn with_parse_sess<F, R>(f: F) -> R
165         where F: FnOnce(&ParseSess) -> R
166     {
167         let p = CURRENT_SESS.with(|p| p.get());
168         assert!(!p.is_null(), "proc_macro::__internal::with_parse_sess() called \
169                                before set_parse_sess()!");
170         f(unsafe { &*p })
171     }
172 }
173
174 fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
175     err.cancel();
176     LexError { _inner: () }
177 }
178
179 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
180 impl FromStr for TokenStream {
181     type Err = LexError;
182
183     fn from_str(src: &str) -> Result<TokenStream, LexError> {
184         __internal::with_parse_sess(|sess| {
185             let src = src.to_string();
186             let name = "<proc-macro source code>".to_string();
187             let stream = parse::parse_stream_from_source_str(name, src, sess);
188             Ok(__internal::token_stream_wrap(stream))
189         })
190     }
191 }
192
193 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
194 impl fmt::Display for TokenStream {
195     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196         self.inner.fmt(f)
197     }
198 }