Prechádzať zdrojové kódy

chore: auto import pb file

appflowy 2 rokov pred
rodič
commit
d30d42e841

+ 1 - 1
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;

+ 1 - 1
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;

+ 1 - 1
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;

+ 2 - 1
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;

+ 0 - 1
shared-lib/flowy-error-code/resources/proto/code.proto

@@ -1,5 +1,4 @@
 syntax = "proto3";
-
 enum ErrorCode {
     Internal = 0;
     UserUnauthorized = 2;

+ 1 - 1
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;

+ 2 - 1
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;

+ 1 - 1
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;

+ 0 - 1
shared-lib/flowy-grid-data-model/resources/proto/field.proto

@@ -1,5 +1,4 @@
 syntax = "proto3";
-
 message Field {
     string id = 1;
     string name = 2;

+ 0 - 1
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;

+ 0 - 1
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;

+ 2 - 1
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;

+ 1 - 1
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;

+ 36 - 19
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<String> = 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<String> = structs.iter().map(|s| s.name.clone()).collect();
+            let enums: Vec<String> = 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<Option<Match<'t>>>
         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');

+ 54 - 3
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::<HashMap<String, ProtoFileSymbol>>()
+        })
+        .flatten()
+        .collect::<HashMap<String, ProtoFileSymbol>>();
+
     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, ProtoFileSymbol>) -> String {
+    let mut import_content = String::new();
+    file_path_symbols_map
+        .iter()
+        .for_each(|(file_path, proto_file_symbols)| {
+            if file_path != &current_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<String>,
+}
+
 fn write_rust_crate_mod_file(crate_contexts: &[ProtobufCrateContext]) {
     for context in crate_contexts {
         let mod_path = context.protobuf_crate.proto_model_mod_file();

+ 17 - 1
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<String>,
+
+    pub ref_types: Vec<String>,
+
     pub enums: Vec<String>,
-    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<String> {
+        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<String>) -> Vec<ProtobufCrate> {

+ 1 - 1
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",