mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: delete flowy-tool
This commit is contained in:
10
frontend/scripts/flowy-tool/.gitignore
vendored
10
frontend/scripts/flowy-tool/.gitignore
vendored
@ -1,10 +0,0 @@
|
|||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
/target/
|
|
||||||
|
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
|
||||||
**/*.rs.bk
|
|
@ -1,27 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "flowy-tool"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
clap = "2.33.3"
|
|
||||||
walkdir = "2.3.1"
|
|
||||||
syn = { version = "1.0.60", features = ["extra-traits", "parsing", "derive", "full"]}
|
|
||||||
tera = { version = "1.5.0" }
|
|
||||||
log = "0.4.11"
|
|
||||||
env_logger = "0.8.2"
|
|
||||||
#shell = { git="https://github.com/google/rust-shell.git"}
|
|
||||||
cmd_lib = "1.1"
|
|
||||||
flowy-ast = { path = "../../../shared-lib/flowy-ast" }
|
|
||||||
console = "0.14.0"
|
|
||||||
fancy-regex = "0.10.0"
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
phf = { version = "0.8.0", features = ["macros"] }
|
|
||||||
similar = "1.2.2"
|
|
||||||
dialoguer = "0.8.0"
|
|
||||||
toml = "0.5.8"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
pathdiff = "0.2.0"
|
|
||||||
itertools = "0.10"
|
|
@ -1,15 +0,0 @@
|
|||||||
use std::fs;
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
pub struct FlowyConfig {
|
|
||||||
pub proto_crates: Vec<String>,
|
|
||||||
pub event_files: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlowyConfig {
|
|
||||||
pub fn from_toml_file(path: &str) -> Self {
|
|
||||||
let content = fs::read_to_string(path).unwrap();
|
|
||||||
let config: FlowyConfig = toml::from_str(content.as_ref()).unwrap();
|
|
||||||
config
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,136 +0,0 @@
|
|||||||
use super::event_template::*;
|
|
||||||
|
|
||||||
use crate::util::*;
|
|
||||||
use flowy_ast::{event_ast::*, *};
|
|
||||||
use syn::Item;
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
pub struct DartEventCodeGen {
|
|
||||||
pub rust_sources: Vec<String>,
|
|
||||||
pub output_dir: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DartEventCodeGen {
|
|
||||||
pub fn gen(&self) {
|
|
||||||
let event_crates = parse_dart_event_files(self.rust_sources.clone());
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
save_content_to_file_with_diff_prompt(
|
|
||||||
render_result.as_ref(),
|
|
||||||
self.output_dir.as_str(),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DartEventCrate {
|
|
||||||
crate_path: String,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
crate_name: String,
|
|
||||||
event_files: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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(roots: Vec<String>) -> Vec<DartEventCrate> {
|
|
||||||
let mut dart_event_crates: Vec<DartEventCrate> = vec![];
|
|
||||||
roots.iter().for_each(|root| {
|
|
||||||
let crates = WalkDir::new(root)
|
|
||||||
.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());
|
|
||||||
// eprintln!(
|
|
||||||
// "😁 {:?} / {:?}",
|
|
||||||
// event_ast.event_input, event_ast.event_output
|
|
||||||
// );
|
|
||||||
|
|
||||||
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>>()
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
use crate::util::get_tera;
|
|
||||||
use tera::Context;
|
|
||||||
|
|
||||||
pub struct EventTemplate {
|
|
||||||
tera_context: Context,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const DART_IMPORTED: &str = r#"
|
|
||||||
/// Auto gen code from rust ast, do not edit
|
|
||||||
part of 'dispatch.dart';
|
|
||||||
"#;
|
|
||||||
|
|
||||||
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> {
|
|
||||||
if index == 0 {
|
|
||||||
self.tera_context
|
|
||||||
.insert("imported_dart_files", DART_IMPORTED)
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
{%- if index == 0 %}
|
|
||||||
{{ imported_dart_files }}
|
|
||||||
{%- endif -%}
|
|
||||||
|
|
||||||
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 %}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
#![allow(clippy::module_inception)]
|
|
||||||
mod dart_event;
|
|
||||||
mod event_template;
|
|
||||||
|
|
||||||
pub use dart_event::*;
|
|
@ -1,95 +0,0 @@
|
|||||||
mod config;
|
|
||||||
mod dart_event;
|
|
||||||
mod proto;
|
|
||||||
mod util;
|
|
||||||
use clap::{App, Arg};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
std::env::set_var("RUST_LOG", "Info");
|
|
||||||
env_logger::init();
|
|
||||||
|
|
||||||
let matches = app().get_matches();
|
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("pb-gen") {
|
|
||||||
let rust_sources: Vec<String> = matches
|
|
||||||
.values_of("rust_sources")
|
|
||||||
.unwrap()
|
|
||||||
.map(|value| value.to_owned())
|
|
||||||
.collect();
|
|
||||||
let derive_meta = matches.value_of("derive_meta").unwrap();
|
|
||||||
let flutter_package_lib = matches.value_of("flutter_package_lib").unwrap();
|
|
||||||
|
|
||||||
proto::ProtoGenBuilder::new()
|
|
||||||
.set_rust_source_dirs(rust_sources)
|
|
||||||
.set_derive_meta_dir(derive_meta)
|
|
||||||
.set_flutter_package_lib(flutter_package_lib)
|
|
||||||
.build()
|
|
||||||
.gen();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("dart-event") {
|
|
||||||
let rust_sources: Vec<String> = matches
|
|
||||||
.values_of("rust_sources")
|
|
||||||
.unwrap()
|
|
||||||
.map(|value| value.to_owned())
|
|
||||||
.collect();
|
|
||||||
let output_dir = matches.value_of("output").unwrap().to_string();
|
|
||||||
|
|
||||||
let code_gen = dart_event::DartEventCodeGen {
|
|
||||||
rust_sources,
|
|
||||||
output_dir,
|
|
||||||
};
|
|
||||||
code_gen.gen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn app<'a, 'b>() -> App<'a, 'b> {
|
|
||||||
let app = App::new("flowy-tool")
|
|
||||||
.version("0.1")
|
|
||||||
.author("nathan")
|
|
||||||
.about("flowy tool")
|
|
||||||
.subcommand(
|
|
||||||
App::new("pb-gen")
|
|
||||||
.about("Generate proto file from rust code")
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("rust_sources")
|
|
||||||
.long("rust_sources")
|
|
||||||
.multiple(true)
|
|
||||||
.required(true)
|
|
||||||
.min_values(1)
|
|
||||||
.value_name("DIRECTORY")
|
|
||||||
.help("Directories of the cargo workspace"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("derive_meta")
|
|
||||||
.long("derive_meta")
|
|
||||||
.value_name("PATH")
|
|
||||||
.help("Caching information used by flowy-derive"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("flutter_package_lib")
|
|
||||||
.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_sources")
|
|
||||||
.long("rust_sources")
|
|
||||||
.multiple(true)
|
|
||||||
.required(true)
|
|
||||||
.min_values(1)
|
|
||||||
.value_name("DIRECTORY")
|
|
||||||
.help("Directories of the cargo workspace"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("output")
|
|
||||||
.long("output")
|
|
||||||
.value_name("DIRECTORY"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
app
|
|
||||||
}
|
|
@ -1,189 +0,0 @@
|
|||||||
use crate::proto::proto_info::*;
|
|
||||||
use crate::proto::template::{EnumTemplate, StructTemplate};
|
|
||||||
use crate::util::*;
|
|
||||||
use fancy_regex::Regex;
|
|
||||||
use flowy_ast::*;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use std::{fs::File, io::Read, path::Path};
|
|
||||||
use syn::Item;
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
pub fn parse_crate_protobuf(roots: Vec<String>) -> Vec<CrateProtoInfo> {
|
|
||||||
let crate_infos = parse_crate_info_from_path(roots);
|
|
||||||
crate_infos
|
|
||||||
.into_iter()
|
|
||||||
.map(|crate_info| {
|
|
||||||
let proto_output_dir = crate_info.proto_file_output_dir();
|
|
||||||
let files = crate_info
|
|
||||||
.proto_paths
|
|
||||||
.iter()
|
|
||||||
.map(|proto_crate_path| parse_files_protobuf(proto_crate_path, &proto_output_dir))
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<ProtoFile>>();
|
|
||||||
|
|
||||||
CrateProtoInfo::from_crate_info(crate_info, files)
|
|
||||||
})
|
|
||||||
.collect::<Vec<CrateProtoInfo>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec<ProtoFile> {
|
|
||||||
let mut gen_proto_vec: Vec<ProtoFile> = 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()
|
|
||||||
.filter_entry(|e| !is_hidden(e))
|
|
||||||
.filter_map(|e| e.ok())
|
|
||||||
.filter(|e| !e.file_type().is_dir())
|
|
||||||
.map(|e| {
|
|
||||||
let path = e.path().to_str().unwrap().to_string();
|
|
||||||
let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
|
|
||||||
(path, file_name)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
if file_name == "mod" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://docs.rs/syn/1.0.54/syn/struct.File.html
|
|
||||||
let ast = syn::parse_file(read_file(&path).unwrap().as_ref())
|
|
||||||
.unwrap_or_else(|_| panic!("Unable to parse file at {}", path));
|
|
||||||
let structs = get_ast_structs(&ast);
|
|
||||||
let proto_file_path = format!("{}/{}.proto", &proto_output_dir, &file_name);
|
|
||||||
let mut proto_file_content = parse_or_init_proto_file(proto_file_path.as_ref());
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
let s = struct_template.render().unwrap();
|
|
||||||
proto_file_content.push_str(s.as_ref());
|
|
||||||
proto_file_content.push('\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
let enums = get_ast_enums(&ast);
|
|
||||||
enums.iter().for_each(|e| {
|
|
||||||
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');
|
|
||||||
});
|
|
||||||
|
|
||||||
if !enums.is_empty() || !structs.is_empty() {
|
|
||||||
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(),
|
|
||||||
};
|
|
||||||
gen_proto_vec.push(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_proto_vec
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_or_init_proto_file(path: &str) -> String {
|
|
||||||
let mut proto_file_content = String::new();
|
|
||||||
let imported_content = find_proto_file_import(path);
|
|
||||||
proto_file_content.push_str(imported_content.as_ref());
|
|
||||||
proto_file_content.push('\n');
|
|
||||||
proto_file_content
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_ast_structs(ast: &syn::File) -> Vec<Struct> {
|
|
||||||
// let mut content = format!("{:#?}", &ast);
|
|
||||||
// let mut file = File::create("./foo.txt").unwrap();
|
|
||||||
// file.write_all(content.as_bytes()).unwrap();
|
|
||||||
let ctxt = Ctxt::new();
|
|
||||||
let mut proto_structs: Vec<Struct> = vec![];
|
|
||||||
ast.items.iter().for_each(|item| {
|
|
||||||
if let Item::Struct(item_struct) = item {
|
|
||||||
let (_, fields) = struct_from_ast(&ctxt, &item_struct.fields);
|
|
||||||
|
|
||||||
if fields
|
|
||||||
.iter()
|
|
||||||
.filter(|f| f.attrs.pb_index().is_some())
|
|
||||||
.count()
|
|
||||||
> 0
|
|
||||||
{
|
|
||||||
proto_structs.push(Struct {
|
|
||||||
name: item_struct.ident.to_string(),
|
|
||||||
fields,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ctxt.check().unwrap();
|
|
||||||
proto_structs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_ast_enums(ast: &syn::File) -> Vec<FlowyEnum> {
|
|
||||||
let mut flowy_enums: Vec<FlowyEnum> = vec![];
|
|
||||||
let ctxt = Ctxt::new();
|
|
||||||
|
|
||||||
ast.items.iter().for_each(|item| {
|
|
||||||
// https://docs.rs/syn/1.0.54/syn/enum.Item.html
|
|
||||||
if let Item::Enum(item_enum) = item {
|
|
||||||
let attrs =
|
|
||||||
flowy_ast::enum_from_ast(&ctxt, &item_enum.ident, &item_enum.variants, &ast.attrs);
|
|
||||||
flowy_enums.push(FlowyEnum {
|
|
||||||
name: item_enum.ident.to_string(),
|
|
||||||
attrs,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ctxt.check().unwrap();
|
|
||||||
flowy_enums
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FlowyEnum<'a> {
|
|
||||||
pub name: String,
|
|
||||||
pub attrs: Vec<ASTEnumVariant<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Struct<'a> {
|
|
||||||
pub name: String,
|
|
||||||
pub fields: Vec<ASTField<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref SYNTAX_REGEX: Regex = Regex::new("syntax.*;").unwrap();
|
|
||||||
static ref IMPORT_REGEX: Regex = Regex::new("(import\\s).*;").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_proto_file_import(path: &str) -> String {
|
|
||||||
let mut result = String::new();
|
|
||||||
if !Path::new(path).exists() {
|
|
||||||
// log::error!("{} not exist", path);
|
|
||||||
result = String::from("syntax = \"proto3\";");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut file = File::open(path).unwrap();
|
|
||||||
let mut content = String::new();
|
|
||||||
file.read_to_string(&mut content).unwrap();
|
|
||||||
|
|
||||||
content.lines().for_each(|line| {
|
|
||||||
////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');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
use crate::proto::ProtoGen;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct ProtoGenBuilder {
|
|
||||||
rust_source_dirs: Option<Vec<String>>,
|
|
||||||
flutter_package_lib: Option<String>,
|
|
||||||
derive_meta_dir: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProtoGenBuilder {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
ProtoGenBuilder {
|
|
||||||
rust_source_dirs: None,
|
|
||||||
flutter_package_lib: None,
|
|
||||||
derive_meta_dir: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_rust_source_dirs(mut self, dirs: Vec<String>) -> Self {
|
|
||||||
self.rust_source_dirs = Some(dirs);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_flutter_package_lib(mut self, dir: &str) -> Self {
|
|
||||||
self.flutter_package_lib = Some(dir.to_string());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_derive_meta_dir(mut self, dir: &str) -> Self {
|
|
||||||
self.derive_meta_dir = Some(dir.to_string());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(self) -> ProtoGen {
|
|
||||||
ProtoGen {
|
|
||||||
rust_source_dirs: self.rust_source_dirs.unwrap(),
|
|
||||||
flutter_package_lib: self.flutter_package_lib.unwrap(),
|
|
||||||
derive_meta_dir: self.derive_meta_dir.unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
mod ast;
|
|
||||||
mod builder;
|
|
||||||
mod proto_gen;
|
|
||||||
mod proto_info;
|
|
||||||
mod template;
|
|
||||||
|
|
||||||
pub use builder::*;
|
|
||||||
pub use proto_gen::*;
|
|
@ -1,170 +0,0 @@
|
|||||||
#![allow(clippy::all)]
|
|
||||||
#![allow(unused_attributes)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_results)]
|
|
||||||
use crate::proto::ast::*;
|
|
||||||
use crate::proto::proto_info::*;
|
|
||||||
use crate::{proto::template::*, util::*};
|
|
||||||
use std::path::Path;
|
|
||||||
use std::{fs::OpenOptions, io::Write};
|
|
||||||
|
|
||||||
pub struct ProtoGen {
|
|
||||||
pub(crate) rust_source_dirs: Vec<String>,
|
|
||||||
pub(crate) flutter_package_lib: String,
|
|
||||||
pub(crate) derive_meta_dir: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProtoGen {
|
|
||||||
pub fn gen(&self) {
|
|
||||||
let crate_proto_infos = parse_crate_protobuf(self.rust_source_dirs.clone());
|
|
||||||
write_proto_files(&crate_proto_infos);
|
|
||||||
run_rust_protoc(&crate_proto_infos);
|
|
||||||
|
|
||||||
// write_rust_crate_mod_file(&crate_proto_infos);
|
|
||||||
write_derive_meta(&crate_proto_infos, self.derive_meta_dir.as_ref());
|
|
||||||
|
|
||||||
// let flutter_package = FlutterProtobufInfo::new(self.flutter_package_lib.as_ref());
|
|
||||||
// run_flutter_protoc(&crate_proto_infos, &flutter_package);
|
|
||||||
// write_flutter_protobuf_package_mod_file(&crate_proto_infos, &flutter_package);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_proto_files(crate_infos: &[CrateProtoInfo]) {
|
|
||||||
for crate_info in crate_infos {
|
|
||||||
let dir = crate_info.inner.proto_file_output_dir();
|
|
||||||
crate_info.files.iter().for_each(|info| {
|
|
||||||
let proto_file_path = format!("{}/{}.proto", dir, &info.file_name);
|
|
||||||
save_content_to_file_with_diff_prompt(
|
|
||||||
&info.generated_content,
|
|
||||||
proto_file_path.as_ref(),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_rust_crate_mod_file(crate_infos: &[CrateProtoInfo]) {
|
|
||||||
for crate_info in crate_infos {
|
|
||||||
let mod_path = crate_info.inner.proto_model_mod_file();
|
|
||||||
match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.append(false)
|
|
||||||
.truncate(true)
|
|
||||||
.open(&mod_path)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => {
|
|
||||||
let mut mod_file_content = String::new();
|
|
||||||
|
|
||||||
mod_file_content.push_str("#![cfg_attr(rustfmt, rustfmt::skip)]\n");
|
|
||||||
mod_file_content.push_str("// Auto-generated, do not edit\n");
|
|
||||||
walk_dir(
|
|
||||||
crate_info.inner.proto_file_output_dir().as_ref(),
|
|
||||||
|e| !e.file_type().is_dir(),
|
|
||||||
|_, name| {
|
|
||||||
let c = format!("\nmod {};\npub use {}::*;\n", &name, &name);
|
|
||||||
mod_file_content.push_str(c.as_ref());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
file.write_all(mod_file_content.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
panic!("Failed to open file: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_flutter_protobuf_package_mod_file(
|
|
||||||
crate_infos: &[CrateProtoInfo],
|
|
||||||
package_info: &FlutterProtobufInfo,
|
|
||||||
) {
|
|
||||||
let model_dir = package_info.model_dir();
|
|
||||||
for crate_info in crate_infos {
|
|
||||||
let mod_path = crate_info.flutter_mod_file(model_dir.as_str());
|
|
||||||
match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.append(false)
|
|
||||||
.truncate(true)
|
|
||||||
.open(&mod_path)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => {
|
|
||||||
let mut mod_file_content = String::new();
|
|
||||||
mod_file_content.push_str("// Auto-generated, do not edit \n");
|
|
||||||
|
|
||||||
walk_dir(
|
|
||||||
crate_info.inner.proto_file_output_dir().as_ref(),
|
|
||||||
|e| !e.file_type().is_dir(),
|
|
||||||
|_, name| {
|
|
||||||
let c = format!("export './{}.pb.dart';\n", &name);
|
|
||||||
mod_file_content.push_str(c.as_ref());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write_all(mod_file_content.as_bytes()).unwrap();
|
|
||||||
file.flush().unwrap();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
panic!("Failed to open file: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_rust_protoc(crate_infos: &[CrateProtoInfo]) {
|
|
||||||
for crate_info in crate_infos {
|
|
||||||
let rust_out = crate_info.inner.proto_struct_output_dir();
|
|
||||||
let proto_path = crate_info.inner.proto_file_output_dir();
|
|
||||||
walk_dir(
|
|
||||||
proto_path.as_ref(),
|
|
||||||
|e| is_proto_file(e),
|
|
||||||
|proto_file, _| {
|
|
||||||
if cmd_lib::run_cmd! {
|
|
||||||
protoc --rust_out=${rust_out} --proto_path=${proto_path} ${proto_file}
|
|
||||||
}
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
panic!("Run flutter protoc fail")
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
crate_info.create_crate_mod_file();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_flutter_protoc(crate_infos: &[CrateProtoInfo], package_info: &FlutterProtobufInfo) {
|
|
||||||
let model_dir = package_info.model_dir();
|
|
||||||
if !Path::new(&model_dir).exists() {
|
|
||||||
std::fs::create_dir_all(&model_dir).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
for crate_info in crate_infos {
|
|
||||||
let proto_path = crate_info.inner.proto_file_output_dir();
|
|
||||||
let crate_module_dir = crate_info.flutter_mod_dir(model_dir.as_str());
|
|
||||||
remove_everything_in_dir(crate_module_dir.as_str());
|
|
||||||
|
|
||||||
walk_dir(
|
|
||||||
proto_path.as_ref(),
|
|
||||||
|e| is_proto_file(e),
|
|
||||||
|proto_file, _| {
|
|
||||||
if cmd_lib::run_cmd! {
|
|
||||||
protoc --dart_out=${crate_module_dir} --proto_path=${proto_path} ${proto_file}
|
|
||||||
}
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
panic!("Run flutter protoc fail")
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_everything_in_dir(dir: &str) {
|
|
||||||
if Path::new(dir).exists() && std::fs::remove_dir_all(dir).is_err() {
|
|
||||||
panic!("Reset protobuf directory failed")
|
|
||||||
}
|
|
||||||
std::fs::create_dir_all(dir).unwrap();
|
|
||||||
}
|
|
@ -1,137 +0,0 @@
|
|||||||
#![allow(clippy::all)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
use crate::util::*;
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::Write;
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
pub struct CrateProtoInfo {
|
|
||||||
pub files: Vec<ProtoFile>,
|
|
||||||
pub inner: ProtobufCrate,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CrateProtoInfo {
|
|
||||||
pub fn from_crate_info(inner: ProtobufCrate, files: Vec<ProtoFile>) -> Self {
|
|
||||||
Self { files, inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_crate_mod_file(&self) {
|
|
||||||
// mod model;
|
|
||||||
// pub use model::*;
|
|
||||||
let mod_file_path = format!("{}/mod.rs", self.inner.protobuf_crate_name());
|
|
||||||
let mut content = "#![cfg_attr(rustfmt, rustfmt::skip)]\n".to_owned();
|
|
||||||
content.push_str("// Auto-generated, do not edit\n");
|
|
||||||
content.push_str("mod model;\npub use model::*;");
|
|
||||||
match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.append(false)
|
|
||||||
.truncate(true)
|
|
||||||
.open(&mod_file_path)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => {
|
|
||||||
file.write_all(content.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
panic!("Failed to open protobuf mod file: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flutter_mod_dir(&self, root: &str) -> String {
|
|
||||||
let crate_module_dir = format!("{}/{}", root, self.inner.folder_name);
|
|
||||||
crate_module_dir
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flutter_mod_file(&self, root: &str) -> String {
|
|
||||||
let crate_module_dir = format!("{}/{}/protobuf.dart", root, self.inner.folder_name);
|
|
||||||
crate_module_dir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct ProtobufCrate {
|
|
||||||
pub folder_name: String,
|
|
||||||
pub proto_paths: Vec<String>,
|
|
||||||
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 ProtoFile {
|
|
||||||
pub file_path: String,
|
|
||||||
pub file_name: String,
|
|
||||||
pub structs: Vec<String>,
|
|
||||||
pub enums: Vec<String>,
|
|
||||||
pub generated_content: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_crate_info_from_path(roots: Vec<String>) -> Vec<ProtobufCrate> {
|
|
||||||
let mut protobuf_crates: Vec<ProtobufCrate> = vec![];
|
|
||||||
roots.iter().for_each(|root| {
|
|
||||||
let crates = 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(ProtobufCrate::from_config)
|
|
||||||
.collect::<Vec<ProtobufCrate>>();
|
|
||||||
protobuf_crates.extend(crates);
|
|
||||||
});
|
|
||||||
protobuf_crates
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FlutterProtobufInfo {
|
|
||||||
package_path: String,
|
|
||||||
}
|
|
||||||
impl FlutterProtobufInfo {
|
|
||||||
pub fn new(root: &str) -> Self {
|
|
||||||
FlutterProtobufInfo {
|
|
||||||
package_path: root.to_owned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn model_dir(&self) -> String {
|
|
||||||
let model_dir = format!("{}/protobuf", self.package_path);
|
|
||||||
create_dir_if_not_exist(model_dir.as_ref());
|
|
||||||
model_dir
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn mod_file_path(&self) -> String {
|
|
||||||
let mod_file_path = format!("{}/protobuf.dart", self.package_path);
|
|
||||||
mod_file_path
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
#![allow(clippy::all)]
|
|
||||||
#![allow(unused_attributes)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_results)]
|
|
||||||
use crate::proto::proto_info::{CrateProtoInfo, ProtoFile};
|
|
||||||
use crate::util::{get_tera, read_file};
|
|
||||||
use itertools::Itertools;
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::Write;
|
|
||||||
use tera::Context;
|
|
||||||
|
|
||||||
pub struct ProtobufDeriveMeta {
|
|
||||||
context: Context,
|
|
||||||
structs: Vec<String>,
|
|
||||||
enums: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl ProtobufDeriveMeta {
|
|
||||||
pub fn new(structs: Vec<String>, enums: Vec<String>) -> Self {
|
|
||||||
let enums: Vec<_> = enums.into_iter().unique().collect();
|
|
||||||
ProtobufDeriveMeta {
|
|
||||||
context: Context::new(),
|
|
||||||
structs,
|
|
||||||
enums,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(&mut self) -> Option<String> {
|
|
||||||
self.context.insert("names", &self.structs);
|
|
||||||
self.context.insert("enums", &self.enums);
|
|
||||||
|
|
||||||
let tera = get_tera("proto/template/derive_meta");
|
|
||||||
match tera.render("derive_meta.tera", &self.context) {
|
|
||||||
Ok(r) => Some(r),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_derive_meta(crate_infos: &[CrateProtoInfo], derive_meta_dir: &str) {
|
|
||||||
let file_proto_infos = crate_infos
|
|
||||||
.iter()
|
|
||||||
.map(|ref crate_info| &crate_info.files)
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<&ProtoFile>>();
|
|
||||||
|
|
||||||
let structs: Vec<String> = file_proto_infos
|
|
||||||
.iter()
|
|
||||||
.map(|info| info.structs.clone())
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
let enums: Vec<String> = file_proto_infos
|
|
||||||
.iter()
|
|
||||||
.map(|info| info.enums.clone())
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut derive_template = ProtobufDeriveMeta::new(structs, enums);
|
|
||||||
let new_content = derive_template.render().unwrap();
|
|
||||||
let old_content = read_file(derive_meta_dir).unwrap();
|
|
||||||
if new_content == old_content {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// println!("{}", diff_lines(&old_content, &new_content));
|
|
||||||
match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.append(false)
|
|
||||||
.truncate(true)
|
|
||||||
.open(derive_meta_dir)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => {
|
|
||||||
file.write_all(new_content.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
panic!("Failed to open log file: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
|
||||||
pub enum TypeCategory {
|
|
||||||
Array,
|
|
||||||
Map,
|
|
||||||
Str,
|
|
||||||
Protobuf,
|
|
||||||
Bytes,
|
|
||||||
Enum,
|
|
||||||
Opt,
|
|
||||||
Primitive,
|
|
||||||
}
|
|
||||||
// auto generate, do not edit
|
|
||||||
pub fn category_from_str(type_str: &str) -> TypeCategory {
|
|
||||||
match type_str {
|
|
||||||
"Vec" => TypeCategory::Array,
|
|
||||||
"HashMap" => TypeCategory::Map,
|
|
||||||
"u8" => TypeCategory::Bytes,
|
|
||||||
"String" => TypeCategory::Str,
|
|
||||||
{%- for name in names -%}
|
|
||||||
{%- if loop.first %}
|
|
||||||
"{{ name }}"
|
|
||||||
{%- else %}
|
|
||||||
| "{{ name }}"
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if loop.last %}
|
|
||||||
=> TypeCategory::Protobuf,
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
{%- for enum in enums -%}
|
|
||||||
{%- if loop.first %}
|
|
||||||
"{{ enum }}"
|
|
||||||
{%- else %}
|
|
||||||
| "{{ enum }}"
|
|
||||||
{%- endif -%}
|
|
||||||
{%- if loop.last %}
|
|
||||||
=> TypeCategory::Enum,
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
"Option" => TypeCategory::Opt,
|
|
||||||
_ => TypeCategory::Primitive,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
#![allow(clippy::module_inception)]
|
|
||||||
mod derive_meta;
|
|
||||||
|
|
||||||
pub use derive_meta::*;
|
|
@ -1,5 +0,0 @@
|
|||||||
mod derive_meta;
|
|
||||||
mod proto_file;
|
|
||||||
|
|
||||||
pub use derive_meta::*;
|
|
||||||
pub use proto_file::*;
|
|
@ -1,5 +0,0 @@
|
|||||||
enum {{ enum_name }} {
|
|
||||||
{%- for item in items %}
|
|
||||||
{{ item }}
|
|
||||||
{%- endfor %}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
use crate::proto::ast::FlowyEnum;
|
|
||||||
use crate::util::get_tera;
|
|
||||||
use tera::Context;
|
|
||||||
|
|
||||||
pub struct EnumTemplate {
|
|
||||||
context: Context,
|
|
||||||
items: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl EnumTemplate {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
EnumTemplate {
|
|
||||||
context: Context::new(),
|
|
||||||
items: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_message_enum(&mut self, flowy_enum: &FlowyEnum) {
|
|
||||||
self.context.insert("enum_name", &flowy_enum.name);
|
|
||||||
flowy_enum.attrs.iter().for_each(|item| {
|
|
||||||
self.items.push(format!(
|
|
||||||
"{} = {};",
|
|
||||||
item.attrs.enum_item_name, item.attrs.value
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(&mut self) -> Option<String> {
|
|
||||||
self.context.insert("items", &self.items);
|
|
||||||
let tera = get_tera("proto/template/proto_file");
|
|
||||||
match tera.render("enum.tera", &self.context) {
|
|
||||||
Ok(r) => Some(r),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
mod enum_template;
|
|
||||||
mod struct_template;
|
|
||||||
|
|
||||||
pub use enum_template::*;
|
|
||||||
pub use struct_template::*;
|
|
@ -1,5 +0,0 @@
|
|||||||
message {{ struct_name }} {
|
|
||||||
{%- for field in fields %}
|
|
||||||
{{ field }}
|
|
||||||
{%- endfor %}
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
use crate::util::get_tera;
|
|
||||||
use flowy_ast::*;
|
|
||||||
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! {
|
|
||||||
"String" => "string",
|
|
||||||
"i64" => "int64",
|
|
||||||
"i32" => "int32",
|
|
||||||
"u64" => "uint64",
|
|
||||||
"u32" => "uint32",
|
|
||||||
"u8" => "uint8",
|
|
||||||
"Vec" => "repeated",
|
|
||||||
"f64" => "double",
|
|
||||||
"HashMap" => "map",
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct StructTemplate {
|
|
||||||
context: Context,
|
|
||||||
fields: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl StructTemplate {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
StructTemplate {
|
|
||||||
context: Context::new(),
|
|
||||||
fields: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_message_struct_name(&mut self, name: &str) {
|
|
||||||
self.context.insert("struct_name", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_field(&mut self, field: &ASTField) {
|
|
||||||
// {{ field_type }} {{ field_name }} = {{index}};
|
|
||||||
let name = field.name().unwrap().to_string();
|
|
||||||
let index = field.attrs.pb_index().unwrap();
|
|
||||||
|
|
||||||
let ty: &str = &field.ty_as_str();
|
|
||||||
let mut mapped_ty: &str = ty;
|
|
||||||
|
|
||||||
if RUST_TYPE_MAP.contains_key(ty) {
|
|
||||||
mapped_ty = RUST_TYPE_MAP[ty];
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref category) = field.bracket_category {
|
|
||||||
match category {
|
|
||||||
BracketCategory::Opt => match &field.bracket_inner_ty {
|
|
||||||
None => {}
|
|
||||||
Some(inner_ty) => match inner_ty.to_string().as_str() {
|
|
||||||
//TODO: support hashmap or something else wrapped by Option
|
|
||||||
"Vec" => {
|
|
||||||
self.fields.push(format!(
|
|
||||||
"oneof one_of_{} {{ bytes {} = {}; }};",
|
|
||||||
name, name, index
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.fields.push(format!(
|
|
||||||
"oneof one_of_{} {{ {} {} = {}; }};",
|
|
||||||
name, mapped_ty, name, index
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
BracketCategory::Map((k, v)) => {
|
|
||||||
let key: &str = k;
|
|
||||||
let value: &str = v;
|
|
||||||
self.fields.push(format!(
|
|
||||||
// map<string, string> attrs = 1;
|
|
||||||
"map<{}, {}> {} = {};",
|
|
||||||
RUST_TYPE_MAP.get(key).unwrap_or(&key),
|
|
||||||
RUST_TYPE_MAP.get(value).unwrap_or(&value),
|
|
||||||
name,
|
|
||||||
index
|
|
||||||
));
|
|
||||||
}
|
|
||||||
BracketCategory::Vec => {
|
|
||||||
let bracket_ty: &str = &field.bracket_ty.as_ref().unwrap().to_string();
|
|
||||||
// Vec<u8>
|
|
||||||
if mapped_ty == "u8" && bracket_ty == "Vec" {
|
|
||||||
self.fields.push(format!("bytes {} = {};", name, index))
|
|
||||||
} else {
|
|
||||||
self.fields.push(format!(
|
|
||||||
"{} {} {} = {};",
|
|
||||||
RUST_TYPE_MAP[bracket_ty], mapped_ty, name, index
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BracketCategory::Other => self
|
|
||||||
.fields
|
|
||||||
.push(format!("{} {} = {};", mapped_ty, name, index)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(&mut self) -> Option<String> {
|
|
||||||
self.context.insert("fields", &self.fields);
|
|
||||||
let tera = get_tera("proto/template/proto_file");
|
|
||||||
match tera.render("struct.tera", &self.context) {
|
|
||||||
Ok(r) => Some(r),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{:?}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
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<String> {
|
|
||||||
let proto_paths = self
|
|
||||||
.flowy_config
|
|
||||||
.proto_crates
|
|
||||||
.iter()
|
|
||||||
.map(|name| format!("{}/{}", self.crate_path, name))
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
proto_paths
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_crate_config_from(entry: &walkdir::DirEntry) -> Option<CrateConfig> {
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,171 +0,0 @@
|
|||||||
use console::Style;
|
|
||||||
|
|
||||||
use similar::{ChangeTag, TextDiff};
|
|
||||||
use std::{
|
|
||||||
fs::{File, OpenOptions},
|
|
||||||
io::{Read, Write},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
use tera::Tera;
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
let write_to_file = || match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.append(false)
|
|
||||||
.truncate(true)
|
|
||||||
.open(output_file)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => {
|
|
||||||
file.write_all(new_content.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
panic!("Failed to open log file: {}", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if new_content != old_content {
|
|
||||||
print_diff(old_content, new_content.clone());
|
|
||||||
write_to_file()
|
|
||||||
// if force_write {
|
|
||||||
// write_to_file()
|
|
||||||
// } else {
|
|
||||||
// if Confirm::new().with_prompt("Override?").interact().unwrap() {
|
|
||||||
// write_to_file()
|
|
||||||
// } else {
|
|
||||||
// tracing::info!("never mind then :(");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match OpenOptions::new()
|
|
||||||
.create(true)
|
|
||||||
.write(true)
|
|
||||||
.open(output_file)
|
|
||||||
{
|
|
||||||
Ok(ref mut file) => file.write_all(content.as_bytes()).unwrap(),
|
|
||||||
Err(err) => panic!("Open or create to {} fail: {}", output_file, err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_diff(old_content: String, new_content: String) {
|
|
||||||
let diff = TextDiff::from_lines(&old_content, &new_content);
|
|
||||||
for op in diff.ops() {
|
|
||||||
for change in diff.iter_changes(op) {
|
|
||||||
let (sign, style) = match change.tag() {
|
|
||||||
ChangeTag::Delete => ("-", Style::new().red()),
|
|
||||||
ChangeTag::Insert => ("+", Style::new().green()),
|
|
||||||
ChangeTag::Equal => (" ", Style::new()),
|
|
||||||
};
|
|
||||||
|
|
||||||
match change.tag() {
|
|
||||||
ChangeTag::Delete => {
|
|
||||||
print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change));
|
|
||||||
}
|
|
||||||
ChangeTag::Insert => {
|
|
||||||
print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change));
|
|
||||||
}
|
|
||||||
ChangeTag::Equal => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
println!("---------------------------------------------------");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_tera(directory: &str) -> Tera {
|
|
||||||
let mut root = "./scripts/flowy-tool/src/".to_owned();
|
|
||||||
root.push_str(directory);
|
|
||||||
|
|
||||||
let root_absolute_path = std::fs::canonicalize(root)
|
|
||||||
.unwrap()
|
|
||||||
.as_path()
|
|
||||||
.display()
|
|
||||||
.to_string();
|
|
||||||
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 is_crate_dir(e: &walkdir::DirEntry) -> bool {
|
|
||||||
let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string();
|
|
||||||
cargo == *"Cargo"
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
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<F1, F2>(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn suffix_relative_to_path(path: &str, base: &str) -> String {
|
|
||||||
let base = Path::new(base);
|
|
||||||
let path = Path::new(path);
|
|
||||||
path.strip_prefix(base)
|
|
||||||
.unwrap()
|
|
||||||
.to_str()
|
|
||||||
.unwrap()
|
|
||||||
.to_owned()
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
mod crate_config;
|
|
||||||
mod file;
|
|
||||||
|
|
||||||
pub use crate_config::*;
|
|
||||||
pub use file::*;
|
|
@ -55,79 +55,6 @@ dart pub global activate protoc_plugin
|
|||||||
script_runner = "@shell"
|
script_runner = "@shell"
|
||||||
|
|
||||||
|
|
||||||
[tasks.gen_pb_file]
|
|
||||||
script = [
|
|
||||||
"""
|
|
||||||
flowy_tool=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
|
||||||
rust_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
|
||||||
shared_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared-lib
|
|
||||||
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
|
||||||
|
|
||||||
derive_meta=${shared_lib}/flowy-derive/src/derive_cache/derive_cache.rs
|
|
||||||
flutter_package_lib=${flutter_lib}/flowy_sdk/lib
|
|
||||||
|
|
||||||
cargo run \
|
|
||||||
--manifest-path ${flowy_tool} pb-gen \
|
|
||||||
--rust_sources ${rust_lib} ${shared_lib} \
|
|
||||||
--derive_meta=${derive_meta} \
|
|
||||||
--flutter_package_lib=${flutter_package_lib}
|
|
||||||
""",
|
|
||||||
]
|
|
||||||
script_runner = "@shell"
|
|
||||||
|
|
||||||
|
|
||||||
[tasks.gen_pb_file.windows]
|
|
||||||
script = [
|
|
||||||
"""
|
|
||||||
flowy_tool=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
|
||||||
rust_source=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
|
||||||
# rust_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib
|
|
||||||
shared_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/../shared-lib
|
|
||||||
flutter_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
|
||||||
|
|
||||||
derive_meta=set ${shared_lib}/flowy-derive/src/derive_cache/derive_cache.rs
|
|
||||||
flutter_package_lib=set ${flutter_lib}/flowy_sdk/lib
|
|
||||||
|
|
||||||
exec cmd /c cargo run \
|
|
||||||
--manifest-path ${flowy_tool} pb-gen \
|
|
||||||
--rust_source=${rust_source} \
|
|
||||||
--derive_meta=${derive_meta} \
|
|
||||||
--flutter_package_lib=${flutter_package_lib}
|
|
||||||
""",
|
|
||||||
]
|
|
||||||
script_runner = "@duckscript"
|
|
||||||
|
|
||||||
|
|
||||||
[tasks.gen_dart_event]
|
|
||||||
script = [
|
|
||||||
"""
|
|
||||||
flowy_tool=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
|
||||||
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
|
||||||
|
|
||||||
rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
|
||||||
output=${flutter_lib}/flowy_sdk/lib/dispatch/dart_event.dart
|
|
||||||
|
|
||||||
cargo run \
|
|
||||||
--manifest-path ${flowy_tool} dart-event \
|
|
||||||
--rust_sources=${rust_source} \
|
|
||||||
--output=${output}
|
|
||||||
""",
|
|
||||||
]
|
|
||||||
script_runner = "@shell"
|
|
||||||
|
|
||||||
[tasks.gen_dart_event.windows]
|
|
||||||
script = [
|
|
||||||
"""
|
|
||||||
flowy_tool=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
|
||||||
flutter_lib=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
|
||||||
|
|
||||||
rust_source=set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
|
||||||
output=set ${flutter_lib}/flowy_sdk/lib/dispatch/dart_event.dart
|
|
||||||
|
|
||||||
exec cmd.exe /c cargo run \
|
|
||||||
--manifest-path ${flowy_tool} dart-event \
|
|
||||||
--rust_source=${rust_source} \
|
|
||||||
--output=${output}
|
|
||||||
""",
|
|
||||||
]
|
|
||||||
script_runner = "@duckscript"
|
|
||||||
|
Reference in New Issue
Block a user