mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #337 from AppFlowy-IO/auto_gen_dart_event
Auto gen dart event
This commit is contained in:
commit
91b1430e7b
3
.github/workflows/rust_lint.yml
vendored
3
.github/workflows/rust_lint.yml
vendored
@ -41,9 +41,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
override: true
|
||||||
- name: Install cargo-make
|
|
||||||
run: cargo install --force cargo-make
|
|
||||||
working-directory: frontend
|
|
||||||
- run: rustup component add clippy
|
- run: rustup component add clippy
|
||||||
working-directory: frontend/rust-lib
|
working-directory: frontend/rust-lib
|
||||||
- run: cargo clippy --no-default-features
|
- run: cargo clippy --no-default-features
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="dart-event" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
<configuration default="false" name="dart-event" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart" />
|
<option name="command" value="run --manifest-path $PROJECT_DIR$/scripts/flowy-tool/Cargo.toml -- dart-event --rust_source=$PROJECT_DIR$/rust-lib/ --output=$PROJECT_DIR$/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event.dart" />
|
||||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
<option name="channel" value="DEFAULT" />
|
<option name="channel" value="DEFAULT" />
|
||||||
<option name="allFeatures" value="false" />
|
<option name="allFeatures" value="false" />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.PHONY: flowy_dev_install
|
.PHONY: flowy_dev_install flowy_clean
|
||||||
|
|
||||||
flowy_dev_install:
|
flowy_dev_install:
|
||||||
brew bundle
|
brew bundle
|
||||||
@ -8,3 +8,7 @@ flowy_dev_install:
|
|||||||
cargo make flowy_dev
|
cargo make flowy_dev
|
||||||
|
|
||||||
|
|
||||||
|
flowy_clean:
|
||||||
|
sh ./scripts/clean.sh
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ PRODUCT_NAME = "AppFlowy"
|
|||||||
CRATE_TYPE = "staticlib"
|
CRATE_TYPE = "staticlib"
|
||||||
SDK_EXT = "a"
|
SDK_EXT = "a"
|
||||||
APP_ENVIRONMENT = "local"
|
APP_ENVIRONMENT = "local"
|
||||||
FLUTTER_FLOWY_SDK_PATH="app_flowy/packages/flowy_sdk/lib/protobuf"
|
FLUTTER_FLOWY_SDK_PATH="app_flowy/packages/flowy_sdk"
|
||||||
PROTOBUF_DERIVE_CACHE="../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs"
|
PROTOBUF_DERIVE_CACHE="../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs"
|
||||||
|
|
||||||
[env.development-mac]
|
[env.development-mac]
|
||||||
@ -158,8 +158,8 @@ script_runner = "@duckscript"
|
|||||||
condition = { env_set = [ "FLUTTER_FLOWY_SDK_PATH"] }
|
condition = { env_set = [ "FLUTTER_FLOWY_SDK_PATH"] }
|
||||||
script = [
|
script = [
|
||||||
"""
|
"""
|
||||||
cd ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared-lib/error-code
|
cd ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/flowy-net
|
||||||
cargo build -vv
|
cargo build -vv --features=dart
|
||||||
""",
|
""",
|
||||||
]
|
]
|
||||||
script_runner = "@shell"
|
script_runner = "@shell"
|
||||||
|
7
frontend/app_flowy/.vscode/launch.json
vendored
7
frontend/app_flowy/.vscode/launch.json
vendored
@ -40,5 +40,12 @@
|
|||||||
"preLaunchTask": "Generate Language Files",
|
"preLaunchTask": "Generate Language Files",
|
||||||
"cwd": "${workspaceRoot}"
|
"cwd": "${workspaceRoot}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Clean",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"preLaunchTask": "Clean",
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
21
frontend/app_flowy/.vscode/tasks.json
vendored
21
frontend/app_flowy/.vscode/tasks.json
vendored
@ -70,6 +70,27 @@
|
|||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/../"
|
"cwd": "${workspaceFolder}/../"
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Clean FlowySDK",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "sh ./scripts/clean.sh",
|
||||||
|
"windows": {
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "cmd.exe",
|
||||||
|
"args": [
|
||||||
|
"/d",
|
||||||
|
"/c",
|
||||||
|
".\\scripts\\clean.cmd"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"group": "build",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -77,4 +77,5 @@ build/
|
|||||||
**/*.a
|
**/*.a
|
||||||
**/*.lib
|
**/*.lib
|
||||||
**/*.dll
|
**/*.dll
|
||||||
**/*.so
|
**/*.so
|
||||||
|
# lib/**/dart_event.dart
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
|
/// Auto generate. Do not edit
|
||||||
/// Auto gen code from rust ast, do not edit
|
|
||||||
part of 'dispatch.dart';
|
part of 'dispatch.dart';
|
||||||
class FolderEventCreateWorkspace {
|
class FolderEventCreateWorkspace {
|
||||||
CreateWorkspaceRequest request;
|
CreateWorkspaceRequest request;
|
@ -27,7 +27,7 @@ import 'package:protobuf/protobuf.dart';
|
|||||||
import 'dart:convert' show utf8;
|
import 'dart:convert' show utf8;
|
||||||
import 'error.dart';
|
import 'error.dart';
|
||||||
|
|
||||||
part 'code_gen.dart';
|
part 'dart_event.dart';
|
||||||
|
|
||||||
enum FFIException {
|
enum FFIException {
|
||||||
RequestIsEmpty,
|
RequestIsEmpty,
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
///
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: event_map.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
export 'event_map.pbenum.dart';
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
///
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: event_map.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
||||||
|
|
||||||
|
// ignore_for_file: UNDEFINED_SHOWN_NAME
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
class NetworkEvent extends $pb.ProtobufEnum {
|
||||||
|
static const NetworkEvent UpdateNetworkType = NetworkEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateNetworkType');
|
||||||
|
|
||||||
|
static const $core.List<NetworkEvent> values = <NetworkEvent> [
|
||||||
|
UpdateNetworkType,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, NetworkEvent> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static NetworkEvent? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const NetworkEvent._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
///
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: event_map.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
@$core.Deprecated('Use networkEventDescriptor instead')
|
||||||
|
const NetworkEvent$json = const {
|
||||||
|
'1': 'NetworkEvent',
|
||||||
|
'2': const [
|
||||||
|
const {'1': 'UpdateNetworkType', '2': 0},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `NetworkEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||||
|
final $typed_data.Uint8List networkEventDescriptor = $convert.base64Decode('CgxOZXR3b3JrRXZlbnQSFQoRVXBkYXRlTmV0d29ya1R5cGUQAA==');
|
@ -0,0 +1,9 @@
|
|||||||
|
///
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: event_map.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
|
||||||
|
|
||||||
|
export 'event_map.pb.dart';
|
||||||
|
|
@ -1,3 +1,3 @@
|
|||||||
// Auto-generated, do not edit
|
// Auto-generated, do not edit
|
||||||
export './network_state.pb.dart';
|
export './network_state.pb.dart';
|
||||||
export './event.pb.dart';
|
export './event_map.pb.dart';
|
||||||
|
@ -29,8 +29,8 @@ dart-notify = {path = "../dart-notify" }
|
|||||||
flowy-derive = {path = "../../../shared-lib/flowy-derive" }
|
flowy-derive = {path = "../../../shared-lib/flowy-derive" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["flowy-sdk/dart"]
|
default = ["flowy-sdk/dart", "dart-notify/dart", "flutter"]
|
||||||
flutter = ["dart-notify/dart"]
|
flutter = []
|
||||||
http_server = ["flowy-sdk/http_server", "flowy-sdk/use_bunyan"]
|
http_server = ["flowy-sdk/http_server", "flowy-sdk/use_bunyan"]
|
||||||
#use_serde = ["bincode"]
|
#use_serde = ["bincode"]
|
||||||
#use_protobuf= ["protobuf"]
|
#use_protobuf= ["protobuf"]
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
use lib_infra::code_gen::dart_event;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
copy_dart_event_files();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
fn copy_dart_event_files() {
|
||||||
|
let workspace_dir = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap();
|
||||||
|
let flutter_sdk_path = std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap();
|
||||||
|
let output_file = format!("{}/{}/lib/dispatch/dart_event.dart", workspace_dir, flutter_sdk_path);
|
||||||
|
println!("cargo:rerun-if-changed={}", output_file);
|
||||||
|
dart_event::write_dart_event_file(&output_file);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files("flowy-error", "./src/protobuf/proto");
|
code_gen::protobuf_file::gen("flowy-error", "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
let crate_name = env!("CARGO_PKG_NAME");
|
||||||
|
code_gen::protobuf_file::gen(crate_name, "./src/protobuf/proto");
|
||||||
|
code_gen::dart_event::gen(crate_name);
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,7 @@ use flowy_test::{event_builder::*, FlowySDKTest};
|
|||||||
async fn workspace_read_all() {
|
async fn workspace_read_all() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
test.run_scripts(vec![ReadAllWorkspaces]).await;
|
test.run_scripts(vec![ReadAllWorkspaces]).await;
|
||||||
// The first workspace will be the default workspace
|
assert!(!test.all_workspace.is_empty());
|
||||||
// The second workspace will be created by FolderTest
|
|
||||||
assert_eq!(test.all_workspace.len(), 2);
|
|
||||||
|
|
||||||
let new_name = "My new workspace".to_owned();
|
|
||||||
test.run_scripts(vec![
|
|
||||||
CreateWorkspace {
|
|
||||||
name: new_name.clone(),
|
|
||||||
desc: "Daily routines".to_owned(),
|
|
||||||
},
|
|
||||||
ReadAllWorkspaces,
|
|
||||||
])
|
|
||||||
.await;
|
|
||||||
assert_eq!(test.all_workspace.len(), 3);
|
|
||||||
assert_eq!(test.all_workspace[2].name, new_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
proto_crates = ["src/event.rs", "src/entities"]
|
proto_crates = ["src/event_map.rs", "src/entities"]
|
||||||
event_files = ["src/event.rs"]
|
event_files = ["src/event_map.rs"]
|
@ -1,5 +1,7 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
let crate_name = env!("CARGO_PKG_NAME");
|
||||||
|
code_gen::protobuf_file::gen(crate_name, "./src/protobuf/proto");
|
||||||
|
code_gen::dart_event::gen(crate_name);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
|
||||||
use strum_macros::Display;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
|
||||||
#[event_err = "FlowyError"]
|
|
||||||
pub enum NetworkEvent {
|
|
||||||
#[event(input = "NetworkState")]
|
|
||||||
UpdateNetworkType = 0,
|
|
||||||
}
|
|
19
frontend/rust-lib/flowy-net/src/event_map.rs
Normal file
19
frontend/rust-lib/flowy-net/src/event_map.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use crate::{handlers::*, ws::connection::FlowyWebSocketConnect};
|
||||||
|
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||||
|
use lib_dispatch::prelude::*;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use strum_macros::Display;
|
||||||
|
|
||||||
|
pub fn create(ws_conn: Arc<FlowyWebSocketConnect>) -> Module {
|
||||||
|
Module::new()
|
||||||
|
.name("Flowy-Network")
|
||||||
|
.data(ws_conn)
|
||||||
|
.event(NetworkEvent::UpdateNetworkType, update_network_ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||||
|
#[event_err = "FlowyError"]
|
||||||
|
pub enum NetworkEvent {
|
||||||
|
#[event(input = "NetworkState")]
|
||||||
|
UpdateNetworkType = 0,
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
mod configuration;
|
mod configuration;
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
mod event;
|
pub mod event_map;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
pub mod http_server;
|
pub mod http_server;
|
||||||
pub mod local_server;
|
pub mod local_server;
|
||||||
pub mod module;
|
|
||||||
pub mod protobuf;
|
pub mod protobuf;
|
||||||
mod request;
|
mod request;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
use crate::{event::NetworkEvent, handlers::*, ws::connection::FlowyWebSocketConnect};
|
|
||||||
use lib_dispatch::prelude::*;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub fn create(ws_conn: Arc<FlowyWebSocketConnect>) -> Module {
|
|
||||||
Module::new()
|
|
||||||
.name("Flowy-Network")
|
|
||||||
.data(ws_conn)
|
|
||||||
.event(NetworkEvent::UpdateNetworkType, update_network_ty)
|
|
||||||
}
|
|
@ -17,7 +17,7 @@
|
|||||||
#![allow(trivial_casts)]
|
#![allow(trivial_casts)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused_results)]
|
#![allow(unused_results)]
|
||||||
//! Generated file from `event.proto`
|
//! Generated file from `event_map.proto`
|
||||||
|
|
||||||
/// Generated files are compatible only with the same version
|
/// Generated files are compatible only with the same version
|
||||||
/// of protobuf runtime.
|
/// of protobuf runtime.
|
||||||
@ -71,8 +71,8 @@ impl ::protobuf::reflect::ProtobufValue for NetworkEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
\n\x0bevent.proto*%\n\x0cNetworkEvent\x12\x15\n\x11UpdateNetworkType\x10\
|
\n\x0fevent_map.proto*%\n\x0cNetworkEvent\x12\x15\n\x11UpdateNetworkType\
|
||||||
\0b\x06proto3\
|
\x10\0b\x06proto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
@ -4,5 +4,5 @@
|
|||||||
mod network_state;
|
mod network_state;
|
||||||
pub use network_state::*;
|
pub use network_state::*;
|
||||||
|
|
||||||
mod event;
|
mod event_map;
|
||||||
pub use event::*;
|
pub use event_map::*;
|
||||||
|
@ -24,5 +24,5 @@ fn mk_folder_module(core: Arc<FolderManager>) -> Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn mk_network_module(ws_conn: Arc<FlowyWebSocketConnect>) -> Module {
|
fn mk_network_module(ws_conn: Arc<FlowyWebSocketConnect>) -> Module {
|
||||||
flowy_net::module::create(ws_conn)
|
flowy_net::event_map::create(ws_conn)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
let crate_name = env!("CARGO_PKG_NAME");
|
||||||
|
code_gen::protobuf_file::gen(crate_name, "./src/protobuf/proto");
|
||||||
|
code_gen::dart_event::gen(crate_name);
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
|
||||||
use strum_macros::Display;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
|
||||||
#[event_err = "FlowyError"]
|
|
||||||
pub enum UserEvent {
|
|
||||||
#[event()]
|
|
||||||
InitUser = 0,
|
|
||||||
|
|
||||||
#[event(input = "SignInRequest", output = "UserProfile")]
|
|
||||||
SignIn = 1,
|
|
||||||
|
|
||||||
#[event(input = "SignUpRequest", output = "UserProfile")]
|
|
||||||
SignUp = 2,
|
|
||||||
|
|
||||||
#[event(passthrough)]
|
|
||||||
SignOut = 3,
|
|
||||||
|
|
||||||
#[event(input = "UpdateUserRequest")]
|
|
||||||
UpdateUser = 4,
|
|
||||||
|
|
||||||
#[event(output = "UserProfile")]
|
|
||||||
GetUserProfile = 5,
|
|
||||||
|
|
||||||
#[event(output = "UserProfile")]
|
|
||||||
CheckUser = 6,
|
|
||||||
}
|
|
7
frontend/scripts/clean.cmd
Normal file
7
frontend/scripts/clean.cmd
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
cd rust-lib
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
cd ../../shared-lib
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
rmdir /s/q lib-infra/.cache
|
10
frontend/scripts/clean.sh
Normal file
10
frontend/scripts/clean.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#!/usr/bin/env fish
|
||||||
|
|
||||||
|
cd rust-lib
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
cd ../../shared-lib
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
rm -rf lib-infra/.cache
|
@ -107,7 +107,7 @@ script = [
|
|||||||
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
||||||
|
|
||||||
rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
||||||
output=${flutter_lib}/flowy_sdk/lib/dispatch/code_gen.dart
|
output=${flutter_lib}/flowy_sdk/lib/dispatch/dart_event.dart
|
||||||
|
|
||||||
cargo run \
|
cargo run \
|
||||||
--manifest-path ${flowy_tool} dart-event \
|
--manifest-path ${flowy_tool} dart-event \
|
||||||
@ -124,7 +124,7 @@ script = [
|
|||||||
flutter_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
flutter_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
||||||
|
|
||||||
rust_source=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
rust_source=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
||||||
output=set ${flutter_lib}/flowy_sdk/lib/dispatch/code_gen.dart
|
output=set ${flutter_lib}/flowy_sdk/lib/dispatch/dart_event.dart
|
||||||
|
|
||||||
exec cmd.exe /c cargo run \
|
exec cmd.exe /c cargo run \
|
||||||
--manifest-path ${flowy_tool} dart-event \
|
--manifest-path ${flowy_tool} dart-event \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use crate::proto_buf::{
|
|||||||
};
|
};
|
||||||
use flowy_ast::*;
|
use flowy_ast::*;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
use std::default::Default;
|
||||||
|
|
||||||
pub fn expand_derive(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
pub fn expand_derive(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
||||||
let ctxt = Ctxt::new();
|
let ctxt = Ctxt::new();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use dashmap::{DashMap, DashSet};
|
use dashmap::{DashMap, DashSet};
|
||||||
use flowy_ast::{Ctxt, TyInfo};
|
use flowy_ast::{Ctxt, TyInfo};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use lib_infra::proto_gen::ProtoCache;
|
use lib_infra::code_gen::ProtoCache;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -54,6 +54,7 @@ pub fn category_from_str(type_str: String) -> TypeCategory {
|
|||||||
for path in WalkDir::new(cache_dir)
|
for path in WalkDir::new(cache_dir)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|e| e.ok())
|
.filter_map(|e| e.ok())
|
||||||
|
.filter(|e| e.path().file_stem().unwrap().to_str().unwrap() == "proto_cache")
|
||||||
.map(|e| e.path().to_str().unwrap().to_string())
|
.map(|e| e.path().to_str().unwrap().to_string())
|
||||||
{
|
{
|
||||||
match read_file(&path) {
|
match read_file(&path) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
@ -48,4 +48,5 @@ proto_gen = [
|
|||||||
"toml"
|
"toml"
|
||||||
]
|
]
|
||||||
pb_gen = ["cmd_lib", "protoc-rust", "walkdir", "protoc-bin-vendored",]
|
pb_gen = ["cmd_lib", "protoc-rust", "walkdir", "protoc-bin-vendored",]
|
||||||
dart = ["proto_gen"]
|
dart_event = ["walkdir", "flowy-ast", "tera", "syn"]
|
||||||
|
dart = ["proto_gen", "dart_event"]
|
165
shared-lib/lib-infra/src/code_gen/dart_event/dart_event.rs
Normal file
165
shared-lib/lib-infra/src/code_gen/dart_event/dart_event.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
use super::event_template::*;
|
||||||
|
use crate::code_gen::flowy_toml::{parse_crate_config_from, CrateConfig};
|
||||||
|
use crate::code_gen::util::{cache_dir, is_crate_dir, is_hidden, read_file};
|
||||||
|
use flowy_ast::{event_ast::*, *};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use syn::Item;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
pub fn gen(crate_name: &str) {
|
||||||
|
let crate_path = std::fs::canonicalize(".").unwrap().as_path().display().to_string();
|
||||||
|
let event_crates = parse_dart_event_files(vec![crate_path]);
|
||||||
|
let event_ast = event_crates.iter().map(parse_event_crate).flatten().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
if let Some(content) = event_template.render(render_ctx, index) {
|
||||||
|
render_result.push_str(content.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache_dir = format!("{}/{}", cache_dir(), crate_name);
|
||||||
|
let dart_event_file_path = format!("{}/dart_event.dart", cache_dir);
|
||||||
|
|
||||||
|
match std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.append(false)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&dart_event_file_path)
|
||||||
|
{
|
||||||
|
Ok(ref mut file) => {
|
||||||
|
file.write_all(render_result.as_bytes()).unwrap();
|
||||||
|
File::flush(file).unwrap();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
panic!("Failed to open file: {}, {:?}", dart_event_file_path, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DART_IMPORTED: &str = r#"
|
||||||
|
/// Auto generate. Do not edit
|
||||||
|
part of 'dispatch.dart';
|
||||||
|
"#;
|
||||||
|
|
||||||
|
pub fn write_dart_event_file(file_path: &str) {
|
||||||
|
let cache_dir = cache_dir();
|
||||||
|
let mut content = DART_IMPORTED.to_owned();
|
||||||
|
for path in WalkDir::new(cache_dir)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
.filter(|e| e.path().file_stem().unwrap().to_str().unwrap() == "dart_event")
|
||||||
|
.map(|e| e.path().to_str().unwrap().to_string())
|
||||||
|
{
|
||||||
|
let file_content = read_file(path.as_ref()).unwrap();
|
||||||
|
content.push_str(&file_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
match std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.append(false)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&file_path)
|
||||||
|
{
|
||||||
|
Ok(ref mut file) => {
|
||||||
|
file.write_all(content.as_bytes()).unwrap();
|
||||||
|
File::flush(file).unwrap();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
panic!("Failed to write dart event file: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DartEventCrate {
|
||||||
|
crate_path: String,
|
||||||
|
event_files: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DartEventCrate {
|
||||||
|
pub fn from_config(config: &CrateConfig) -> Self {
|
||||||
|
DartEventCrate {
|
||||||
|
crate_path: config.crate_path.clone(),
|
||||||
|
event_files: config.flowy_config.event_files.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_dart_event_files(crate_paths: Vec<String>) -> Vec<DartEventCrate> {
|
||||||
|
let mut dart_event_crates: Vec<DartEventCrate> = vec![];
|
||||||
|
crate_paths.iter().for_each(|path| {
|
||||||
|
let crates = WalkDir::new(path)
|
||||||
|
.into_iter()
|
||||||
|
.filter_entry(|e| !is_hidden(e))
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
.filter(is_crate_dir)
|
||||||
|
.flat_map(|e| parse_crate_config_from(&e))
|
||||||
|
.map(|crate_config| DartEventCrate::from_config(&crate_config))
|
||||||
|
.collect::<Vec<DartEventCrate>>();
|
||||||
|
dart_event_crates.extend(crates);
|
||||||
|
});
|
||||||
|
dart_event_crates
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_event_crate(event_crate: &DartEventCrate) -> Vec<EventASTContext> {
|
||||||
|
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.ident, &item_enum.variants, &item_enum.attrs);
|
||||||
|
ctxt.check().unwrap();
|
||||||
|
attrs
|
||||||
|
.iter()
|
||||||
|
.filter(|attr| !attr.attrs.event_attrs.ignore)
|
||||||
|
.enumerate()
|
||||||
|
.map(|(_index, attr)| EventASTContext::from(&attr.attrs))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
_ => vec![],
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<EventASTContext>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ast_to_event_render_ctx(ast: &[EventASTContext]) -> Vec<EventRenderContext> {
|
||||||
|
ast.iter()
|
||||||
|
.map(|event_ast| {
|
||||||
|
let input_deserializer = event_ast
|
||||||
|
.event_input
|
||||||
|
.as_ref()
|
||||||
|
.map(|event_input| event_input.get_ident().unwrap().to_string());
|
||||||
|
|
||||||
|
let output_deserializer = event_ast
|
||||||
|
.event_output
|
||||||
|
.as_ref()
|
||||||
|
.map(|event_output| event_output.get_ident().unwrap().to_string());
|
||||||
|
|
||||||
|
EventRenderContext {
|
||||||
|
input_deserializer,
|
||||||
|
output_deserializer,
|
||||||
|
error_deserializer: event_ast.event_error.clone(),
|
||||||
|
event: event_ast.event.to_string(),
|
||||||
|
event_ty: event_ast.event_ty.to_string(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<EventRenderContext>>()
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
use crate::code_gen::util::get_tera;
|
||||||
|
use tera::Context;
|
||||||
|
|
||||||
|
pub struct EventTemplate {
|
||||||
|
tera_context: Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventRenderContext {
|
||||||
|
pub input_deserializer: Option<String>,
|
||||||
|
pub output_deserializer: Option<String>,
|
||||||
|
pub error_deserializer: String,
|
||||||
|
pub event: String,
|
||||||
|
pub event_ty: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl EventTemplate {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
EventTemplate {
|
||||||
|
tera_context: Context::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&mut self, ctx: EventRenderContext, index: usize) -> Option<String> {
|
||||||
|
self.tera_context.insert("index", &index);
|
||||||
|
let dart_class_name = format!("{}{}", ctx.event_ty, ctx.event);
|
||||||
|
let event = format!("{}.{}", ctx.event_ty, ctx.event);
|
||||||
|
self.tera_context.insert("event_class", &dart_class_name);
|
||||||
|
self.tera_context.insert("event", &event);
|
||||||
|
|
||||||
|
self.tera_context.insert("has_input", &ctx.input_deserializer.is_some());
|
||||||
|
match ctx.input_deserializer {
|
||||||
|
None => self.tera_context.insert("input_deserializer", "Unit"),
|
||||||
|
Some(ref input) => self.tera_context.insert("input_deserializer", input),
|
||||||
|
}
|
||||||
|
|
||||||
|
// eprintln!(
|
||||||
|
// "😁 {:?} / {:?}",
|
||||||
|
// &ctx.input_deserializer, &ctx.output_deserializer
|
||||||
|
// );
|
||||||
|
|
||||||
|
let has_output = ctx.output_deserializer.is_some();
|
||||||
|
self.tera_context.insert("has_output", &has_output);
|
||||||
|
|
||||||
|
match ctx.output_deserializer {
|
||||||
|
None => self.tera_context.insert("output_deserializer", "Unit"),
|
||||||
|
Some(ref output) => self.tera_context.insert("output_deserializer", output),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tera_context.insert("error_deserializer", &ctx.error_deserializer);
|
||||||
|
|
||||||
|
let tera = get_tera("dart_event");
|
||||||
|
match tera.render("event_template.tera", &self.tera_context) {
|
||||||
|
Ok(r) => Some(r),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("{:?}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
class {{ event_class }} {
|
||||||
|
{%- if has_input %}
|
||||||
|
{{ input_deserializer }} request;
|
||||||
|
{{ event_class }}(this.request);
|
||||||
|
{%- else %}
|
||||||
|
{{ event_class }}();
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
Future<Either<{{ output_deserializer }}, {{ error_deserializer }}>> send() {
|
||||||
|
|
||||||
|
{%- if has_input %}
|
||||||
|
final request = FFIRequest.create()
|
||||||
|
..event = {{ event }}.toString()
|
||||||
|
..payload = requestToBytes(this.request);
|
||||||
|
|
||||||
|
return Dispatch.asyncRequest(request)
|
||||||
|
.then((bytesResult) => bytesResult.fold(
|
||||||
|
|
||||||
|
{%- if has_output %}
|
||||||
|
(okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)),
|
||||||
|
{%- else %}
|
||||||
|
(bytes) => left(unit),
|
||||||
|
{%- endif %}
|
||||||
|
(errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)),
|
||||||
|
));
|
||||||
|
|
||||||
|
{%- else %}
|
||||||
|
final request = FFIRequest.create()
|
||||||
|
..event = {{ event }}.toString();
|
||||||
|
{%- if has_input %}
|
||||||
|
..payload = bytes;
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
|
||||||
|
{%- if has_output %}
|
||||||
|
(okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)),
|
||||||
|
{%- else %}
|
||||||
|
(bytes) => left(unit),
|
||||||
|
{%- endif %}
|
||||||
|
(errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)),
|
||||||
|
));
|
||||||
|
{%- endif %}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
5
shared-lib/lib-infra/src/code_gen/dart_event/mod.rs
Normal file
5
shared-lib/lib-infra/src/code_gen/dart_event/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#![allow(clippy::module_inception)]
|
||||||
|
mod dart_event;
|
||||||
|
mod event_template;
|
||||||
|
|
||||||
|
pub use dart_event::*;
|
@ -15,9 +15,9 @@ impl FlowyConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CrateConfig {
|
pub struct CrateConfig {
|
||||||
pub(crate) crate_path: String,
|
pub crate_path: String,
|
||||||
pub(crate) folder_name: String,
|
pub folder_name: String,
|
||||||
pub(crate) flowy_config: FlowyConfig,
|
pub flowy_config: FlowyConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateConfig {
|
impl CrateConfig {
|
17
shared-lib/lib-infra/src/code_gen/mod.rs
Normal file
17
shared-lib/lib-infra/src/code_gen/mod.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#[cfg(feature = "pb_gen")]
|
||||||
|
pub mod protobuf_file;
|
||||||
|
|
||||||
|
#[cfg(feature = "dart_event")]
|
||||||
|
pub mod dart_event;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "pb_gen", feature = "dart_event"))]
|
||||||
|
mod flowy_toml;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "pb_gen", feature = "dart_event"))]
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct ProtoCache {
|
||||||
|
pub structs: Vec<String>,
|
||||||
|
pub enums: Vec<String>,
|
||||||
|
}
|
@ -2,9 +2,9 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused_results)]
|
#![allow(unused_results)]
|
||||||
use crate::proto_gen::template::{EnumTemplate, StructTemplate};
|
use crate::code_gen::protobuf_file::template::{EnumTemplate, StructTemplate};
|
||||||
use crate::proto_gen::util::*;
|
use crate::code_gen::protobuf_file::{parse_crate_info_from_path, ProtoFile, ProtobufCrateContext};
|
||||||
use crate::proto_gen::{parse_crate_info_from_path, ProtoFile, ProtobufCrateContext};
|
use crate::code_gen::util::*;
|
||||||
use fancy_regex::Regex;
|
use fancy_regex::Regex;
|
||||||
use flowy_ast::*;
|
use flowy_ast::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -12,8 +12,8 @@ use std::{fs::File, io::Read, path::Path};
|
|||||||
use syn::Item;
|
use syn::Item;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub fn parse_crate_protobuf(roots: Vec<String>) -> Vec<ProtobufCrateContext> {
|
pub fn parse_crate_protobuf(crate_paths: Vec<String>) -> Vec<ProtobufCrateContext> {
|
||||||
let crate_infos = parse_crate_info_from_path(roots);
|
let crate_infos = parse_crate_info_from_path(crate_paths);
|
||||||
crate_infos
|
crate_infos
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|crate_info| {
|
.map(|crate_info| {
|
@ -1,9 +1,15 @@
|
|||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused_attributes)]
|
#![allow(unused_attributes)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
mod ast;
|
||||||
|
mod proto_gen;
|
||||||
|
mod proto_info;
|
||||||
|
mod template;
|
||||||
|
|
||||||
|
pub use proto_gen::*;
|
||||||
|
pub use proto_info::*;
|
||||||
|
|
||||||
#[cfg(feature = "proto_gen")]
|
#[cfg(feature = "proto_gen")]
|
||||||
use crate::proto_gen::*;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -11,12 +17,12 @@ use std::path::PathBuf;
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub fn gen_files(crate_name: &str, proto_file_dir: &str) {
|
pub fn gen(crate_name: &str, proto_file_dir: &str) {
|
||||||
// 1. generate the proto files to proto_file_dir
|
// 1. generate the proto files to proto_file_dir
|
||||||
#[cfg(feature = "proto_gen")]
|
#[cfg(feature = "proto_gen")]
|
||||||
let _ = gen_protos(crate_name);
|
let _ = gen_protos(crate_name);
|
||||||
|
|
||||||
let mut paths = vec![];
|
let mut proto_file_paths = vec![];
|
||||||
let mut file_names = vec![];
|
let mut file_names = vec![];
|
||||||
|
|
||||||
for (path, file_name) in WalkDir::new(proto_file_dir)
|
for (path, file_name) in WalkDir::new(proto_file_dir)
|
||||||
@ -31,26 +37,31 @@ pub fn gen_files(crate_name: &str, proto_file_dir: &str) {
|
|||||||
if path.ends_with(".proto") {
|
if path.ends_with(".proto") {
|
||||||
// https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
|
// https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
|
||||||
println!("cargo:rerun-if-changed={}", path);
|
println!("cargo:rerun-if-changed={}", path);
|
||||||
paths.push(path);
|
proto_file_paths.push(path);
|
||||||
file_names.push(file_name);
|
file_names.push(file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
|
||||||
let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
|
let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
|
||||||
|
|
||||||
// 2. generate the protobuf files(Dart)
|
// 2. generate the protobuf files(Dart)
|
||||||
#[cfg(feature = "dart")]
|
#[cfg(feature = "dart")]
|
||||||
generate_dart_protobuf_files(crate_name, proto_file_dir, &paths, &file_names, &protoc_bin_path);
|
generate_dart_protobuf_files(
|
||||||
|
crate_name,
|
||||||
|
proto_file_dir,
|
||||||
|
&proto_file_paths,
|
||||||
|
&file_names,
|
||||||
|
&protoc_bin_path,
|
||||||
|
);
|
||||||
|
|
||||||
// 3. generate the protobuf files(Rust)
|
// 3. generate the protobuf files(Rust)
|
||||||
generate_rust_protobuf_files(&protoc_bin_path, &paths, proto_file_dir);
|
generate_rust_protobuf_files(&protoc_bin_path, &proto_file_paths, proto_file_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_rust_protobuf_files(protoc_bin_path: &PathBuf, input_paths: &Vec<String>, proto_file_dir: &str) {
|
fn generate_rust_protobuf_files(protoc_bin_path: &PathBuf, proto_file_paths: &Vec<String>, proto_file_dir: &str) {
|
||||||
protoc_rust::Codegen::new()
|
protoc_rust::Codegen::new()
|
||||||
.out_dir("./src/protobuf/model")
|
.out_dir("./src/protobuf/model")
|
||||||
.protoc_path(protoc_bin_path)
|
.protoc_path(protoc_bin_path)
|
||||||
.inputs(input_paths)
|
.inputs(proto_file_paths)
|
||||||
.include(proto_file_dir)
|
.include(proto_file_dir)
|
||||||
.run()
|
.run()
|
||||||
.expect("Running protoc failed.");
|
.expect("Running protoc failed.");
|
||||||
@ -62,7 +73,7 @@ fn generate_dart_protobuf_files(
|
|||||||
root: &str,
|
root: &str,
|
||||||
paths: &Vec<String>,
|
paths: &Vec<String>,
|
||||||
file_names: &Vec<String>,
|
file_names: &Vec<String>,
|
||||||
proto_path: &PathBuf,
|
protoc_bin_path: &PathBuf,
|
||||||
) {
|
) {
|
||||||
if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
|
if std::env::var("CARGO_MAKE_WORKING_DIRECTORY").is_err() {
|
||||||
log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
|
log::warn!("CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb");
|
||||||
@ -76,15 +87,15 @@ fn generate_dart_protobuf_files(
|
|||||||
|
|
||||||
let workspace_dir = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap();
|
let workspace_dir = std::env::var("CARGO_MAKE_WORKING_DIRECTORY").unwrap();
|
||||||
let flutter_sdk_path = std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap();
|
let flutter_sdk_path = std::env::var("FLUTTER_FLOWY_SDK_PATH").unwrap();
|
||||||
let output = format!("{}/{}/{}", workspace_dir, flutter_sdk_path, name);
|
let output = format!("{}/{}/lib/protobuf/{}", workspace_dir, flutter_sdk_path, name);
|
||||||
if !std::path::Path::new(&output).exists() {
|
if !std::path::Path::new(&output).exists() {
|
||||||
std::fs::create_dir_all(&output).unwrap();
|
std::fs::create_dir_all(&output).unwrap();
|
||||||
}
|
}
|
||||||
check_pb_dart_plugin();
|
check_pb_dart_plugin();
|
||||||
let proto_path = proto_path.to_str().unwrap().to_owned();
|
let protoc_bin_path = protoc_bin_path.to_str().unwrap().to_owned();
|
||||||
paths.iter().for_each(|path| {
|
paths.iter().for_each(|path| {
|
||||||
if cmd_lib::run_cmd! {
|
if cmd_lib::run_cmd! {
|
||||||
${proto_path} --dart_out=${output} --proto_path=${root} ${path}
|
${protoc_bin_path} --dart_out=${output} --proto_path=${root} ${path}
|
||||||
}
|
}
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
@ -147,9 +158,8 @@ fn run_command(cmd: &str) -> bool {
|
|||||||
|
|
||||||
#[cfg(feature = "proto_gen")]
|
#[cfg(feature = "proto_gen")]
|
||||||
fn gen_protos(crate_name: &str) -> Vec<ProtobufCrate> {
|
fn gen_protos(crate_name: &str) -> Vec<ProtobufCrate> {
|
||||||
let cache_path = env!("CARGO_MANIFEST_DIR");
|
let crate_path = std::fs::canonicalize(".").unwrap().as_path().display().to_string();
|
||||||
let root = std::fs::canonicalize(".").unwrap().as_path().display().to_string();
|
let crate_context = ProtoGenerator::gen(crate_name, &crate_path);
|
||||||
let crate_context = ProtoGenerator::gen(crate_name, &root, cache_path);
|
|
||||||
let proto_crates = crate_context
|
let proto_crates = crate_context
|
||||||
.iter()
|
.iter()
|
||||||
.map(|info| info.protobuf_crate.clone())
|
.map(|info| info.protobuf_crate.clone())
|
@ -2,17 +2,18 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused_results)]
|
#![allow(unused_results)]
|
||||||
use crate::proto_gen::ast::parse_crate_protobuf;
|
use crate::code_gen::protobuf_file::ast::parse_crate_protobuf;
|
||||||
use crate::proto_gen::proto_info::ProtobufCrateContext;
|
use crate::code_gen::protobuf_file::proto_info::ProtobufCrateContext;
|
||||||
use crate::proto_gen::util::*;
|
use crate::code_gen::protobuf_file::ProtoFile;
|
||||||
use crate::proto_gen::ProtoFile;
|
use crate::code_gen::util::*;
|
||||||
|
use crate::code_gen::ProtoCache;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::{fs::OpenOptions, io::Write};
|
use std::{fs::OpenOptions, io::Write};
|
||||||
|
|
||||||
pub(crate) struct ProtoGenerator();
|
pub struct ProtoGenerator();
|
||||||
impl ProtoGenerator {
|
impl ProtoGenerator {
|
||||||
pub(crate) fn gen(crate_name: &str, crate_path: &str, cache_path: &str) -> Vec<ProtobufCrateContext> {
|
pub fn gen(crate_name: &str, crate_path: &str) -> Vec<ProtobufCrateContext> {
|
||||||
let crate_contexts = parse_crate_protobuf(vec![crate_path.to_owned()]);
|
let crate_contexts = parse_crate_protobuf(vec![crate_path.to_owned()]);
|
||||||
write_proto_files(&crate_contexts);
|
write_proto_files(&crate_contexts);
|
||||||
write_rust_crate_mod_file(&crate_contexts);
|
write_rust_crate_mod_file(&crate_contexts);
|
||||||
@ -24,7 +25,7 @@ impl ProtoGenerator {
|
|||||||
|
|
||||||
let cache = ProtoCache::from_crate_contexts(&crate_contexts);
|
let cache = ProtoCache::from_crate_contexts(&crate_contexts);
|
||||||
let cache_str = serde_json::to_string(&cache).unwrap();
|
let cache_str = serde_json::to_string(&cache).unwrap();
|
||||||
let cache_dir = format!("{}/.cache/{}", cache_path, crate_name);
|
let cache_dir = format!("{}/{}", cache_dir(), crate_name);
|
||||||
if !Path::new(&cache_dir).exists() {
|
if !Path::new(&cache_dir).exists() {
|
||||||
std::fs::create_dir_all(&cache_dir).unwrap();
|
std::fs::create_dir_all(&cache_dir).unwrap();
|
||||||
}
|
}
|
||||||
@ -92,12 +93,6 @@ fn write_rust_crate_mod_file(crate_contexts: &[ProtobufCrateContext]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct ProtoCache {
|
|
||||||
pub structs: Vec<String>,
|
|
||||||
pub enums: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProtoCache {
|
impl ProtoCache {
|
||||||
fn from_crate_contexts(crate_contexts: &[ProtobufCrateContext]) -> Self {
|
fn from_crate_contexts(crate_contexts: &[ProtobufCrateContext]) -> Self {
|
||||||
let proto_files = crate_contexts
|
let proto_files = crate_contexts
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::proto_gen::flowy_toml::{parse_crate_config_from, CrateConfig};
|
use crate::code_gen::flowy_toml::{parse_crate_config_from, CrateConfig};
|
||||||
use crate::proto_gen::util::*;
|
use crate::code_gen::util::*;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
@ -1,4 +1,4 @@
|
|||||||
use crate::proto_gen::template::get_tera;
|
use crate::code_gen::util::get_tera;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ impl ProtobufDeriveMeta {
|
|||||||
self.context.insert("names", &self.structs);
|
self.context.insert("names", &self.structs);
|
||||||
self.context.insert("enums", &self.enums);
|
self.context.insert("enums", &self.enums);
|
||||||
|
|
||||||
let tera = get_tera("derive_meta");
|
let tera = get_tera("protobuf_file/template/derive_meta");
|
||||||
match tera.render("derive_meta.tera", &self.context) {
|
match tera.render("derive_meta.tera", &self.context) {
|
||||||
Ok(r) => Some(r),
|
Ok(r) => Some(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
@ -0,0 +1,5 @@
|
|||||||
|
mod derive_meta;
|
||||||
|
mod proto_file;
|
||||||
|
|
||||||
|
pub use derive_meta::*;
|
||||||
|
pub use proto_file::*;
|
@ -1,5 +1,5 @@
|
|||||||
use crate::proto_gen::ast::FlowyEnum;
|
use crate::code_gen::protobuf_file::ast::FlowyEnum;
|
||||||
use crate::proto_gen::template::get_tera;
|
use crate::code_gen::util::get_tera;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
pub struct EnumTemplate {
|
pub struct EnumTemplate {
|
||||||
@ -26,7 +26,7 @@ impl EnumTemplate {
|
|||||||
|
|
||||||
pub fn render(&mut self) -> Option<String> {
|
pub fn render(&mut self) -> Option<String> {
|
||||||
self.context.insert("items", &self.items);
|
self.context.insert("items", &self.items);
|
||||||
let tera = get_tera("proto_file");
|
let tera = get_tera("protobuf_file/template/proto_file");
|
||||||
match tera.render("enum.tera", &self.context) {
|
match tera.render("enum.tera", &self.context) {
|
||||||
Ok(r) => Some(r),
|
Ok(r) => Some(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
@ -1,7 +1,6 @@
|
|||||||
|
use crate::code_gen::util::get_tera;
|
||||||
use flowy_ast::*;
|
use flowy_ast::*;
|
||||||
use phf::phf_map;
|
use phf::phf_map;
|
||||||
|
|
||||||
use crate::proto_gen::template::get_tera;
|
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
// Protobuf data type : https://developers.google.com/protocol-buffers/docs/proto3
|
// Protobuf data type : https://developers.google.com/protocol-buffers/docs/proto3
|
||||||
@ -95,7 +94,7 @@ impl StructTemplate {
|
|||||||
|
|
||||||
pub fn render(&mut self) -> Option<String> {
|
pub fn render(&mut self) -> Option<String> {
|
||||||
self.context.insert("fields", &self.fields);
|
self.context.insert("fields", &self.fields);
|
||||||
let tera = get_tera("proto_file");
|
let tera = get_tera("protobuf_file/template/proto_file");
|
||||||
match tera.render("struct.tera", &self.context) {
|
match tera.render("struct.tera", &self.context) {
|
||||||
Ok(r) => Some(r),
|
Ok(r) => Some(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
@ -1,11 +1,11 @@
|
|||||||
use console::Style;
|
use console::Style;
|
||||||
|
|
||||||
use similar::{ChangeTag, TextDiff};
|
use similar::{ChangeTag, TextDiff};
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::{File, OpenOptions},
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
use tera::Tera;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub fn read_file(path: &str) -> Option<String> {
|
pub fn read_file(path: &str) -> Option<String> {
|
||||||
@ -100,7 +100,7 @@ pub fn create_dir_if_not_exist(dir: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn walk_dir<F1, F2>(dir: &str, filter: F2, mut path_and_name: F1)
|
pub fn walk_dir<F1, F2>(dir: &str, filter: F2, mut path_and_name: F1)
|
||||||
where
|
where
|
||||||
F1: FnMut(String, String),
|
F1: FnMut(String, String),
|
||||||
F2: Fn(&walkdir::DirEntry) -> bool,
|
F2: Fn(&walkdir::DirEntry) -> bool,
|
||||||
@ -126,3 +126,33 @@ pub fn suffix_relative_to_path(path: &str, base: &str) -> String {
|
|||||||
let path = Path::new(path);
|
let path = Path::new(path);
|
||||||
path.strip_prefix(base).unwrap().to_str().unwrap().to_owned()
|
path.strip_prefix(base).unwrap().to_str().unwrap().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_tera(directory: &str) -> Tera {
|
||||||
|
let mut root = format!("{}/src/code_gen/", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
root.push_str(directory);
|
||||||
|
|
||||||
|
let root_absolute_path = match std::fs::canonicalize(&root) {
|
||||||
|
Ok(p) => p.as_path().display().to_string(),
|
||||||
|
Err(e) => {
|
||||||
|
panic!("❌ Canonicalize file path {} failed {:?}", root, e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut template_path = format!("{}/**/*.tera", root_absolute_path);
|
||||||
|
if cfg!(windows) {
|
||||||
|
// remove "\\?\" prefix on windows
|
||||||
|
template_path = format!("{}/**/*.tera", &root_absolute_path[4..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
match Tera::new(template_path.as_ref()) {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Parsing error(s): {}", e);
|
||||||
|
::std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cache_dir() -> String {
|
||||||
|
format!("{}/.cache", env!("CARGO_MANIFEST_DIR"))
|
||||||
|
}
|
@ -1,12 +1,7 @@
|
|||||||
|
pub mod code_gen;
|
||||||
pub mod future;
|
pub mod future;
|
||||||
pub mod retry;
|
pub mod retry;
|
||||||
|
|
||||||
#[cfg(feature = "pb_gen")]
|
|
||||||
pub mod pb;
|
|
||||||
|
|
||||||
#[cfg(feature = "proto_gen")]
|
|
||||||
pub mod proto_gen;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn uuid_string() -> String {
|
pub fn uuid_string() -> String {
|
||||||
uuid::Uuid::new_v4().to_string()
|
uuid::Uuid::new_v4().to_string()
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
#![allow(clippy::module_inception)]
|
|
||||||
mod ast;
|
|
||||||
mod flowy_toml;
|
|
||||||
mod proto_gen;
|
|
||||||
mod proto_info;
|
|
||||||
mod template;
|
|
||||||
pub mod util;
|
|
||||||
|
|
||||||
pub use proto_gen::*;
|
|
||||||
pub use proto_info::*;
|
|
@ -1,47 +0,0 @@
|
|||||||
mod derive_meta;
|
|
||||||
mod proto_file;
|
|
||||||
|
|
||||||
pub use derive_meta::*;
|
|
||||||
pub use proto_file::*;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
use tera::Tera;
|
|
||||||
|
|
||||||
pub fn get_tera(directory: &str) -> Tera {
|
|
||||||
let mut root = format!("{}/src/proto_gen/template/", env!("CARGO_MANIFEST_DIR"));
|
|
||||||
root.push_str(directory);
|
|
||||||
|
|
||||||
let root_absolute_path = match std::fs::canonicalize(&root) {
|
|
||||||
Ok(p) => p.as_path().display().to_string(),
|
|
||||||
Err(e) => {
|
|
||||||
panic!("❌ Canonicalize file path {} failed {:?}", root, e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut template_path = format!("{}/**/*.tera", root_absolute_path);
|
|
||||||
if cfg!(windows) {
|
|
||||||
// remove "\\?\" prefix on windows
|
|
||||||
template_path = format!("{}/**/*.tera", &root_absolute_path[4..]);
|
|
||||||
}
|
|
||||||
|
|
||||||
match Tera::new(template_path.as_ref()) {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Parsing error(s): {}", e);
|
|
||||||
::std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn read_file(path: &str) -> Option<String> {
|
|
||||||
let mut file = File::open(path).unwrap_or_else(|_| panic!("Unable to open file at {}", path));
|
|
||||||
let mut content = String::new();
|
|
||||||
match file.read_to_string(&mut content) {
|
|
||||||
Ok(_) => Some(content),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{}, with error: {:?}", path, e);
|
|
||||||
Some("".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
use lib_infra::pb;
|
use lib_infra::code_gen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pb::gen_files(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"), "./src/protobuf/proto");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user