blob: 057a03bec7074e7389b16f81b36fe06f1d774515 [file] [log] [blame]
pub use diagnostic_shim::{Diagnostic, DiagnosticShim, EmitErrorExt};
use meta::MetaItem;
use proc_macro2::{Span, TokenStream};
use syn::{Data, DeriveInput, GenericArgument, Type};
pub fn wrap_in_dummy_mod(item: TokenStream) -> TokenStream {
quote! {
#[allow(unused_imports)]
const _: () = {
// This import is not actually redundant. When using diesel_derives
// inside of diesel, `diesel` doesn't exist as an extern crate, and
// to work around that it contains a private
// `mod diesel { pub use super::*; }` that this import will then
// refer to. In all other cases, this imports refers to the extern
// crate diesel.
use diesel;
#item
};
}
}
pub fn inner_of_option_ty(ty: &Type) -> &Type {
option_ty_arg(ty).unwrap_or(ty)
}
pub fn is_option_ty(ty: &Type) -> bool {
option_ty_arg(ty).is_some()
}
fn option_ty_arg(ty: &Type) -> Option<&Type> {
use syn::PathArguments::AngleBracketed;
match *ty {
Type::Path(ref ty) => {
let last_segment = ty.path.segments.iter().last().unwrap();
match last_segment.arguments {
AngleBracketed(ref args) if last_segment.ident == "Option" => {
match args.args.iter().last() {
Some(&GenericArgument::Type(ref ty)) => Some(ty),
_ => None,
}
}
_ => None,
}
}
_ => None,
}
}
pub fn ty_for_foreign_derive(item: &DeriveInput, flags: &MetaItem) -> Result<Type, Diagnostic> {
if flags.has_flag("foreign_derive") {
match item.data {
Data::Struct(ref body) => match body.fields.iter().next() {
Some(field) => Ok(field.ty.clone()),
None => Err(flags
.span()
.error("foreign_derive requires at least one field")),
},
_ => Err(flags
.span()
.error("foreign_derive can only be used with structs")),
}
} else {
let ident = &item.ident;
let (_, ty_generics, ..) = item.generics.split_for_impl();
Ok(parse_quote!(#ident #ty_generics))
}
}
pub fn fix_span(maybe_bad_span: Span, mut fallback: Span) -> Span {
let bad_span_debug = "#0 bytes(0..0)";
if format!("{:?}", fallback) == bad_span_debug {
// On recent rust nightlies, even our fallback span is bad.
fallback = Span::call_site();
}
if format!("{:?}", maybe_bad_span) == bad_span_debug {
fallback
} else {
maybe_bad_span
}
}