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
#![cfg_attr( not(any(feature = "postgres", feature = "mysql", feature = "offline")), allow(dead_code, unused_macros, unused_imports) )] extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; type Error = Box<dyn std::error::Error>; type Result<T> = std::result::Result<T, Error>; mod common; mod database; mod derives; mod query; #[cfg(feature = "migrate")] mod migrate; #[proc_macro] pub fn expand_query(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as query::QueryMacroInput); match query::expand_input(input) { Ok(ts) => ts.into(), Err(e) => { if let Some(parse_err) = e.downcast_ref::<syn::Error>() { parse_err.to_compile_error().into() } else { let msg = e.to_string(); quote!(::std::compile_error!(#msg)).into() } } } } #[proc_macro_derive(Encode, attributes(sqlx))] pub fn derive_encode(tokenstream: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(tokenstream as syn::DeriveInput); match derives::expand_derive_encode(&input) { Ok(ts) => ts.into(), Err(e) => e.to_compile_error().into(), } } #[proc_macro_derive(Decode, attributes(sqlx))] pub fn derive_decode(tokenstream: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(tokenstream as syn::DeriveInput); match derives::expand_derive_decode(&input) { Ok(ts) => ts.into(), Err(e) => e.to_compile_error().into(), } } #[proc_macro_derive(Type, attributes(sqlx))] pub fn derive_type(tokenstream: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(tokenstream as syn::DeriveInput); match derives::expand_derive_type_encode_decode(&input) { Ok(ts) => ts.into(), Err(e) => e.to_compile_error().into(), } } #[proc_macro_derive(FromRow, attributes(sqlx))] pub fn derive_from_row(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); match derives::expand_derive_from_row(&input) { Ok(ts) => ts.into(), Err(e) => e.to_compile_error().into(), } } #[cfg(feature = "migrate")] #[proc_macro] pub fn migrate(input: TokenStream) -> TokenStream { use syn::LitStr; let input = syn::parse_macro_input!(input as LitStr); match migrate::expand_migrator_from_dir(input) { Ok(ts) => ts.into(), Err(e) => { if let Some(parse_err) = e.downcast_ref::<syn::Error>() { parse_err.to_compile_error().into() } else { let msg = e.to_string(); quote!(::std::compile_error!(#msg)).into() } } } } #[doc(hidden)] #[proc_macro_attribute] pub fn test(_attr: TokenStream, input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::ItemFn); let ret = &input.sig.output; let name = &input.sig.ident; let body = &input.block; let attrs = &input.attrs; let result = if cfg!(feature = "_rt-tokio") { quote! { #[test] #(#attrs)* fn #name() #ret { ::sqlx_rt::tokio::runtime::Builder::new_multi_thread() .enable_io() .enable_time() .build() .unwrap() .block_on(async { #body }) } } } else if cfg!(feature = "_rt-async-std") { quote! { #[test] #(#attrs)* fn #name() #ret { ::sqlx_rt::async_std::task::block_on(async { #body }) } } } else if cfg!(feature = "_rt-actix") { quote! { #[test] #(#attrs)* fn #name() #ret { ::sqlx_rt::actix_rt::System::new() .block_on(async { #body }) } } } else { panic!("one of 'runtime-actix', 'runtime-async-std' or 'runtime-tokio' features must be enabled"); }; result.into() }