Skip to content

Commit baa304c

Browse files
committed
test: add fixtures to test function codegen
1 parent 01d7e83 commit baa304c

File tree

21 files changed

+150
-50
lines changed

21 files changed

+150
-50
lines changed

Cargo.lock

+23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frb_codegen/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ notify = "6.1.1"
5555
notify-debouncer-mini = "0.4.1"
5656

5757
[dev-dependencies]
58+
pretty_assertions = "1.4.0"
5859
semver = "1.0.12"
5960

6061
[package.metadata.binstall]

frb_codegen/src/library/codegen/generator/api_dart/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ mod tests {
5656
body("library/codegen/generator/api_dart/mod/simple")
5757
}
5858

59+
#[test]
60+
#[serial]
61+
fn test_functions() -> anyhow::Result<()> {
62+
body("library/codegen/generator/api_dart/mod/functions")
63+
}
64+
5965
fn body(fixture_name: &str) -> anyhow::Result<()> {
6066
configure_opinionated_test_logging();
6167
let test_fixture_dir = get_test_fixture_dir(fixture_name);

frb_codegen/src/library/codegen/generator/api_dart/spec_generator/class/field.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,19 @@ fn default_value_maybe_to_dart_style(value: &str, enable: bool) -> Cow<str> {
5151
}
5252

5353
fn default_value_to_dart_style(value: &str) -> String {
54-
let mut split = value.split('.');
55-
let enum_name = split.next().unwrap();
56-
57-
let variant_name = split.next().unwrap().to_string();
58-
let variant_name = make_string_keyword_safe(variant_name.to_case(Case::Camel));
59-
60-
format!("{enum_name}.{variant_name}")
54+
match value.split_once('.') {
55+
// If the user is explicitly calling an enum variant's constructor
56+
// i.e. `const Foo.bar()` instead of `Foo.Bar`, we trust that they
57+
// really mean it and don't convert.
58+
Some((enum_name, variant_name))
59+
if !enum_name.starts_with("const ") && !variant_name.contains('(') =>
60+
{
61+
format!(
62+
"{}.{}",
63+
enum_name,
64+
make_string_keyword_safe(variant_name.to_string()).to_case(Case::Camel)
65+
)
66+
}
67+
_ => value.to_string(),
68+
}
6169
}

frb_codegen/src/library/codegen/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::codegen::dumper::Dumper;
1616
use crate::codegen::misc::GeneratorProgressBarPack;
1717
use crate::codegen::parser::reader::CachedRustReader;
1818
pub use config::config::{Config, MetaConfig};
19-
pub use config::config_parser::*;
19+
2020
pub use dumper::internal_config::ConfigDumpContent;
2121
use log::debug;
2222

frb_codegen/src/library/commands/cargo_expand.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ use crate::codegen::dumper::Dumper;
22
use crate::codegen::ConfigDumpContent;
33
use crate::command_args;
44
use crate::library::commands::command_runner::execute_command;
5+
56
use anyhow::{bail, Context, Result};
67
use itertools::Itertools;
8+
use lazy_static::lazy_static;
79
use log::{debug, info, warn};
810
use regex::Regex;
11+
12+
use std::borrow::Cow;
913
use std::collections::hash_map::Entry::{Occupied, Vacant};
1014
use std::collections::HashMap;
1115
use std::path::{Path, PathBuf};
12-
use std::sync::OnceLock;
1316
use std::{env, fs};
1417

1518
#[derive(Default)]
@@ -41,7 +44,10 @@ impl CachedCargoExpand {
4144

4245
let expanded = match self.cache.entry(rust_crate_dir.to_owned()) {
4346
Occupied(entry) => entry.into_mut(),
44-
Vacant(entry) => entry.insert(run_cargo_expand(rust_crate_dir, dumper, true)?),
47+
Vacant(entry) => entry.insert(
48+
unwrap_frb_attrs_in_doc(&run_cargo_expand(rust_crate_dir, dumper, true)?)
49+
.into_owned(),
50+
),
4551
};
4652

4753
extract_module(expanded, module)
@@ -93,7 +99,7 @@ fn run_cargo_expand(
9399
"--theme=none",
94100
"--ugly",
95101
"--config",
96-
"build.rustflags=\"--cfg frb_expand\""
102+
r#"build.rustflags="--cfg frb_expand""#
97103
);
98104

99105
let output = execute_command("cargo", &args, Some(rust_crate_dir), None)
@@ -114,20 +120,22 @@ fn run_cargo_expand(
114120
// frb-coverage:ignore-end
115121
}
116122

117-
let mut stdout_lines = stdout.lines();
118-
stdout_lines.next();
119-
let ans = stdout_lines.join("\n");
120-
static PATTERN: OnceLock<Regex> = OnceLock::new();
121-
let pattern = PATTERN.get_or_init(|| {
122-
Regex::new(r####"#\[doc =[\s\n]*r###"frb_marker: ([\s\S]*?)"###]"####).unwrap()
123-
});
124-
let ans = pattern.replace_all(&ans, "$1").into_owned();
125-
123+
let ans = stdout.lines().skip(1).join("\n");
126124
dumper.dump_str(ConfigDumpContent::Source, "cargo_expand.rs", &ans)?;
127-
128125
Ok(ans)
129126
}
130127

128+
/// Turns `#[doc = "frb_marker: .."]` back into `#[frb(..)]`, usually produced
129+
/// as a side-effect of cargo-expand.
130+
// NOTE: The amount of pounds must match exactly with the implementation in frb_macros
131+
fn unwrap_frb_attrs_in_doc(code: &str) -> Cow<str> {
132+
lazy_static! {
133+
static ref PATTERN: Regex =
134+
Regex::new(r####"#\[doc =[\s\n]*r###"frb_marker: ([\s\S]*?)"###]"####).unwrap();
135+
}
136+
PATTERN.replace_all(code, "$1")
137+
}
138+
131139
fn install_cargo_expand() -> Result<()> {
132140
execute_command(
133141
"cargo",

frb_codegen/src/library/commands/command_runner.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ macro_rules! command_run {
3838
}};
3939
}
4040

41-
/// Formats a list of [`PathBuf`]s using the syntax detailed in [`run`].
41+
/// Formats a list of [`PathBuf`]s using the syntax detailed in [`command_run`].
4242
#[doc(hidden)]
4343
#[macro_export]
4444
macro_rules! command_args {

frb_codegen/src/library/integration/integrator.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn integrate(config: IntegrateConfig) -> Result<()> {
6363
fn modify_permissions(dart_root: &Path) -> Result<()> {
6464
let dir_cargokit = dart_root.join("rust_builder").join("cargokit");
6565

66-
#[cfg(not(windows))]
66+
#[cfg(unix)]
6767
{
6868
set_permission_executable(&dir_cargokit.join("build_pod.sh"))?;
6969
set_permission_executable(&dir_cargokit.join("run_build_tool.sh"))?;
@@ -82,7 +82,7 @@ fn setup_cargokit_dependencies(dart_root: &Path) -> Result<()> {
8282
flutter_pub_get(&build_tool_dir)
8383
}
8484

85-
#[cfg(not(windows))]
85+
#[cfg(unix)]
8686
fn set_permission_executable(path: &Path) -> Result<()> {
8787
use std::os::unix::fs::PermissionsExt;
8888

frb_codegen/src/library/utils/test_utils.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,43 @@ pub(crate) fn json_golden_test(
2828
let actual: Value = serde_json::from_str(&actual_str)?;
2929
debug!("json_golden_test sanitizers={sanitizers:?} actual:\n{actual_str}");
3030

31-
raw_golden_test(actual, &actual_str, matcher_path, |x| {
32-
Ok(serde_json::from_str(&x)?)
33-
})
31+
raw_golden_test(
32+
actual,
33+
&actual_str,
34+
matcher_path,
35+
|x| Ok(serde_json::from_str(&x)?),
36+
None,
37+
)
3438
}
3539

3640
pub(crate) fn text_golden_test(actual: String, matcher_path: &Path) -> anyhow::Result<()> {
37-
raw_golden_test(actual.clone(), &actual, matcher_path, |x| {
41+
raw_golden_test(
42+
actual.clone(),
43+
&actual,
44+
matcher_path,
3845
// Otherwise tests in macos/linux passes but fails on windows
39-
Ok(x.replace("\r\n", "\n"))
40-
})
46+
|x| Ok(x.replace("\r\n", "\n")),
47+
Some(|expect, actual| {
48+
#[cfg(test)]
49+
use pretty_assertions::assert_str_eq as assert_eq;
50+
assert_eq!(expect, actual);
51+
}),
52+
)
4153
}
4254

4355
fn raw_golden_test<T, F>(
4456
actual: T,
4557
actual_str: &str,
4658
matcher_path: &Path,
4759
deserializer: F,
60+
asserter: Option<fn(&T, &T)>,
4861
) -> anyhow::Result<()>
4962
where
5063
T: Eq + Debug,
5164
F: Fn(String) -> anyhow::Result<T>,
5265
{
66+
#[cfg(test)]
67+
use pretty_assertions::assert_eq;
5368
// This is *test* utils, not a part of real codegen, so no need to consider coverage
5469
// frb-coverage:ignore-start
5570
let expect = deserializer(if matcher_path.exists() {
@@ -64,7 +79,8 @@ where
6479
fs::write(matcher_path, actual_str)?;
6580
}
6681
} else {
67-
assert_eq!(actual, expect);
82+
let asserter = asserter.unwrap_or(|expect, actual| assert_eq!(expect, actual));
83+
asserter(&expect, &actual);
6884
}
6985

7086
Ok(())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "example"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
flutter_rust_bridge_macros.path = "../../../../../../../../frb_macros"
10+
11+
[workspace]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
// This file is automatically generated, so please do not edit it.
3+
// Generated by `flutter_rust_bridge`@ {VERSION}.
4+
5+
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
6+
7+
import 'frb_generated.dart';
8+
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
9+
10+
11+
Future<void> fnWithDefaultArg({int foo = 1, dynamic hint}) => RustLib.instance.api.fnWithDefaultArg(foo: foo, hint: hint);
12+
13+
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
rust_input: src/api.rs
2+
dart_output: .
3+
c_output: frb_generated.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name: fake_dart_package
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[flutter_rust_bridge_macros::frb]
2+
pub fn fn_with_default_arg(#[frb(default = 1)] foo: i32) {
3+
drop(foo);
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod api;

frb_example/pure_dart_pde/lib/src/rust/api/attribute.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Future<void> handleCustomizedStructTwinNormal(
1414
RustLib.instance.api.handleCustomizedStructTwinNormal(val: val, hint: hint);
1515

1616
Future<UserIdTwinNormal> nextUserIdTwinNormal(
17-
{required UserIdTwinNormal userId, dynamic hint}) =>
17+
{UserIdTwinNormal userId = const UserIdTwinNormal(), dynamic hint}) =>
1818
RustLib.instance.api.nextUserIdTwinNormal(userId: userId, hint: hint);
1919

2020
class CustomizedTwinNormal {

frb_example/pure_dart_pde/lib/src/rust/api/pseudo_manual/attribute_twin_rust_async.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Future<void> handleCustomizedStructTwinRustAsync(
1515
.handleCustomizedStructTwinRustAsync(val: val, hint: hint);
1616

1717
Future<UserIdTwinRustAsync> nextUserIdTwinRustAsync(
18-
{required UserIdTwinRustAsync userId, dynamic hint}) =>
18+
{UserIdTwinRustAsync userId = const UserIdTwinRustAsync(),
19+
dynamic hint}) =>
1920
RustLib.instance.api.nextUserIdTwinRustAsync(userId: userId, hint: hint);
2021

2122
class CustomizedTwinRustAsync {

frb_example/pure_dart_pde/lib/src/rust/api/pseudo_manual/attribute_twin_sync.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ void handleCustomizedStructTwinSync(
1414
RustLib.instance.api.handleCustomizedStructTwinSync(val: val, hint: hint);
1515

1616
UserIdTwinSync nextUserIdTwinSync(
17-
{required UserIdTwinSync userId, dynamic hint}) =>
17+
{UserIdTwinSync userId = const UserIdTwinSync(), dynamic hint}) =>
1818
RustLib.instance.api.nextUserIdTwinSync(userId: userId, hint: hint);
1919

2020
class CustomizedTwinSync {

frb_example/pure_dart_pde/lib/src/rust/frb_generated.dart

+7-6
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ abstract class RustLibApi extends BaseApi {
219219
{required CustomizedTwinNormal val, dynamic hint});
220220

221221
Future<UserIdTwinNormal> nextUserIdTwinNormal(
222-
{required UserIdTwinNormal userId, dynamic hint});
222+
{UserIdTwinNormal userId = const UserIdTwinNormal(), dynamic hint});
223223

224224
void benchmarkVoidSemiSerialize({dynamic hint});
225225

@@ -735,13 +735,13 @@ abstract class RustLibApi extends BaseApi {
735735
{required CustomizedTwinRustAsync val, dynamic hint});
736736

737737
Future<UserIdTwinRustAsync> nextUserIdTwinRustAsync(
738-
{required UserIdTwinRustAsync userId, dynamic hint});
738+
{UserIdTwinRustAsync userId = const UserIdTwinRustAsync(), dynamic hint});
739739

740740
void handleCustomizedStructTwinSync(
741741
{required CustomizedTwinSync val, dynamic hint});
742742

743743
UserIdTwinSync nextUserIdTwinSync(
744-
{required UserIdTwinSync userId, dynamic hint});
744+
{UserIdTwinSync userId = const UserIdTwinSync(), dynamic hint});
745745

746746
Future<BasicGeneralEnumTwinNormal>
747747
exampleBasicTypeBasicGeneralEnumTwinNormalTwinNormal(
@@ -3715,7 +3715,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
37153715

37163716
@override
37173717
Future<UserIdTwinNormal> nextUserIdTwinNormal(
3718-
{required UserIdTwinNormal userId, dynamic hint}) {
3718+
{UserIdTwinNormal userId = const UserIdTwinNormal(), dynamic hint}) {
37193719
return handler.executeNormal(NormalTask(
37203720
callFfi: (port_) {
37213721
final serializer = SseSerializer(generalizedFrbRustBinding);
@@ -8498,7 +8498,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
84988498

84998499
@override
85008500
Future<UserIdTwinRustAsync> nextUserIdTwinRustAsync(
8501-
{required UserIdTwinRustAsync userId, dynamic hint}) {
8501+
{UserIdTwinRustAsync userId = const UserIdTwinRustAsync(),
8502+
dynamic hint}) {
85028503
return handler.executeNormal(NormalTask(
85038504
callFfi: (port_) {
85048505
final serializer = SseSerializer(generalizedFrbRustBinding);
@@ -8550,7 +8551,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
85508551

85518552
@override
85528553
UserIdTwinSync nextUserIdTwinSync(
8553-
{required UserIdTwinSync userId, dynamic hint}) {
8554+
{UserIdTwinSync userId = const UserIdTwinSync(), dynamic hint}) {
85548555
return handler.executeSync(SyncTask(
85558556
callFfi: () {
85568557
final serializer = SseSerializer(generalizedFrbRustBinding);

0 commit comments

Comments
 (0)