2020-06-20 20:28:50 +00:00
/*
* meli -
*
* Copyright Manos Pitsidianakis
*
* This file is part of meli .
*
* meli is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* meli is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with meli . If not , see < http ://www.gnu.org/licenses/>.
* /
2023-04-30 16:39:41 +00:00
use std ::{
fs ::File ,
io ::prelude ::* ,
process ::{ Command , Stdio } ,
} ;
2020-06-20 20:28:50 +00:00
use quote ::{ format_ident , quote } ;
2023-06-01 08:56:49 +00:00
extern crate proc_macro ;
2020-06-20 20:28:50 +00:00
// Write ConfigStructOverride to overrides.rs
pub fn override_derive ( filenames : & [ ( & str , & str ) ] ) {
let mut output_file =
File ::create ( " src/conf/overrides.rs " ) . expect ( " Unable to open output file " ) ;
2023-04-30 16:39:41 +00:00
let mut output_string = r ##" // @generated
/*
2020-06-20 20:28:50 +00:00
* meli - conf / overrides . rs
*
* Copyright 2020 Manos Pitsidianakis
*
* This file is part of meli .
*
* meli is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* meli is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with meli . If not , see < http ://www.gnu.org/licenses/>.
* /
2022-08-25 12:17:18 +00:00
#![ allow(clippy::derivable_impls) ]
//! This module is automatically generated by config_macros.rs.
2023-05-28 14:40:50 +00:00
2020-06-20 20:28:50 +00:00
use super ::* ;
2023-05-28 14:40:50 +00:00
use melib ::HeaderName ;
2020-06-20 20:28:50 +00:00
" ##
. to_string ( ) ;
' file_loop : for ( filename , ident ) in filenames {
println! ( " cargo:rerun-if-changed= {} " , filename ) ;
2023-04-30 16:39:41 +00:00
let mut file = File ::open ( filename )
2020-08-25 13:39:12 +00:00
. unwrap_or_else ( | err | panic! ( " Unable to open file ` {} ` {} " , filename , err ) ) ;
2020-06-20 20:28:50 +00:00
let mut src = String ::new ( ) ;
file . read_to_string ( & mut src ) . expect ( " Unable to read file " ) ;
let syntax = syn ::parse_file ( & src ) . expect ( " Unable to parse file " ) ;
if syntax . items . iter ( ) . any ( | item | {
if let syn ::Item ::Struct ( s ) = item {
if s . ident . to_string ( ) . ends_with ( " Override " ) {
println! ( " ident {} exists, skipping {} " , ident , filename ) ;
return true ;
}
}
false
} ) {
continue 'file_loop ;
}
for item in syntax . items . iter ( ) {
if let syn ::Item ::Struct ( s ) = item {
if s . ident ! = ident {
continue ;
}
if s . ident . to_string ( ) . ends_with ( " Override " ) {
unreachable! ( ) ;
}
let override_ident : syn ::Ident = format_ident! ( " {}Override " , s . ident ) ;
let mut field_tokentrees = vec! [ ] ;
2020-10-10 21:32:55 +00:00
let mut attrs_tokens = vec! [ ] ;
for attr in & s . attrs {
if let Ok ( syn ::Meta ::List ( ml ) ) = attr . parse_meta ( ) {
if ml . path . get_ident ( ) . is_some ( ) & & ml . path . get_ident ( ) . unwrap ( ) = = " cfg " {
attrs_tokens . push ( attr ) ;
}
}
}
2020-06-20 20:28:50 +00:00
let mut field_idents = vec! [ ] ;
for f in & s . fields {
let ident = & f . ident ;
let ty = & f . ty ;
let attrs = f
. attrs
. iter ( )
. filter_map ( | f | {
let mut new_attr = f . clone ( ) ;
2023-06-01 08:56:49 +00:00
if let proc_macro2 ::TokenTree ::Group ( g ) =
2020-06-20 20:28:50 +00:00
f . tokens . clone ( ) . into_iter ( ) . next ( ) . unwrap ( )
{
let attr_inner_value = f . tokens . to_string ( ) ;
if ! attr_inner_value . starts_with ( " ( default " )
& & ! attr_inner_value . starts_with ( " ( default = " )
2020-09-13 13:34:07 +00:00
& & ! attr_inner_value . starts_with ( " (default " )
& & ! attr_inner_value . starts_with ( " (default = " )
2020-06-20 20:28:50 +00:00
{
2020-07-08 09:04:53 +00:00
return Some ( new_attr ) ;
2020-06-20 20:28:50 +00:00
}
2020-09-13 13:34:07 +00:00
if attr_inner_value . starts_with ( " ( default = " )
| | attr_inner_value . starts_with ( " (default = " )
{
2020-07-13 15:49:27 +00:00
let rest = g . stream ( ) . into_iter ( ) . skip ( 4 ) ;
2020-06-20 20:28:50 +00:00
new_attr . tokens = quote! { ( #( #rest ) * ) } ;
2020-09-13 13:34:07 +00:00
match new_attr . tokens . to_string ( ) . as_str ( ) {
" ( ) " | " () " = > {
return None ;
}
_ = > { }
2020-06-20 20:28:50 +00:00
}
2020-09-13 13:34:07 +00:00
} else if attr_inner_value . starts_with ( " ( default " )
| | attr_inner_value . starts_with ( " (default " )
{
2020-07-13 15:49:27 +00:00
let rest = g . stream ( ) . into_iter ( ) . skip ( 2 ) ;
2020-06-20 20:28:50 +00:00
new_attr . tokens = quote! { ( #( #rest ) * ) } ;
2020-09-13 13:34:07 +00:00
match new_attr . tokens . to_string ( ) . as_str ( ) {
" ( ) " | " () " = > {
return None ;
}
_ = > { }
2020-06-20 20:28:50 +00:00
}
}
}
Some ( new_attr )
} )
. collect ::< Vec < _ > > ( ) ;
let t = quote! {
#( #attrs ) *
#[ serde(default) ]
pub #ident : Option < #ty >
} ;
field_idents . push ( ident ) ;
field_tokentrees . push ( t ) ;
}
//let fields = &s.fields;
let literal_struct = quote! {
2020-10-10 21:32:55 +00:00
#( #attrs_tokens ) *
2020-06-20 20:28:50 +00:00
#[ derive(Debug, Serialize, Deserialize, Clone) ]
2020-08-03 19:53:06 +00:00
#[ serde(deny_unknown_fields) ]
2020-06-20 20:28:50 +00:00
pub struct #override_ident {
#( #field_tokentrees ) , *
}
2020-10-10 21:32:55 +00:00
#( #attrs_tokens ) *
2020-06-20 20:28:50 +00:00
impl Default for #override_ident {
fn default ( ) -> Self {
#override_ident {
#( #field_idents : None ) , *
}
}
}
} ;
2020-08-25 13:39:12 +00:00
output_string . push_str ( & literal_struct . to_string ( ) ) ;
2020-06-20 20:28:50 +00:00
output_string . push_str ( " \n \n " ) ;
}
}
}
2020-06-21 09:23:01 +00:00
let rustfmt_closure = move | output_file : & mut File , output_string : & str | {
let mut rustfmt = Command ::new ( " rustfmt " )
. stdin ( Stdio ::piped ( ) )
. stdout ( Stdio ::piped ( ) )
. stderr ( Stdio ::piped ( ) )
. spawn ( )
. map_err ( | err | format! ( " failed to execute rustfmt {} " , err ) ) ? ;
{
// limited borrow of stdin
let stdin = rustfmt
. stdin
. as_mut ( )
. ok_or ( " failed to get rustfmt stdin " ) ? ;
stdin
. write_all ( output_string . as_bytes ( ) )
. map_err ( | err | format! ( " failed to write to rustfmt stdin {} " , err ) ) ? ;
}
2020-06-20 20:28:50 +00:00
2020-06-21 09:23:01 +00:00
let output = rustfmt
. wait_with_output ( )
. map_err ( | err | format! ( " failed to wait on rustfmt child {} " , err ) ) ? ;
if ! output . stderr . is_empty ( ) {
return Err ( format! (
" rustfmt invocation replied with: `{}` " ,
String ::from_utf8_lossy ( & output . stderr )
) ) ;
}
2020-06-20 20:28:50 +00:00
2020-06-21 09:23:01 +00:00
output_file
. write_all ( & output . stdout )
. expect ( " failed to write to src/conf/overrides.rs " ) ;
Ok ( ( ) )
} ;
if let Err ( err ) = rustfmt_closure ( & mut output_file , & output_string ) {
println! ( " Tried rustfmt on overrides module, got error: {} " , err ) ;
output_file . write_all ( output_string . as_bytes ( ) ) . unwrap ( ) ;
}
2020-06-20 20:28:50 +00:00
}