diff --git a/frontend/rust-lib/flowy-grid/resources/proto/cell_entities.proto b/frontend/rust-lib/flowy-grid/resources/proto/cell_entities.proto index 558ed90034..32d4590427 100644 --- a/frontend/rust-lib/flowy-grid/resources/proto/cell_entities.proto +++ b/frontend/rust-lib/flowy-grid/resources/proto/cell_entities.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "field_entities.proto"; +import "field_entities.proto"; message CreateSelectOptionPayload { FieldIdentifierPayload field_identifier = 1; string option_name = 2; diff --git a/frontend/rust-lib/flowy-grid/resources/proto/date_type_option.proto b/frontend/rust-lib/flowy-grid/resources/proto/date_type_option.proto index b441f29f9d..b67566ad58 100644 --- a/frontend/rust-lib/flowy-grid/resources/proto/date_type_option.proto +++ b/frontend/rust-lib/flowy-grid/resources/proto/date_type_option.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "cell_entities.proto"; +import "cell_entities.proto"; message DateTypeOption { DateFormat date_format = 1; TimeFormat time_format = 2; diff --git a/frontend/rust-lib/flowy-grid/resources/proto/number_type_option.proto b/frontend/rust-lib/flowy-grid/resources/proto/number_type_option.proto index 47a76e40cd..c87ff88c3e 100644 --- a/frontend/rust-lib/flowy-grid/resources/proto/number_type_option.proto +++ b/frontend/rust-lib/flowy-grid/resources/proto/number_type_option.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "format.proto"; +import "format.proto"; message NumberTypeOption { NumberFormat format = 1; uint32 scale = 2; diff --git a/frontend/rust-lib/flowy-grid/resources/proto/selection_type_option.proto b/frontend/rust-lib/flowy-grid/resources/proto/selection_type_option.proto index 0ad96d7dd2..f26ebf72f1 100644 --- a/frontend/rust-lib/flowy-grid/resources/proto/selection_type_option.proto +++ b/frontend/rust-lib/flowy-grid/resources/proto/selection_type_option.proto @@ -1,6 +1,7 @@ syntax = "proto3"; -import "cell_entities.proto"; +import "cell_entities.proto"; +import "cell_entities.proto"; message SingleSelectTypeOption { repeated SelectOption options = 1; bool disable_color = 2; diff --git a/shared-lib/flowy-error-code/resources/proto/code.proto b/shared-lib/flowy-error-code/resources/proto/code.proto index 67aa0ab640..ede9b65657 100644 --- a/shared-lib/flowy-error-code/resources/proto/code.proto +++ b/shared-lib/flowy-error-code/resources/proto/code.proto @@ -1,5 +1,4 @@ syntax = "proto3"; - enum ErrorCode { Internal = 0; UserUnauthorized = 2; diff --git a/shared-lib/flowy-folder-data-model/resources/proto/app.proto b/shared-lib/flowy-folder-data-model/resources/proto/app.proto index 53ffe4b092..a71bc15a0a 100644 --- a/shared-lib/flowy-folder-data-model/resources/proto/app.proto +++ b/shared-lib/flowy-folder-data-model/resources/proto/app.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "view.proto"; +import "view.proto"; message App { string id = 1; string workspace_id = 2; diff --git a/shared-lib/flowy-folder-data-model/resources/proto/view_info.proto b/shared-lib/flowy-folder-data-model/resources/proto/view_info.proto index 90d115c3a8..fe2f4cc7cc 100644 --- a/shared-lib/flowy-folder-data-model/resources/proto/view_info.proto +++ b/shared-lib/flowy-folder-data-model/resources/proto/view_info.proto @@ -1,6 +1,7 @@ syntax = "proto3"; -import "view.proto"; +import "view.proto"; +import "view.proto"; message ViewInfo { string id = 1; string belong_to_id = 2; diff --git a/shared-lib/flowy-folder-data-model/resources/proto/workspace.proto b/shared-lib/flowy-folder-data-model/resources/proto/workspace.proto index dceb73f02a..4c05aa7d24 100644 --- a/shared-lib/flowy-folder-data-model/resources/proto/workspace.proto +++ b/shared-lib/flowy-folder-data-model/resources/proto/workspace.proto @@ -1,7 +1,7 @@ syntax = "proto3"; + import "app.proto"; import "view.proto"; - message Workspace { string id = 1; string name = 2; diff --git a/shared-lib/flowy-grid-data-model/resources/proto/field.proto b/shared-lib/flowy-grid-data-model/resources/proto/field.proto index 7ec7559110..c27c8a4f4d 100644 --- a/shared-lib/flowy-grid-data-model/resources/proto/field.proto +++ b/shared-lib/flowy-grid-data-model/resources/proto/field.proto @@ -1,5 +1,4 @@ syntax = "proto3"; - message Field { string id = 1; string name = 2; diff --git a/shared-lib/flowy-grid-data-model/resources/proto/grid.proto b/shared-lib/flowy-grid-data-model/resources/proto/grid.proto index 1a99f272f6..8112d9c335 100644 --- a/shared-lib/flowy-grid-data-model/resources/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/resources/proto/grid.proto @@ -1,6 +1,5 @@ syntax = "proto3"; import "field.proto"; - message Grid { string id = 1; repeated FieldOrder field_orders = 2; diff --git a/shared-lib/flowy-grid-data-model/resources/proto/grid_info.proto b/shared-lib/flowy-grid-data-model/resources/proto/grid_info.proto index 53a3a7345b..7e0780f810 100644 --- a/shared-lib/flowy-grid-data-model/resources/proto/grid_info.proto +++ b/shared-lib/flowy-grid-data-model/resources/proto/grid_info.proto @@ -1,5 +1,4 @@ syntax = "proto3"; - message ViewExtData { ViewFilter filter = 1; ViewGroup group = 2; diff --git a/shared-lib/flowy-sync/resources/proto/text_block_info.proto b/shared-lib/flowy-sync/resources/proto/text_block_info.proto index 70717c4d2b..0bdf0fa485 100644 --- a/shared-lib/flowy-sync/resources/proto/text_block_info.proto +++ b/shared-lib/flowy-sync/resources/proto/text_block_info.proto @@ -1,6 +1,7 @@ syntax = "proto3"; -import "revision.proto"; +import "revision.proto"; +import "revision.proto"; message CreateTextBlockParams { string id = 1; RepeatedRevision revisions = 2; diff --git a/shared-lib/flowy-sync/resources/proto/ws_data.proto b/shared-lib/flowy-sync/resources/proto/ws_data.proto index eceb412de0..73ed03a764 100644 --- a/shared-lib/flowy-sync/resources/proto/ws_data.proto +++ b/shared-lib/flowy-sync/resources/proto/ws_data.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "revision.proto"; +import "revision.proto"; message ClientRevisionWSData { string object_id = 1; ClientRevisionWSDataType ty = 2; diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs index de5538ea0a..cbf2b4ffa8 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #![allow(unused_imports)] #![allow(unused_results)] -use crate::code_gen::protobuf_file::template::{EnumTemplate, StructTemplate}; +use crate::code_gen::protobuf_file::template::{EnumTemplate, StructTemplate, RUST_TYPE_MAP}; use crate::code_gen::protobuf_file::{parse_crate_info_from_path, ProtoFile, ProtobufCrateContext}; use crate::code_gen::util::*; use fancy_regex::Regex; @@ -57,19 +57,28 @@ fn parse_files_protobuf(proto_crate_path: &Path, proto_output_path: &Path) -> Ve let structs = get_ast_structs(&ast); let proto_file = format!("{}.proto", &file_name); let proto_file_path = path_string_with_component(proto_output_path, vec![&proto_file]); - let mut proto_file_content = find_proto_syntax(proto_file_path.as_ref()); + let proto_syntax = find_proto_syntax(proto_file_path.as_ref()); + let mut proto_content = String::new(); + + // The types that are not defined in the current file. + let mut ref_types: Vec = vec![]; structs.iter().for_each(|s| { let mut struct_template = StructTemplate::new(); struct_template.set_message_struct_name(&s.name); - s.fields.iter().filter(|f| f.attrs.pb_index().is_some()).for_each(|f| { - struct_template.set_field(f); - }); + s.fields + .iter() + .filter(|field| field.attrs.pb_index().is_some()) + .for_each(|field| { + ref_types.push(field.ty_as_str().to_string()); + struct_template.set_field(field); + }); let s = struct_template.render().unwrap(); - proto_file_content.push_str(s.as_ref()); - proto_file_content.push('\n'); + + proto_content.push_str(s.as_ref()); + proto_content.push('\n'); }); let enums = get_ast_enums(&ast); @@ -77,17 +86,26 @@ fn parse_files_protobuf(proto_crate_path: &Path, proto_output_path: &Path) -> Ve let mut enum_template = EnumTemplate::new(); enum_template.set_message_enum(e); let s = enum_template.render().unwrap(); - proto_file_content.push_str(s.as_ref()); - proto_file_content.push('\n'); + proto_content.push_str(s.as_ref()); + ref_types.push(e.name.clone()); + + proto_content.push('\n'); }); if !enums.is_empty() || !structs.is_empty() { + let structs: Vec = structs.iter().map(|s| s.name.clone()).collect(); + let enums: Vec = enums.iter().map(|e| e.name.clone()).collect(); + ref_types.retain(|s| !structs.contains(&s)); + ref_types.retain(|s| !enums.contains(&s)); + let info = ProtoFile { file_path: path.clone(), file_name: file_name.clone(), - structs: structs.iter().map(|s| s.name.clone()).collect(), - enums: enums.iter().map(|e| e.name.clone()).collect(), - generated_content: proto_file_content.clone(), + ref_types, + structs, + enums, + syntax: proto_syntax, + content: proto_content, }; gen_proto_vec.push(info); } @@ -148,12 +166,12 @@ pub struct Struct<'a> { lazy_static! { static ref SYNTAX_REGEX: Regex = Regex::new("syntax.*;").unwrap(); - static ref IMPORT_REGEX: Regex = Regex::new("(import\\s).*;").unwrap(); + // static ref IMPORT_REGEX: Regex = Regex::new("(import\\s).*;").unwrap(); } fn find_proto_syntax(path: &str) -> String { if !Path::new(path).exists() { - return String::from("syntax = \"proto3\";\n\n"); + return String::from("syntax = \"proto3\";\n"); } let mut result = String::new(); @@ -165,13 +183,12 @@ fn find_proto_syntax(path: &str) -> String { ////Result>> if let Ok(Some(m)) = SYNTAX_REGEX.find(line) { result.push_str(m.as_str()); - result.push('\n'); } - if let Ok(Some(m)) = IMPORT_REGEX.find(line) { - result.push_str(m.as_str()); - result.push('\n'); - } + // if let Ok(Some(m)) = IMPORT_REGEX.find(line) { + // result.push_str(m.as_str()); + // result.push('\n'); + // } }); result.push('\n'); diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs index 0c22ba7d1a..f3fe114c42 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs @@ -7,6 +7,7 @@ use crate::code_gen::protobuf_file::proto_info::ProtobufCrateContext; use crate::code_gen::protobuf_file::ProtoFile; use crate::code_gen::util::*; use crate::code_gen::ProtoCache; +use std::collections::HashMap; use std::fs::File; use std::path::Path; use std::{fs::OpenOptions, io::Write}; @@ -49,16 +50,66 @@ impl ProtoGenerator { } fn write_proto_files(crate_contexts: &[ProtobufCrateContext]) { + let file_path_content_map = crate_contexts + .iter() + .map(|ctx| { + ctx.files + .iter() + .map(|file| { + ( + file.file_path.clone(), + ProtoFileSymbol { + file_name: file.file_name.clone(), + symbols: file.symbols(), + }, + ) + }) + .collect::>() + }) + .flatten() + .collect::>(); + for context in crate_contexts { let dir = context.protobuf_crate.proto_output_path(); - context.files.iter().for_each(|info| { - let proto_file = format!("{}.proto", &info.file_name); + context.files.iter().for_each(|file| { + // syntax + let mut file_content = file.syntax.clone(); + + // import + file_content.push_str(&gen_import_content(&file, &file_path_content_map)); + + // content + file_content.push_str(&file.content); + + let proto_file = format!("{}.proto", &file.file_name); let proto_file_path = path_string_with_component(&dir, vec![&proto_file]); - save_content_to_file_with_diff_prompt(&info.generated_content, proto_file_path.as_ref()); + save_content_to_file_with_diff_prompt(&file_content, proto_file_path.as_ref()); }); } } +fn gen_import_content(current_file: &ProtoFile, file_path_symbols_map: &HashMap) -> String { + let mut import_content = String::new(); + file_path_symbols_map + .iter() + .for_each(|(file_path, proto_file_symbols)| { + if file_path != ¤t_file.file_path { + current_file.ref_types.iter().for_each(|ref_type| { + if proto_file_symbols.symbols.contains(ref_type) { + import_content.push_str(&format!("import \"{}.proto\";\n", proto_file_symbols.file_name)); + } + }); + } + }); + + import_content +} + +struct ProtoFileSymbol { + file_name: String, + symbols: Vec, +} + fn write_rust_crate_mod_file(crate_contexts: &[ProtobufCrateContext]) { for context in crate_contexts { let mod_path = context.protobuf_crate.proto_model_mod_file(); diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs index be2c8fdb38..d5dcbcaeaa 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs @@ -106,8 +106,24 @@ pub struct ProtoFile { pub file_path: String, pub file_name: String, pub structs: Vec, + + pub ref_types: Vec, + pub enums: Vec, - pub generated_content: String, + // proto syntax. "proto3" or "proto2" + pub syntax: String, + + // proto message content + pub content: String, +} + +impl ProtoFile { + pub fn symbols(&self) -> Vec { + let mut symbols = self.structs.clone(); + let mut enum_symbols = self.enums.clone(); + symbols.append(&mut enum_symbols); + symbols + } } pub fn parse_crate_info_from_path(roots: Vec) -> Vec { diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/template/proto_file/struct_template.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/template/proto_file/struct_template.rs index 2f3e9d462d..c1844889a3 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/template/proto_file/struct_template.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/template/proto_file/struct_template.rs @@ -4,7 +4,7 @@ use phf::phf_map; use tera::Context; // Protobuf data type : https://developers.google.com/protocol-buffers/docs/proto3 -static RUST_TYPE_MAP: phf::Map<&'static str, &'static str> = phf_map! { +pub static RUST_TYPE_MAP: phf::Map<&'static str, &'static str> = phf_map! { "String" => "string", "i64" => "int64", "i32" => "int32",