diff --git a/frb_codegen/src/binary/commands.rs b/frb_codegen/src/binary/commands.rs index 5d95ce3896..602aded9ed 100644 --- a/frb_codegen/src/binary/commands.rs +++ b/frb_codegen/src/binary/commands.rs @@ -88,6 +88,10 @@ pub(crate) struct GenerateCommandArgsPrimary { #[arg(long)] pub dart_format_line_length: Option, + /// Raw header of output generated Dart code, pasted as-it-is. + #[arg(long)] + pub dart_preamble: Option, + /// The generated Dart enums will not have their variant names camelCased. #[arg(long)] pub no_dart_enums_style: bool, diff --git a/frb_codegen/src/binary/commands_parser.rs b/frb_codegen/src/binary/commands_parser.rs index 36a7b6affe..db7669d33f 100644 --- a/frb_codegen/src/binary/commands_parser.rs +++ b/frb_codegen/src/binary/commands_parser.rs @@ -52,6 +52,7 @@ fn compute_codegen_config_from_naive_command_args( rust_output: args.rust_output, dart_entrypoint_class_name: args.dart_entrypoint_class_name, dart_format_line_length: args.dart_format_line_length, + dart_preamble: args.dart_preamble, dart_enums_style: Some(!args.no_dart_enums_style), add_mod_to_lib: Some(!args.no_add_mod_to_lib), llvm_path: args.llvm_path, diff --git a/frb_codegen/src/library/codegen/config/config.rs b/frb_codegen/src/library/codegen/config/config.rs index 2f00a40149..85fd2104ae 100644 --- a/frb_codegen/src/library/codegen/config/config.rs +++ b/frb_codegen/src/library/codegen/config/config.rs @@ -15,6 +15,7 @@ pub struct Config { pub rust_output: Option, pub dart_entrypoint_class_name: Option, pub dart_format_line_length: Option, + pub dart_preamble: Option, pub dart_enums_style: Option, pub add_mod_to_lib: Option, pub llvm_path: Option>, diff --git a/frb_codegen/src/library/codegen/config/internal_config_parser.rs b/frb_codegen/src/library/codegen/config/internal_config_parser.rs index 4154e5caf5..73b14eae29 100644 --- a/frb_codegen/src/library/codegen/config/internal_config_parser.rs +++ b/frb_codegen/src/library/codegen/config/internal_config_parser.rs @@ -119,6 +119,7 @@ impl InternalConfig { dart_entrypoint_class_name: dart_output_class_name_pack .entrypoint_class_name .clone(), + dart_preamble: config.dart_preamble.clone().unwrap_or_default(), }, wire: GeneratorWireInternalConfig { dart: GeneratorWireDartInternalConfig { diff --git a/frb_codegen/src/library/codegen/generator/api_dart/internal_config.rs b/frb_codegen/src/library/codegen/generator/api_dart/internal_config.rs index 12cb0f7c02..38e688da85 100644 --- a/frb_codegen/src/library/codegen/generator/api_dart/internal_config.rs +++ b/frb_codegen/src/library/codegen/generator/api_dart/internal_config.rs @@ -7,4 +7,5 @@ pub(crate) struct GeneratorApiDartInternalConfig { pub dart3: bool, pub dart_decl_base_output_path: PathBuf, pub dart_entrypoint_class_name: String, + pub dart_preamble: String, } diff --git a/frb_codegen/src/library/codegen/generator/api_dart/mod.rs b/frb_codegen/src/library/codegen/generator/api_dart/mod.rs index b58353481c..3c84cf643f 100644 --- a/frb_codegen/src/library/codegen/generator/api_dart/mod.rs +++ b/frb_codegen/src/library/codegen/generator/api_dart/mod.rs @@ -48,21 +48,31 @@ mod tests { use crate::utils::logs::configure_opinionated_test_logging; use crate::utils::test_utils::{get_test_fixture_dir, text_golden_test}; use serial_test::serial; + use std::collections::HashMap; use std::env; #[test] #[serial] fn test_simple() -> anyhow::Result<()> { - body("library/codegen/generator/api_dart/mod/simple") + body( + "library/codegen/generator/api_dart/mod/simple", + HashMap::from([ + ("api.dart", "expect_output.dart"), + ("dep.dart", "expect_output2.dart"), + ]), + ) } #[test] #[serial] fn test_functions() -> anyhow::Result<()> { - body("library/codegen/generator/api_dart/mod/functions") + body( + "library/codegen/generator/api_dart/mod/functions", + HashMap::from([("api.dart", "expect_output.dart")]), + ) } - fn body(fixture_name: &str) -> anyhow::Result<()> { + fn body(fixture_name: &str, expect_outputs: HashMap<&str, &str>) -> anyhow::Result<()> { configure_opinionated_test_logging(); let test_fixture_dir = get_test_fixture_dir(fixture_name); env::set_current_dir(&test_fixture_dir)?; @@ -83,10 +93,13 @@ mod tests { )?; let output_texts = actual.output_texts; - assert_eq!(output_texts.0.len(), 1); - - let raw_text = (output_texts.0[0].text).replace(env!("CARGO_PKG_VERSION"), "{VERSION}"); - text_golden_test(raw_text, &test_fixture_dir.join("expect_output.dart"))?; + assert_eq!(output_texts.0.len(), expect_outputs.len()); + for path_text in output_texts.0 { + let path = path_text.path.file_name().unwrap().to_str().unwrap(); + let expect_output = expect_outputs.get(path).unwrap(); + let raw_text = (path_text.text).replace(env!("CARGO_PKG_VERSION"), "{VERSION}"); + text_golden_test(raw_text, &test_fixture_dir.join(expect_output))?; + } Ok(()) } diff --git a/frb_codegen/src/library/codegen/generator/api_dart/spec_generator/mod.rs b/frb_codegen/src/library/codegen/generator/api_dart/spec_generator/mod.rs index 4e34035cc6..08fc97fd9b 100644 --- a/frb_codegen/src/library/codegen/generator/api_dart/spec_generator/mod.rs +++ b/frb_codegen/src/library/codegen/generator/api_dart/spec_generator/mod.rs @@ -40,6 +40,7 @@ pub(crate) struct ApiDartOutputSpecItem { pub funcs: Vec, pub classes: Vec, pub imports: DartBasicHeaderCode, + pub preamble: String, pub unused_types: Vec, pub needs_freezed: bool, } @@ -134,6 +135,7 @@ fn generate_item( funcs, classes, imports, + preamble: context.config.dart_preamble.clone(), unused_types, needs_freezed, }) diff --git a/frb_codegen/src/library/codegen/generator/api_dart/text_generator.rs b/frb_codegen/src/library/codegen/generator/api_dart/text_generator.rs index dca717eaaf..9aef083dd6 100644 --- a/frb_codegen/src/library/codegen/generator/api_dart/text_generator.rs +++ b/frb_codegen/src/library/codegen/generator/api_dart/text_generator.rs @@ -59,8 +59,10 @@ fn generate_end_api_text( // TODO use relative path calculation let path_frb_generated = "../".repeat(path_chunks_len - 2) + "frb_generated.dart"; + let preamble = &item.preamble.as_str(); let mut header = DartBasicHeaderCode { file_top: generate_code_header() + + if !preamble.is_empty() {"\n\n"} else {""} + preamble + "\n\n// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import\n", import: format!( " diff --git a/frb_codegen/src/library/codegen/generator/wire/dart/spec_generator/misc/mod.rs b/frb_codegen/src/library/codegen/generator/wire/dart/spec_generator/misc/mod.rs index 225c104f3c..0e62402f46 100644 --- a/frb_codegen/src/library/codegen/generator/wire/dart/spec_generator/misc/mod.rs +++ b/frb_codegen/src/library/codegen/generator/wire/dart/spec_generator/misc/mod.rs @@ -79,7 +79,9 @@ fn generate_boilerplate( .. } = &context.config.dart_output_class_name_pack; + let dart_preamble = &context.api_dart_config.dart_preamble.as_str(); let file_top = generate_code_header() + + if !dart_preamble.is_empty() {"\n\n"} else {""} + dart_preamble + "\n\n// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field\n"; let mut universal_imports = generate_import_dart_api_layer( diff --git a/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/single_rust_input/expect_output.json b/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/single_rust_input/expect_output.json index cb7dd6f80d..3afc43a3d9 100644 --- a/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/single_rust_input/expect_output.json +++ b/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/single_rust_input/expect_output.json @@ -20,7 +20,8 @@ "dart3": true, "dart_decl_base_output_path": "{the-working-directory}/my_dart_folder", "dart_entrypoint_class_name": "RustLib", - "dart_enums_style": true + "dart_enums_style": true, + "dart_preamble": "" }, "wire": { "c": { diff --git a/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/wildcard_rust_input/expect_output.json b/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/wildcard_rust_input/expect_output.json index 27942f99b8..57ddebdf42 100644 --- a/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/wildcard_rust_input/expect_output.json +++ b/frb_codegen/test_fixtures/library/codegen/config/internal_config_parser/wildcard_rust_input/expect_output.json @@ -20,7 +20,8 @@ "dart3": true, "dart_decl_base_output_path": "{the-working-directory}/my_dart_folder", "dart_entrypoint_class_name": "RustLib", - "dart_enums_style": true + "dart_enums_style": true, + "dart_preamble": "" }, "wire": { "c": { diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output.dart b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output.dart index e630ccbfe7..820b484ef4 100644 --- a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output.dart +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output.dart @@ -2,8 +2,11 @@ // This file is automatically generated, so please do not edit it. // Generated by `flutter_rust_bridge`@ {VERSION}. +// test for dart_preamble + // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import +import 'dep.dart'; import 'frb_generated.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; @@ -12,5 +15,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; Future firstFunction({dynamic hint}) => RustLib.instance.api.crateApiFirstFunction(hint: hint); +Future secondFunction({required Simple arg , dynamic hint}) => RustLib.instance.api.crateApiSecondFunction(arg: arg, hint: hint); + \ No newline at end of file diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output2.dart b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output2.dart new file mode 100644 index 0000000000..0a5202a7f0 --- /dev/null +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/expect_output2.dart @@ -0,0 +1,39 @@ + + // This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ {VERSION}. + +// test for dart_preamble + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + + + + + + + class Simple { + final int val; + + const Simple({required this.val ,}); + + + + + + @override + int get hashCode => val.hashCode; + + + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Simple && + runtimeType == other.runtimeType + && val == other.val; + + } + \ No newline at end of file diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/flutter_rust_bridge.yaml b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/flutter_rust_bridge.yaml index eb15b30ea2..4632478305 100644 --- a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/flutter_rust_bridge.yaml +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/flutter_rust_bridge.yaml @@ -1,3 +1,4 @@ rust_input: src/api.rs dart_output: . c_output: frb_generated.h +dart_preamble: "// test for dart_preamble" diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/api.rs b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/api.rs index 001e0c67a3..7661af1a37 100644 --- a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/api.rs +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/api.rs @@ -1 +1,4 @@ +use super::dep::Simple; + pub fn first_function() {} +pub fn second_function(arg: Simple) {} diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/dep.rs b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/dep.rs new file mode 100644 index 0000000000..f7d0d2061d --- /dev/null +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/dep.rs @@ -0,0 +1,3 @@ +pub struct Simple{ + val:u32 +} diff --git a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/lib.rs b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/lib.rs index b32f9e29f1..baa02899c3 100644 --- a/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/lib.rs +++ b/frb_codegen/test_fixtures/library/codegen/generator/api_dart/mod/simple/src/lib.rs @@ -1 +1,2 @@ mod api; +mod dep; diff --git a/website/docs/generated/_frb-codegen-command-generate.mdx b/website/docs/generated/_frb-codegen-command-generate.mdx index f2b60cf716..6d96cf1e4a 100644 --- a/website/docs/generated/_frb-codegen-command-generate.mdx +++ b/website/docs/generated/_frb-codegen-command-generate.mdx @@ -36,6 +36,9 @@ Options: --dart-format-line-length Line length for Dart formatting + --dart-preamble + Raw header of output generated Dart code, pasted as-it-is + --no-dart-enums-style The generated Dart enums will not have their variant names camelCased