Skip to content

Commit

Permalink
Fix Dart default ctor generation code around Options (rust-diplomat#676)
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth authored Sep 4, 2024
1 parent c2929db commit 253a7c0
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
8 changes: 6 additions & 2 deletions core/src/hir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,13 @@ impl<P: TyPosition> Type<P> {
}
}

/// Whether this type is a `DiplomatOption`
/// Whether this type is a `DiplomatOption` or optional Opaque
pub fn is_option(&self) -> bool {
matches!(self, Self::DiplomatOption(..))
match self {
Self::DiplomatOption(..) => true,
Self::Opaque(ref o) if o.is_optional() => true,
_ => false,
}
}
}

Expand Down
16 changes: 14 additions & 2 deletions feature_tests/dart/lib/src/OptionInputStruct.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions feature_tests/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ pub mod ffi {
c: DiplomatOption<OptionEnum>,
}

impl OptionInputStruct {
// Specifically test the Dart default constructor generation code
// around Options
#[diplomat::attr(not(dart), disable)]
#[diplomat::attr(auto, constructor)]
pub fn default_ctor() -> Self {
Self {
a: None.into(),
b: None.into(),
c: None.into(),
}
}
}

#[diplomat::attr(not(supports = option), disable)]
#[derive(Debug)]
pub enum OptionEnum {
Expand Down
20 changes: 16 additions & 4 deletions tool/src/dart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,15 @@ impl<'a, 'cx> TyGenContext<'a, 'cx> {
// If there's an existing zero-arg constructor, we repurpose it with optional arguments for all fields
let args = fields
.iter()
.map(|field| format!("{}? {}", field.dart_type_name, field.name))
.map(|field| {
let question_mark = if field.ty.is_option() {
// If it's optional we don't need to double-wrap in `?`
""
} else {
"?"
};
format!("{}{question_mark} {}", field.dart_type_name, field.name)
})
.collect::<Vec<_>>();
constructor.declaration =
format!("factory {type_name}({{{args}}})", args = args.join(", "));
Expand All @@ -347,9 +355,13 @@ impl<'a, 'cx> TyGenContext<'a, 'cx> {
writeln!(&mut r, "final dart = {type_name}._fromFfi(result);").unwrap();
for field in &fields {
let name = &field.name;
writeln!(&mut r, "if ({name} != null) {{").unwrap();
writeln!(&mut r, " dart.{name} = {name};").unwrap();
writeln!(&mut r, "}}").unwrap();
if field.ty.is_option() {
writeln!(&mut r, "dart.{name} = {name};").unwrap();
} else {
writeln!(&mut r, "if ({name} != null) {{").unwrap();
writeln!(&mut r, " dart.{name} = {name};").unwrap();
writeln!(&mut r, "}}").unwrap();
}
}
write!(&mut r, "return dart;").unwrap();
constructor.return_expression = Some(r.into());
Expand Down

0 comments on commit 253a7c0

Please sign in to comment.