From 569da533a149c7c82569784babc5529c17746ed2 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 7 Jul 2021 14:14:37 +0800 Subject: [PATCH] config event template --- .idea/inspectionProfiles/Project_Default.xml | 10 ++ rust-lib/dart-ffi/Flowy.toml | 3 +- rust-lib/flowy-ast/src/attr.rs | 74 ++++++++++- rust-lib/flowy-ast/src/event_ast.rs | 35 +++++ rust-lib/flowy-ast/src/lib.rs | 3 +- rust-lib/flowy-ast/src/symbol.rs | 5 + rust-lib/flowy-user/Flowy.toml | 3 +- scripts/flowy-tool/src/config/mod.rs | 1 + .../flowy-tool/src/dart_event/dart_event.rs | 122 ++++++++++++++++++ .../src/dart_event/event_template.rs | 25 ++++ .../src/dart_event/event_template.tera | 0 scripts/flowy-tool/src/dart_event/mod.rs | 4 + scripts/flowy-tool/src/main.rs | 27 ++++ scripts/flowy-tool/src/proto/ast.rs | 13 +- scripts/flowy-tool/src/proto/helper.rs | 26 ---- scripts/flowy-tool/src/proto/mod.rs | 3 +- scripts/flowy-tool/src/proto/proto_gen.rs | 28 +--- .../proto/{crate_info.rs => proto_info.rs} | 108 +++++++--------- .../proto/template/derive_meta/derive_meta.rs | 4 +- scripts/flowy-tool/src/util/crate_config.rs | 38 ++++++ scripts/flowy-tool/src/util/file.rs | 52 +++++++- scripts/flowy-tool/src/util/mod.rs | 2 + 22 files changed, 456 insertions(+), 130 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 rust-lib/flowy-ast/src/event_ast.rs create mode 100644 scripts/flowy-tool/src/dart_event/dart_event.rs create mode 100644 scripts/flowy-tool/src/dart_event/event_template.rs create mode 100644 scripts/flowy-tool/src/dart_event/event_template.tera create mode 100644 scripts/flowy-tool/src/dart_event/mod.rs delete mode 100644 scripts/flowy-tool/src/proto/helper.rs rename scripts/flowy-tool/src/proto/{crate_info.rs => proto_info.rs} (60%) create mode 100644 scripts/flowy-tool/src/util/crate_config.rs diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..e29848431e --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/rust-lib/dart-ffi/Flowy.toml b/rust-lib/dart-ffi/Flowy.toml index 0c0da27e6a..41fea48238 100644 --- a/rust-lib/dart-ffi/Flowy.toml +++ b/rust-lib/dart-ffi/Flowy.toml @@ -1 +1,2 @@ -proto_crates = ["src/model"] \ No newline at end of file +proto_crates = ["src/model"] +event_files = [] \ No newline at end of file diff --git a/rust-lib/flowy-ast/src/attr.rs b/rust-lib/flowy-ast/src/attr.rs index 7695686f22..db841b7523 100644 --- a/rust-lib/flowy-ast/src/attr.rs +++ b/rust-lib/flowy-ast/src/attr.rs @@ -255,14 +255,22 @@ pub enum Default { Path(syn::ExprPath), } +#[derive(Debug, Clone)] +pub struct EventAttrs { + input: Option, + output: Option, + pub ignore: bool, +} + #[derive(Debug, Clone)] pub struct ASTEnumAttrVariant { pub name: String, pub value: String, + pub event_attrs: EventAttrs, } impl ASTEnumAttrVariant { - pub fn from_ast(_cx: &Ctxt, variant: &syn::Variant) -> Self { + pub fn from_ast(ctxt: &Ctxt, variant: &syn::Variant) -> Self { let name = variant.ident.to_string(); let mut value = String::new(); if variant.discriminant.is_some() { @@ -278,8 +286,70 @@ impl ASTEnumAttrVariant { _ => {}, } } - ASTEnumAttrVariant { name, value } + let mut event_attrs = EventAttrs { + input: None, + output: None, + ignore: false, + }; + variant.attrs.iter().for_each(|attr| match get_meta_items(ctxt, attr) { + Ok(meta_items) => { + for meta_item in meta_items { + match &meta_item { + Meta(NameValue(name_value)) => { + if name_value.path == EVENT_INPUT { + if let syn::Lit::Str(s) = &name_value.lit { + let input_type = parse_lit_str(s) + .map_err(|_| { + ctxt.error_spanned_by( + s, + format!("failed to parse request deserializer {:?}", s.value()), + ) + }) + .unwrap(); + event_attrs.input = Some(input_type); + } + } + + if name_value.path == EVENT_OUTPUT { + if let syn::Lit::Str(s) = &name_value.lit { + let output_type = parse_lit_str(s) + .map_err(|_| { + ctxt.error_spanned_by( + s, + format!("failed to parse response deserializer {:?}", s.value()), + ) + }) + .unwrap(); + event_attrs.output = Some(output_type); + } + } + }, + Meta(Path(word)) => { + if word == EVENT_IGNORE && attr.path == EVENT { + event_attrs.ignore = true; + } + }, + Lit(s) => { + ctxt.error_spanned_by(s, "unexpected type in cqrs container attribute"); + }, + _ => { + ctxt.error_spanned_by(meta_item, "unexpected type in cqrs container attribute"); + }, + } + } + }, + Err(_) => {}, + }); + ASTEnumAttrVariant { + name, + value, + event_attrs, + } } + + pub fn event_input(&self) -> Option { self.event_attrs.input.clone() } + + pub fn event_output(&self) -> Option { self.event_attrs.output.clone() } } pub fn get_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result, ()> { diff --git a/rust-lib/flowy-ast/src/event_ast.rs b/rust-lib/flowy-ast/src/event_ast.rs new file mode 100644 index 0000000000..3f5ae9ad11 --- /dev/null +++ b/rust-lib/flowy-ast/src/event_ast.rs @@ -0,0 +1,35 @@ +use crate::ASTEnumAttrVariant; + +pub struct EventASTContext { + pub event: syn::Ident, + pub event_ty: syn::Ident, + pub event_request_struct: syn::Ident, + pub event_input: Option, + pub event_output: Option, +} + +impl EventASTContext { + pub fn from(variant: &ASTEnumAttrVariant) -> EventASTContext { + let command_name = variant.name.clone(); + if command_name.is_empty() { + panic!("Invalid command name: {}", variant.name); + } + + let event = format_ident!("{}", &command_name); + let splits = command_name.split("_").collect::>(); + + let event_ty = format_ident!("UserEvent"); + let event_request_struct = format_ident!("{}Event", &splits.join("")); + + let event_input = variant.event_input(); + let event_output = variant.event_output(); + + EventASTContext { + event, + event_ty, + event_request_struct, + event_input, + event_output, + } + } +} diff --git a/rust-lib/flowy-ast/src/lib.rs b/rust-lib/flowy-ast/src/lib.rs index a0d730709f..4ef342f7b9 100644 --- a/rust-lib/flowy-ast/src/lib.rs +++ b/rust-lib/flowy-ast/src/lib.rs @@ -7,9 +7,10 @@ extern crate quote; mod ast; mod attr; mod ctxt; + +pub mod event_ast; pub mod symbol; pub mod ty_ext; - pub use self::{symbol::*, ty_ext::*}; pub use ast::*; pub use attr::*; diff --git a/rust-lib/flowy-ast/src/symbol.rs b/rust-lib/flowy-ast/src/symbol.rs index 86af7d15b3..d80d0feab7 100644 --- a/rust-lib/flowy-ast/src/symbol.rs +++ b/rust-lib/flowy-ast/src/symbol.rs @@ -14,6 +14,11 @@ pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing"); //#[pb(skip_ser pub const PB_STRUCT: Symbol = Symbol("struct"); //#[pb(struct="some struct")] pub const PB_ENUM: Symbol = Symbol("enum"); //#[pb(enum="some enum")] +pub const EVENT_INPUT: Symbol = Symbol("input"); +pub const EVENT_OUTPUT: Symbol = Symbol("output"); +pub const EVENT_IGNORE: Symbol = Symbol("ignore"); +pub const EVENT: Symbol = Symbol("event"); + impl PartialEq for Ident { fn eq(&self, word: &Symbol) -> bool { self == word.0 } } diff --git a/rust-lib/flowy-user/Flowy.toml b/rust-lib/flowy-user/Flowy.toml index a232931702..dfa44fb6e4 100644 --- a/rust-lib/flowy-user/Flowy.toml +++ b/rust-lib/flowy-user/Flowy.toml @@ -1,2 +1,3 @@ -proto_crates = ["src/domain"] \ No newline at end of file +proto_crates = ["src/domain"] +event_files = ["src/module.rs"] \ No newline at end of file diff --git a/scripts/flowy-tool/src/config/mod.rs b/scripts/flowy-tool/src/config/mod.rs index 05ed6bcaf9..941273fa59 100644 --- a/scripts/flowy-tool/src/config/mod.rs +++ b/scripts/flowy-tool/src/config/mod.rs @@ -3,6 +3,7 @@ use std::fs; #[derive(serde::Deserialize)] pub struct FlowyConfig { pub proto_crates: Vec, + pub event_files: Vec, } impl FlowyConfig { diff --git a/scripts/flowy-tool/src/dart_event/dart_event.rs b/scripts/flowy-tool/src/dart_event/dart_event.rs new file mode 100644 index 0000000000..ed00ff8329 --- /dev/null +++ b/scripts/flowy-tool/src/dart_event/dart_event.rs @@ -0,0 +1,122 @@ +use super::event_template::*; + +use crate::util::*; +use flowy_ast::{event_ast::*, *}; +use syn::Item; +use walkdir::WalkDir; + +pub struct DartEventCodeGen { + pub rust_source: String, + pub output_dir: String, +} + +impl DartEventCodeGen { + pub fn gen(&self) { + let event_crates = parse_dart_event_files(self.rust_source.as_ref()); + let event_ast = event_crates + .iter() + .map(|event_crate| parse_event_crate(event_crate)) + .flatten() + .collect::>(); + + let event_render_ctx = ast_to_event_render_ctx(event_ast.as_ref()); + + let mut render_result = String::new(); + for (index, render_ctx) in event_render_ctx.into_iter().enumerate() { + let mut event_template = EventTemplate::new(); + + match event_template.render(render_ctx, index) { + Some(content) => render_result.push_str(content.as_ref()), + None => {} + } + } + + save_content_to_file_with_diff_prompt( + render_result.as_ref(), + self.output_dir.as_str(), + true, + ); + } +} + +pub struct DartEventCrate { + crate_path: String, + crate_name: String, + event_files: Vec, +} + +impl DartEventCrate { + pub fn from_config(config: &CrateConfig) -> Self { + DartEventCrate { + crate_path: config.crate_path.clone(), + crate_name: config.folder_name.clone(), + event_files: config.flowy_config.event_files.clone(), + } + } +} + +pub fn parse_dart_event_files(root: &str) -> Vec { + WalkDir::new(root) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .filter_map(|e| e.ok()) + .filter(|e| is_crate_dir(e)) + .flat_map(|e| parse_crate_config_from(&e)) + .map(|crate_config| DartEventCrate::from_config(&crate_config)) + .collect::>() +} + +pub fn parse_event_crate(event_crate: &DartEventCrate) -> Vec { + event_crate + .event_files + .iter() + .map(|event_file| { + let file_path = format!("{}/{}", event_crate.crate_path, event_file); + let file_content = read_file(file_path.as_ref()).unwrap(); + let ast = syn::parse_file(file_content.as_ref()).expect("Unable to parse file"); + + ast.items + .iter() + .map(|item| match item { + Item::Enum(item_enum) => { + let ctxt = Ctxt::new(); + let attrs = flowy_ast::enum_from_ast(&ctxt, &item_enum.variants); + ctxt.check().unwrap(); + attrs + .iter() + .filter(|attr| attr.attrs.event_attrs.ignore == false) + .enumerate() + .map(|(_index, attr)| EventASTContext::from(&attr.attrs)) + .collect::>() + } + _ => vec![], + }) + .flatten() + .collect::>() + }) + .flatten() + .collect::>() +} + +pub fn ast_to_event_render_ctx(ast: &Vec) -> Vec { + ast.iter() + .map(|event_ast| EventRenderContext { + input_deserializer: event_ast + .event_input + .as_ref() + .unwrap() + .get_ident() + .unwrap() + .to_string(), + output_deserializer: event_ast + .event_output + .as_ref() + .unwrap() + .get_ident() + .unwrap() + .to_string(), + event: event_ast.event.to_string(), + event_ty: event_ast.event_ty.to_string(), + }) + .collect::>() +} diff --git a/scripts/flowy-tool/src/dart_event/event_template.rs b/scripts/flowy-tool/src/dart_event/event_template.rs new file mode 100644 index 0000000000..0526b7025b --- /dev/null +++ b/scripts/flowy-tool/src/dart_event/event_template.rs @@ -0,0 +1,25 @@ +use tera::Context; + +pub struct EventTemplate { + tera_context: Context, +} + +pub struct EventRenderContext { + pub input_deserializer: String, + pub output_deserializer: String, + pub event: String, + pub event_ty: String, +} + +#[allow(dead_code)] +impl EventTemplate { + pub fn new() -> Self { + return EventTemplate { + tera_context: Context::new(), + }; + } + + pub fn render(&mut self, _render_context: EventRenderContext, _index: usize) -> Option { + None + } +} diff --git a/scripts/flowy-tool/src/dart_event/event_template.tera b/scripts/flowy-tool/src/dart_event/event_template.tera new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/flowy-tool/src/dart_event/mod.rs b/scripts/flowy-tool/src/dart_event/mod.rs new file mode 100644 index 0000000000..05ef337b50 --- /dev/null +++ b/scripts/flowy-tool/src/dart_event/mod.rs @@ -0,0 +1,4 @@ +mod dart_event; +mod event_template; + +pub use dart_event::*; diff --git a/scripts/flowy-tool/src/main.rs b/scripts/flowy-tool/src/main.rs index 85e592268c..63b1311af5 100644 --- a/scripts/flowy-tool/src/main.rs +++ b/scripts/flowy-tool/src/main.rs @@ -1,4 +1,5 @@ mod config; +mod dart_event; mod proto; mod util; @@ -22,6 +23,17 @@ fn main() { .build() .gen(); } + + if let Some(ref matches) = matches.subcommand_matches("dart-event") { + let rust_source = matches.value_of("rust_source").unwrap().to_string(); + let output_dir = matches.value_of("output").unwrap().to_string(); + + let code_gen = dart_event::DartEventCodeGen { + rust_source, + output_dir, + }; + code_gen.gen(); + } } pub fn app<'a, 'b>() -> App<'a, 'b> { @@ -49,6 +61,21 @@ pub fn app<'a, 'b>() -> App<'a, 'b> { .long("flutter_package_lib") .value_name("DIRECTORY"), ), + ) + .subcommand( + App::new("dart-event") + .about("Generate the codes that sending events from rust ast") + .arg( + Arg::with_name("rust_source") + .long("rust_source") + .value_name("DIRECTORY") + .help("Directory of the cargo workspace"), + ) + .arg( + Arg::with_name("output") + .long("output") + .value_name("DIRECTORY"), + ), ); app diff --git a/scripts/flowy-tool/src/proto/ast.rs b/scripts/flowy-tool/src/proto/ast.rs index 4eed801d08..6de2be51d8 100644 --- a/scripts/flowy-tool/src/proto/ast.rs +++ b/scripts/flowy-tool/src/proto/ast.rs @@ -1,5 +1,4 @@ -use crate::proto::crate_info::*; -use crate::proto::helper::*; +use crate::proto::proto_info::*; use crate::proto::template::{EnumTemplate, StructTemplate}; use crate::util::*; use fancy_regex::Regex; @@ -16,19 +15,19 @@ pub fn parse_crate_protobuf(root: &str) -> Vec { .map(|crate_info| { let proto_output_dir = crate_info.proto_file_output_dir(); let files = crate_info - .proto_crate_paths + .proto_paths .iter() .map(|proto_crate_path| parse_files_protobuf(proto_crate_path, &proto_output_dir)) .flatten() - .collect::>(); + .collect::>(); CrateProtoInfo::from_crate_info(crate_info, files) }) .collect::>() } -fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec { - let mut gen_proto_vec: Vec = vec![]; +fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec { + let mut gen_proto_vec: Vec = vec![]; // file_stem https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem for (path, file_name) in WalkDir::new(proto_crate_path) .into_iter() @@ -78,7 +77,7 @@ fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec bool { - let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string(); - cargo == "Cargo".to_string() -} - -pub fn is_proto_file(e: &walkdir::DirEntry) -> bool { - if e.path().extension().is_none() { - return false; - } - let ext = e.path().extension().unwrap().to_str().unwrap().to_string(); - ext == "proto".to_string() -} - -pub fn is_hidden(entry: &walkdir::DirEntry) -> bool { - entry - .file_name() - .to_str() - .map(|s| s.starts_with(".")) - .unwrap_or(false) -} - -pub fn create_dir_if_not_exist(dir: &str) { - if !std::path::Path::new(&dir).exists() { - std::fs::create_dir_all(&dir).unwrap(); - } -} diff --git a/scripts/flowy-tool/src/proto/mod.rs b/scripts/flowy-tool/src/proto/mod.rs index c877ba19bc..66f984120a 100644 --- a/scripts/flowy-tool/src/proto/mod.rs +++ b/scripts/flowy-tool/src/proto/mod.rs @@ -1,8 +1,7 @@ mod ast; mod builder; -mod crate_info; -mod helper; mod proto_gen; +mod proto_info; mod template; pub use builder::*; diff --git a/scripts/flowy-tool/src/proto/proto_gen.rs b/scripts/flowy-tool/src/proto/proto_gen.rs index 1bb4bb187f..01b8bd70f3 100644 --- a/scripts/flowy-tool/src/proto/proto_gen.rs +++ b/scripts/flowy-tool/src/proto/proto_gen.rs @@ -1,9 +1,7 @@ use crate::proto::ast::*; -use crate::proto::crate_info::*; -use crate::proto::helper::*; +use crate::proto::proto_info::*; use crate::{proto::template::*, util::*}; use std::{fs::OpenOptions, io::Write}; -use walkdir::WalkDir; pub struct ProtoGen { pub(crate) rust_source_dir: String, @@ -77,7 +75,7 @@ fn write_flutter_protobuf_package_mod_file( package_info: &FlutterProtobufInfo, ) { let mod_path = package_info.mod_file_path(); - let model_dir = package_info.model_dir(); + let _model_dir = package_info.model_dir(); match OpenOptions::new() .create(true) .write(true) @@ -90,7 +88,7 @@ fn write_flutter_protobuf_package_mod_file( mod_file_content.push_str("// Auto-generated, do not edit \n"); for crate_info in crate_infos { - let mod_path = crate_info.inner.proto_model_mod_file(); + let _mod_path = crate_info.inner.proto_model_mod_file(); walk_dir( crate_info.inner.proto_file_output_dir().as_ref(), |e| e.file_type().is_dir() == false, @@ -151,23 +149,3 @@ fn run_flutter_protoc(crate_infos: &Vec, package_info: &FlutterP ); } } - -fn walk_dir(dir: &str, filter: F2, mut path_and_name: F1) -where - F1: FnMut(String, String), - F2: Fn(&walkdir::DirEntry) -> bool, -{ - for (path, name) in WalkDir::new(dir) - .into_iter() - .filter_map(|e| e.ok()) - .filter(|e| filter(e)) - .map(|e| { - ( - e.path().to_str().unwrap().to_string(), - e.path().file_stem().unwrap().to_str().unwrap().to_string(), - ) - }) - { - path_and_name(path, name); - } -} diff --git a/scripts/flowy-tool/src/proto/crate_info.rs b/scripts/flowy-tool/src/proto/proto_info.rs similarity index 60% rename from scripts/flowy-tool/src/proto/crate_info.rs rename to scripts/flowy-tool/src/proto/proto_info.rs index ec55256494..c324efab56 100644 --- a/scripts/flowy-tool/src/proto/crate_info.rs +++ b/scripts/flowy-tool/src/proto/proto_info.rs @@ -1,45 +1,15 @@ -use crate::config::FlowyConfig; -use crate::proto::helper::*; +use crate::util::*; use std::fs::OpenOptions; use std::io::Write; use walkdir::WalkDir; -#[derive(Clone)] -pub struct CrateInfo { - pub crate_folder_name: String, - pub proto_crate_paths: Vec, - pub crate_path: String, -} - pub struct CrateProtoInfo { - pub files: Vec, - pub inner: CrateInfo, -} - -impl CrateInfo { - fn protobuf_crate_name(&self) -> String { - format!("{}/src/protobuf", self.crate_path) - } - - pub fn proto_file_output_dir(&self) -> String { - let dir = format!("{}/proto", self.protobuf_crate_name()); - create_dir_if_not_exist(dir.as_ref()); - dir - } - - pub fn proto_struct_output_dir(&self) -> String { - let dir = format!("{}/model", self.protobuf_crate_name()); - create_dir_if_not_exist(dir.as_ref()); - dir - } - - pub fn proto_model_mod_file(&self) -> String { - format!("{}/mod.rs", self.proto_struct_output_dir()) - } + pub files: Vec, + pub inner: ProtobufCrate, } impl CrateProtoInfo { - pub fn from_crate_info(inner: CrateInfo, files: Vec) -> Self { + pub fn from_crate_info(inner: ProtobufCrate, files: Vec) -> Self { Self { files, inner } } @@ -68,45 +38,61 @@ pub use model::*; } } +#[derive(Clone, Debug)] +pub struct ProtobufCrate { + pub folder_name: String, + pub proto_paths: Vec, + pub crate_path: String, +} + +impl ProtobufCrate { + pub fn from_config(config: CrateConfig) -> Self { + let proto_paths = config.proto_paths(); + ProtobufCrate { + folder_name: config.folder_name, + proto_paths, + crate_path: config.crate_path, + } + } + + fn protobuf_crate_name(&self) -> String { + format!("{}/src/protobuf", self.crate_path) + } + + pub fn proto_file_output_dir(&self) -> String { + let dir = format!("{}/proto", self.protobuf_crate_name()); + create_dir_if_not_exist(dir.as_ref()); + dir + } + + pub fn proto_struct_output_dir(&self) -> String { + let dir = format!("{}/model", self.protobuf_crate_name()); + create_dir_if_not_exist(dir.as_ref()); + dir + } + + pub fn proto_model_mod_file(&self) -> String { + format!("{}/mod.rs", self.proto_struct_output_dir()) + } +} + #[derive(Debug)] -pub struct FileProtoInfo { +pub struct ProtoFile { pub file_name: String, pub structs: Vec, pub enums: Vec, pub generated_content: String, } -pub fn parse_crate_info_from_path(root: &str) -> Vec { +pub fn parse_crate_info_from_path(root: &str) -> Vec { WalkDir::new(root) .into_iter() .filter_entry(|e| !is_hidden(e)) .filter_map(|e| e.ok()) .filter(|e| is_crate_dir(e)) - .flat_map(|e| { - // Assert e.path().parent() will be the crate dir - let path = e.path().parent().unwrap(); - let crate_path = path.to_str().unwrap().to_string(); - let crate_folder_name = path.file_stem().unwrap().to_str().unwrap().to_string(); - let flowy_config_file = format!("{}/Flowy.toml", crate_path); - - if std::path::Path::new(&flowy_config_file).exists() { - let config = FlowyConfig::from_toml_file(flowy_config_file.as_ref()); - let crate_path = path.to_str().unwrap().to_string(); - let proto_crate_paths = config - .proto_crates - .iter() - .map(|name| format!("{}/{}", crate_path, name)) - .collect::>(); - Some(CrateInfo { - crate_folder_name, - proto_crate_paths, - crate_path, - }) - } else { - None - } - }) - .collect::>() + .flat_map(|e| parse_crate_config_from(&e)) + .map(|crate_config| ProtobufCrate::from_config(crate_config)) + .collect::>() } pub struct FlutterProtobufInfo { diff --git a/scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.rs b/scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.rs index d112f68e77..25e0d6b56d 100644 --- a/scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.rs +++ b/scripts/flowy-tool/src/proto/template/derive_meta/derive_meta.rs @@ -1,4 +1,4 @@ -use crate::proto::crate_info::{CrateProtoInfo, FileProtoInfo}; +use crate::proto::proto_info::{CrateProtoInfo, ProtoFile}; use crate::util::{get_tera, read_file}; use std::fs::OpenOptions; use std::io::Write; @@ -40,7 +40,7 @@ pub fn write_derive_meta(crate_infos: &Vec, derive_meta_dir: &st .iter() .map(|ref crate_info| &crate_info.files) .flatten() - .collect::>(); + .collect::>(); let structs: Vec = file_proto_infos .iter() diff --git a/scripts/flowy-tool/src/util/crate_config.rs b/scripts/flowy-tool/src/util/crate_config.rs new file mode 100644 index 0000000000..edb0c11028 --- /dev/null +++ b/scripts/flowy-tool/src/util/crate_config.rs @@ -0,0 +1,38 @@ +use crate::config::FlowyConfig; + +pub struct CrateConfig { + pub(crate) crate_path: String, + pub(crate) folder_name: String, + pub(crate) flowy_config: FlowyConfig, +} + +impl CrateConfig { + pub fn proto_paths(&self) -> Vec { + let proto_paths = self + .flowy_config + .proto_crates + .iter() + .map(|name| format!("{}/{}", self.crate_path, name)) + .collect::>(); + proto_paths + } +} + +pub fn parse_crate_config_from(entry: &walkdir::DirEntry) -> Option { + let path = entry.path().parent().unwrap(); + let crate_path = path.to_str().unwrap().to_string(); + let folder_name = path.file_stem().unwrap().to_str().unwrap().to_string(); + let config_path = format!("{}/Flowy.toml", crate_path); + + if std::path::Path::new(&config_path).exists() { + return None; + } + + let flowy_config = FlowyConfig::from_toml_file(config_path.as_ref()); + + Some(CrateConfig { + crate_path, + folder_name, + flowy_config, + }) +} diff --git a/scripts/flowy-tool/src/util/file.rs b/scripts/flowy-tool/src/util/file.rs index 94a986f627..b129e4643c 100644 --- a/scripts/flowy-tool/src/util/file.rs +++ b/scripts/flowy-tool/src/util/file.rs @@ -1,5 +1,5 @@ use console::Style; -use dialoguer::Confirm; + use similar::{ChangeTag, TextDiff}; use std::{ fs::{File, OpenOptions}, @@ -7,6 +7,7 @@ use std::{ path::Path, }; use tera::Tera; +use walkdir::WalkDir; pub fn read_file(path: &str) -> Option { let mut file = File::open(path).expect("Unable to open file"); @@ -20,7 +21,7 @@ pub fn read_file(path: &str) -> Option { } } -pub fn save_content_to_file_with_diff_prompt(content: &str, output_file: &str, force_write: bool) { +pub fn save_content_to_file_with_diff_prompt(content: &str, output_file: &str, _force_write: bool) { if Path::new(output_file).exists() { let old_content = read_file(output_file).unwrap(); let new_content = content.to_owned(); @@ -106,3 +107,50 @@ pub fn get_tera(directory: &str) -> Tera { } } } + +pub fn is_crate_dir(e: &walkdir::DirEntry) -> bool { + let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string(); + cargo == "Cargo".to_string() +} + +pub fn is_proto_file(e: &walkdir::DirEntry) -> bool { + if e.path().extension().is_none() { + return false; + } + let ext = e.path().extension().unwrap().to_str().unwrap().to_string(); + ext == "proto".to_string() +} + +pub fn is_hidden(entry: &walkdir::DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with(".")) + .unwrap_or(false) +} + +pub fn create_dir_if_not_exist(dir: &str) { + if !std::path::Path::new(&dir).exists() { + std::fs::create_dir_all(&dir).unwrap(); + } +} + +pub(crate) fn walk_dir(dir: &str, filter: F2, mut path_and_name: F1) +where + F1: FnMut(String, String), + F2: Fn(&walkdir::DirEntry) -> bool, +{ + for (path, name) in WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| filter(e)) + .map(|e| { + ( + e.path().to_str().unwrap().to_string(), + e.path().file_stem().unwrap().to_str().unwrap().to_string(), + ) + }) + { + path_and_name(path, name); + } +} diff --git a/scripts/flowy-tool/src/util/mod.rs b/scripts/flowy-tool/src/util/mod.rs index 529c201fa5..5cd62fd870 100644 --- a/scripts/flowy-tool/src/util/mod.rs +++ b/scripts/flowy-tool/src/util/mod.rs @@ -1,3 +1,5 @@ +mod crate_config; mod file; +pub use crate_config::*; pub use file::*;