1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
//! # Rocket - Code Generation //! //! This crate implements the code generation portions of Rocket. This includes //! custom derives, custom attributes, and procedural macros. The documentation //! here is purely technical. The code generation facilities are documented //! thoroughly in the [Rocket programming guide](https://rocket.rs/guide). //! //! ## Custom Attributes //! //! This crate implements the following custom attributes: //! //! * **route** //! * **get** //! * **put** //! * **post** //! * **delete** //! * **head** //! * **patch** //! * **error** //! //! The grammar for all _route_ attributes, including **route**, **get**, //! **put**, **post**, **delete**, **head**, and **patch**, is defined as: //! //! <pre> //! route := METHOD? '(' ('path' '=')? path (',' kv_param)* ')' //! //! path := URI_SEG //! | DYNAMIC_PARAM //! | '?' DYNAMIC_PARAM //! | path '/' path //! (string literal) //! //! kv_param := 'rank' '=' INTEGER //! | 'format' '=' STRING //! | 'data' '=' DYNAMIC_PARAM //! //! INTEGER := isize, as defined by Rust //! STRING := UTF-8 string literal, as defined by Rust //! IDENT := Valid identifier, as defined by Rust //! //! URI_SEG := Valid HTTP URI Segment //! DYNAMIC_PARAM := '<' IDENT '..'? '>' (string literal) //! </pre> //! //! Note that the **route** attribute takes a method as its first argument, //! while the remaining do not. That is, **route** looks like: //! //! #[route(GET, path = "/hello")] //! //! while the equivalent using **get** looks like: //! //! #[get("/hello")] //! //! The syntax for the **error** attribute is: //! //! <pre> //! error := INTEGER //! </pre> //! //! ## Custom Derives //! //! This crate implements the following custom derives: //! //! * **FromForm** //! //! ## Procedural Macros //! //! This crate implements the following procedural macros: //! //! * **routes** //! * **errors** //! //! The syntax for both of these is defined as: //! //! <pre> //! macro := PATH (',' macro)* //! //! PATH := a path, as defined by Rust //! </pre> //! //! # Debugging Codegen //! //! When the `ROCKET_CODEGEN_DEBUG` environment variable is set, this crate logs //! the items it has generated to the console at compile-time. For example, you //! might run the following to build a Rocket application with codegen logging //! enabled: //! //! ``` //! ROCKET_CODEGEN_DEBUG=1 cargo build //! ``` #![crate_type = "dylib"] #![feature(quote, concat_idents, plugin_registrar, rustc_private, unicode)] #![feature(custom_attribute)] #![feature(i128_type)] #![allow(unused_attributes)] #![allow(deprecated)] #[macro_use] extern crate syntax; #[macro_use] extern crate log; extern crate syntax_ext; extern crate rustc; extern crate rustc_plugin; extern crate rocket; #[macro_use] mod utils; mod parser; mod macros; mod decorators; use std::env; use rustc_plugin::Registry; use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; const DEBUG_ENV_VAR: &'static str = "ROCKET_CODEGEN_DEBUG"; const PARAM_PREFIX: &'static str = "rocket_param_"; const ROUTE_STRUCT_PREFIX: &'static str = "static_rocket_route_info_for_"; const CATCH_STRUCT_PREFIX: &'static str = "static_rocket_catch_info_for_"; const ROUTE_FN_PREFIX: &'static str = "rocket_route_fn_"; const CATCH_FN_PREFIX: &'static str = "rocket_catch_fn_"; macro_rules! register_decorators { ($registry:expr, $($name:expr => $func:ident),+) => ( $($registry.register_syntax_extension(Symbol::intern($name), SyntaxExtension::MultiDecorator(Box::new(decorators::$func))); )+ ) } macro_rules! register_derives { ($registry:expr, $($name:expr => $func:ident),+) => ( $($registry.register_custom_derive(Symbol::intern($name), SyntaxExtension::MultiDecorator(Box::new(decorators::$func))); )+ ) } /// Compiler hook for Rust to register plugins. #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { // Enable logging early if the DEBUG_ENV_VAR is set. if env::var(DEBUG_ENV_VAR).is_ok() { ::rocket::logger::init(::rocket::LoggingLevel::Debug); } reg.register_macro("routes", macros::routes); reg.register_macro("errors", macros::errors); register_derives!(reg, "derive_FromForm" => from_form_derive ); register_decorators!(reg, "error" => error_decorator, "route" => route_decorator, "get" => get_decorator, "put" => put_decorator, "post" => post_decorator, "delete" => delete_decorator, "head" => head_decorator, "patch" => patch_decorator // TODO: Allow this once Diesel incompatibility is fixed. Fix docs too. // "options" => options_decorator ); }