dart_event.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. use super::event_template::*;
  2. use crate::ast::EventASTContext;
  3. use crate::flowy_toml::{parse_crate_config_from, CrateConfig};
  4. use crate::util::{is_crate_dir, is_hidden, path_string_with_component, read_file};
  5. use flowy_ast::ASTResult;
  6. use std::fs::File;
  7. use std::io::Write;
  8. use std::path::PathBuf;
  9. use syn::Item;
  10. use walkdir::WalkDir;
  11. pub fn gen(crate_name: &str) {
  12. if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
  13. log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
  14. return;
  15. }
  16. if std::env::var("FLUTTER_FLOWY_SDK_PATH").is_err() {
  17. log::warn!("FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb");
  18. return;
  19. }
  20. let crate_path = std::fs::canonicalize(".")
  21. .unwrap()
  22. .as_path()
  23. .display()
  24. .to_string();
  25. let event_crates = parse_dart_event_files(vec![crate_path]);
  26. let event_ast = event_crates
  27. .iter()
  28. .flat_map(parse_event_crate)
  29. .collect::<Vec<_>>();
  30. let event_render_ctx = ast_to_event_render_ctx(event_ast.as_ref());
  31. let mut render_result = DART_IMPORTED.to_owned();
  32. for (index, render_ctx) in event_render_ctx.into_iter().enumerate() {
  33. let mut event_template = EventTemplate::new();
  34. if let Some(content) = event_template.render(render_ctx, index) {
  35. render_result.push_str(content.as_ref())
  36. }
  37. }
  38. let dart_event_folder: PathBuf = [
  39. &std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap(),
  40. &std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap(),
  41. "lib",
  42. "dispatch",
  43. "dart_event",
  44. crate_name,
  45. ]
  46. .iter()
  47. .collect();
  48. if !dart_event_folder.as_path().exists() {
  49. std::fs::create_dir_all(dart_event_folder.as_path()).unwrap();
  50. }
  51. let dart_event_file_path =
  52. path_string_with_component(&dart_event_folder, vec!["dart_event.dart"]);
  53. println!("cargo:rerun-if-changed={}", dart_event_file_path);
  54. match std::fs::OpenOptions::new()
  55. .create(true)
  56. .write(true)
  57. .append(false)
  58. .truncate(true)
  59. .open(&dart_event_file_path)
  60. {
  61. Ok(ref mut file) => {
  62. file.write_all(render_result.as_bytes()).unwrap();
  63. File::flush(file).unwrap();
  64. },
  65. Err(err) => {
  66. panic!("Failed to open file: {}, {:?}", dart_event_file_path, err);
  67. },
  68. }
  69. }
  70. const DART_IMPORTED: &str = r#"
  71. /// Auto generate. Do not edit
  72. part of '../../dispatch.dart';
  73. "#;
  74. #[derive(Debug)]
  75. pub struct DartEventCrate {
  76. crate_path: PathBuf,
  77. event_files: Vec<String>,
  78. }
  79. impl DartEventCrate {
  80. pub fn from_config(config: &CrateConfig) -> Self {
  81. DartEventCrate {
  82. crate_path: config.crate_path.clone(),
  83. event_files: config.flowy_config.event_files.clone(),
  84. }
  85. }
  86. }
  87. pub fn parse_dart_event_files(crate_paths: Vec<String>) -> Vec<DartEventCrate> {
  88. let mut dart_event_crates: Vec<DartEventCrate> = vec![];
  89. crate_paths.iter().for_each(|path| {
  90. let crates = WalkDir::new(path)
  91. .into_iter()
  92. .filter_entry(|e| !is_hidden(e))
  93. .filter_map(|e| e.ok())
  94. .filter(is_crate_dir)
  95. .flat_map(|e| parse_crate_config_from(&e))
  96. .map(|crate_config| DartEventCrate::from_config(&crate_config))
  97. .collect::<Vec<DartEventCrate>>();
  98. dart_event_crates.extend(crates);
  99. });
  100. dart_event_crates
  101. }
  102. pub fn parse_event_crate(event_crate: &DartEventCrate) -> Vec<EventASTContext> {
  103. event_crate
  104. .event_files
  105. .iter()
  106. .flat_map(|event_file| {
  107. let file_path =
  108. path_string_with_component(&event_crate.crate_path, vec![event_file.as_str()]);
  109. let file_content = read_file(file_path.as_ref()).unwrap();
  110. let ast = syn::parse_file(file_content.as_ref()).expect("Unable to parse file");
  111. ast
  112. .items
  113. .iter()
  114. .flat_map(|item| match item {
  115. Item::Enum(item_enum) => {
  116. let ast_result = ASTResult::new();
  117. let attrs = flowy_ast::enum_from_ast(
  118. &ast_result,
  119. &item_enum.ident,
  120. &item_enum.variants,
  121. &item_enum.attrs,
  122. );
  123. ast_result.check().unwrap();
  124. attrs
  125. .iter()
  126. .filter(|attr| !attr.attrs.event_attrs.ignore)
  127. .enumerate()
  128. .map(|(_index, variant)| EventASTContext::from(&variant.attrs))
  129. .collect::<Vec<_>>()
  130. },
  131. _ => vec![],
  132. })
  133. .collect::<Vec<_>>()
  134. })
  135. .collect::<Vec<EventASTContext>>()
  136. }
  137. pub fn ast_to_event_render_ctx(ast: &[EventASTContext]) -> Vec<EventRenderContext> {
  138. ast
  139. .iter()
  140. .map(|event_ast| {
  141. let input_deserializer = event_ast
  142. .event_input
  143. .as_ref()
  144. .map(|event_input| event_input.get_ident().unwrap().to_string());
  145. let output_deserializer = event_ast
  146. .event_output
  147. .as_ref()
  148. .map(|event_output| event_output.get_ident().unwrap().to_string());
  149. EventRenderContext {
  150. input_deserializer,
  151. output_deserializer,
  152. error_deserializer: event_ast.event_error.clone(),
  153. event: event_ast.event.to_string(),
  154. event_ty: event_ast.event_ty.to_string(),
  155. }
  156. })
  157. .collect::<Vec<EventRenderContext>>()
  158. }