use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use anyhow::Result;
use crate::Lang;
#[derive(Debug, Clone)]
pub enum TypeRef {
TypeReference(String),
Primitive(PrimitiveTypeRef),
Option(Box<TypeRef>),
Vec(Box<TypeRef>),
Set(Box<TypeRef>),
Array {
element_type: Box<TypeRef>,
size: usize,
},
Map {
key: Box<TypeRef>,
value: Box<TypeRef>,
},
}
#[derive(Debug, Clone)]
pub enum PrimitiveTypeRef {
String,
Bool,
I8,
I16,
I32,
I64,
I128,
ISize,
U8,
U16,
U32,
U64,
U128,
USize,
F32,
F64,
}
#[derive(Clone, Debug)]
pub struct TypeGenSkip {
pub hack: bool,
pub flow: bool,
pub typescript: bool,
}
#[derive(Clone, Debug)]
pub struct TypeGenOverrides {
pub hack: Option<&'static str>,
pub flow: Option<&'static str>,
pub typescript: Option<&'static str>,
}
#[derive(Debug, Clone)]
pub struct TypeGenGeneratedType {
pub original_type_name: String,
pub docs: Option<String>,
pub file_path: PathBuf,
pub declaration: TypeGenDecl,
pub overrides: Option<TypeGenOverrides>,
pub skip: Option<TypeGenSkip>,
}
impl TypeGenGeneratedType {
pub fn write_to_file(&self) -> Result<()> {
let enabled = std::env::var("TYPEGEN").unwrap_or_default() == "1";
if !enabled {
return Ok(());
}
let config = crate::config::get_config_for_file(&self.file_path)?;
if let Some(flow_file) = config.make_file(self.clone(), Lang::Flow)? {
flow_file.write()?;
}
if let Some(ts_file) = config.make_file(self.clone(), Lang::TypeScript)? {
ts_file.write()?;
}
if let Some(hack_file) = config.make_file(self.clone(), Lang::Hack)? {
hack_file.write()?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub enum TypeGenDecl {
StructDecl(StructDecl),
TupleStructDecl(TupleStructDecl),
EnumDecl(EnumDecl),
Null,
}
#[derive(Debug, Clone)]
pub struct StructDecl {
pub fields: Vec<FieldDeclaration>,
}
#[derive(Debug, Clone)]
pub struct TupleStructDecl {
pub fields: Vec<TypeRef>,
}
#[derive(Debug, Clone)]
pub struct EnumDecl {
pub variants: Vec<EnumVariant>,
}
#[derive(Debug, Clone)]
pub struct FieldDeclaration {
pub field_name: String,
pub type_ref: TypeRef,
pub docs: Option<String>,
}
#[derive(Debug, Clone)]
pub enum EnumVariant {
Unit { name: String, docs: Option<String> },
Newtype {
name: String,
docs: Option<String>,
field_type: TypeRef,
},
Tuple {
name: String,
docs: Option<String>,
fields: Vec<TypeRef>,
},
Struct {
name: String,
docs: Option<String>,
fields: Vec<FieldDeclaration>,
},
}
pub trait TypeGenTypeRefTrait {
fn type_ref() -> TypeRef;
}
pub trait TypeGenDeclTrait: TypeGenTypeRefTrait {
fn to_type_decl() -> TypeGenGeneratedType;
}
impl TypeGenTypeRefTrait for String {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::String)
}
}
impl TypeGenTypeRefTrait for str {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::String)
}
}
impl TypeGenTypeRefTrait for bool {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::Bool)
}
}
impl TypeGenTypeRefTrait for i8 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::I8)
}
}
impl TypeGenTypeRefTrait for i16 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::I16)
}
}
impl TypeGenTypeRefTrait for i32 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::I32)
}
}
impl TypeGenTypeRefTrait for i64 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::I64)
}
}
impl TypeGenTypeRefTrait for i128 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::I128)
}
}
impl TypeGenTypeRefTrait for isize {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::ISize)
}
}
impl TypeGenTypeRefTrait for u8 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::U8)
}
}
impl TypeGenTypeRefTrait for u16 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::U16)
}
}
impl TypeGenTypeRefTrait for u32 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::U32)
}
}
impl TypeGenTypeRefTrait for u64 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::U64)
}
}
impl TypeGenTypeRefTrait for u128 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::U128)
}
}
impl TypeGenTypeRefTrait for usize {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::USize)
}
}
impl TypeGenTypeRefTrait for f32 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::F32)
}
}
impl TypeGenTypeRefTrait for f64 {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::F64)
}
}
impl TypeGenTypeRefTrait for char {
fn type_ref() -> TypeRef {
TypeRef::Primitive(PrimitiveTypeRef::String) }
}
impl<T: TypeGenTypeRefTrait> TypeGenTypeRefTrait for Vec<T> {
fn type_ref() -> TypeRef {
TypeRef::Vec(Box::new(T::type_ref()))
}
}
impl<T: TypeGenTypeRefTrait> TypeGenTypeRefTrait for BTreeSet<T> {
fn type_ref() -> TypeRef {
TypeRef::Set(Box::new(T::type_ref()))
}
}
impl<T: TypeGenTypeRefTrait> TypeGenTypeRefTrait for Option<T> {
fn type_ref() -> TypeRef {
TypeRef::Option(Box::new(T::type_ref()))
}
}
impl<T: TypeGenTypeRefTrait> TypeGenTypeRefTrait for Arc<T> {
fn type_ref() -> TypeRef {
T::type_ref()
}
}
impl<K: TypeGenTypeRefTrait, V: TypeGenTypeRefTrait> TypeGenTypeRefTrait for HashMap<K, V> {
fn type_ref() -> TypeRef {
TypeRef::Map {
key: Box::new(K::type_ref()),
value: Box::new(V::type_ref()),
}
}
}
impl<K: TypeGenTypeRefTrait, V: TypeGenTypeRefTrait> TypeGenTypeRefTrait for BTreeMap<K, V> {
fn type_ref() -> TypeRef {
TypeRef::Map {
key: Box::new(K::type_ref()),
value: Box::new(V::type_ref()),
}
}
}
impl<T: TypeGenTypeRefTrait, const N: usize> TypeGenTypeRefTrait for [T; N] {
fn type_ref() -> TypeRef {
TypeRef::Array {
element_type: Box::new(T::type_ref()),
size: N,
}
}
}