diff --git a/Cargo.lock b/Cargo.lock index daedcb9..dfd36f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -528,6 +528,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "issue-60" +version = "1.0.0" +dependencies = [ + "thiserror", + "uniffi", + "uniffi_macros", +] + [[package]] name = "itoa" version = "1.0.3" @@ -1199,6 +1208,7 @@ name = "uniffi-bindgen-cs-fixtures" version = "0.1.0" dependencies = [ "global-methods-class-name", + "issue-60", "null-to-empty-string", "uniffi-cs-custom-types-builtin", "uniffi-cs-disposable-fixture", diff --git a/bindgen/templates/EnumTemplate.cs b/bindgen/templates/EnumTemplate.cs index 435d4b9..6e94ca2 100644 --- a/bindgen/templates/EnumTemplate.cs +++ b/bindgen/templates/EnumTemplate.cs @@ -48,8 +48,8 @@ public override void Write({{ type_name }} value, BigEndianStream stream) { public record {{ variant.name()|class_name }}: {{ type_name }} {} {% else -%} public record {{ variant.name()|class_name }} ( - {% for field in variant.fields() -%} - {{ field|type_name}} {{ field.name()|var_name }}{% if !loop.last %},{% endif %} + {%- for field in variant.fields() %} + {% call cs::enum_parameter_type_name(field|type_name, variant.name()|class_name) %} {{ field.name()|var_name }}{% if !loop.last %},{% endif %} {%- endfor %} ) : {{ type_name }} {} {%- endif %} diff --git a/bindgen/templates/ErrorTemplate.cs b/bindgen/templates/ErrorTemplate.cs index 8e75e6c..e6f8c59 100644 --- a/bindgen/templates/ErrorTemplate.cs +++ b/bindgen/templates/ErrorTemplate.cs @@ -64,13 +64,13 @@ public class {{ variant.name()|exception_name }} : {{ type_name }} {} public class {{ variant.name()|exception_name }} : {{ type_name }} { // Members {%- for field in variant.fields() %} - public {{ field|type_name}} {{ field.name()|var_name }}; + public {% call cs::enum_parameter_type_name(field|type_name, variant.name()|exception_name) %} {{ field.name()|var_name }}; {%- endfor %} // Constructor public {{ variant.name()|exception_name }}( {%- for field in variant.fields() %} - {{ field|type_name}} {{ field.name()|var_name }}{% if loop.last %}{% else %}, {% endif %} + {% call cs::enum_parameter_type_name(field|type_name, variant.name()|exception_name) %} {{ field.name()|var_name }}{% if loop.last %}{% else %}, {% endif %} {%- endfor %}) { {%- for field in variant.fields() %} this.{{ field.name()|var_name }} = {{ field.name()|var_name }}; diff --git a/bindgen/templates/macros.cs b/bindgen/templates/macros.cs index 42b6f47..5ee2581 100644 --- a/bindgen/templates/macros.cs +++ b/bindgen/templates/macros.cs @@ -104,3 +104,21 @@ {%- else %} {%- endmatch %} {%- endmacro %} + +{# +// Break the following cycle, where `Rectangle` case name conflicts with top level `Rectangle` type name. +// If param type name matches the enum name, prefix the param type name with top level namespace. +// https://github.com/NordSecurity/uniffi-bindgen-cs/issues/60 +// public record Rectangle(double @width, double @height) { } +// public record Shape +// { ____________ +// ∨ ∧ +// public record Rectangle(Rectangle @s) : Shape { } +// public record Ellipse(Ellipse @s) : Shape { } +// } +#} +{%- macro enum_parameter_type_name(param_type_name, enum_name) %} +{%- if param_type_name == enum_name %}{{ config.namespace() }}.{{ param_type_name }} +{%- else %}{{ param_type_name }} +{%- endif %} +{%- endmacro %} \ No newline at end of file diff --git a/dotnet-tests/UniffiCS.BindingTests/TestRegressions.cs b/dotnet-tests/UniffiCS.BindingTests/TestRegressions.cs new file mode 100644 index 0000000..489acbd --- /dev/null +++ b/dotnet-tests/UniffiCS.BindingTests/TestRegressions.cs @@ -0,0 +1,17 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +using uniffi.issue_60; + +namespace UniffiCS.BindingTests; + +public class TestRegressions +{ + [Fact] + public void TestIssue60() + { + new Shape.Rectangle(new Rectangle(1f, 2f)); + new ShapeException.Rectangle(new Rectangle(1f, 2f)); + } +} diff --git a/fixtures/Cargo.toml b/fixtures/Cargo.toml index 3f105f3..35116e5 100644 --- a/fixtures/Cargo.toml +++ b/fixtures/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["cdylib", "lib"] [dependencies] global-methods-class-name = { path = "global-methods-class-name" } +issue-60 = { path = "regressions/issue-60" } null-to-empty-string = { path = "null-to-empty-string" } uniffi-cs-custom-types-builtin = { path = "custom-types-builtin" } uniffi-cs-disposable-fixture = { path = "disposable" } diff --git a/fixtures/regressions/issue-60/Cargo.toml b/fixtures/regressions/issue-60/Cargo.toml new file mode 100644 index 0000000..325fcae --- /dev/null +++ b/fixtures/regressions/issue-60/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "issue-60" +version = "1.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["lib", "cdylib"] +name = "issue_60" + +[dependencies] +thiserror = "1.0" +uniffi = {path = "../../../3rd-party/uniffi-rs/uniffi", features=["build"]} +uniffi_macros = {path = "../../../3rd-party/uniffi-rs/uniffi_macros"} + +[build-dependencies] +uniffi = {path = "../../../3rd-party/uniffi-rs/uniffi", features=["bindgen-tests"]} diff --git a/fixtures/regressions/issue-60/src/lib.rs b/fixtures/regressions/issue-60/src/lib.rs new file mode 100644 index 0000000..73f5730 --- /dev/null +++ b/fixtures/regressions/issue-60/src/lib.rs @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::fmt; + +#[derive(uniffi::Enum)] +pub enum Shape { + Rectangle { s: Rectangle }, + Ellipse { s: Ellipse }, +} + +#[derive(Debug, thiserror::Error, uniffi::Error)] +pub enum ShapeError { + #[error("Rectangle: {s}")] + Rectangle { s: Rectangle }, + #[error("Ellipse: {s}")] + Ellipse { s: Ellipse }, +} + +#[derive(uniffi::Record, Debug)] +pub struct Rectangle { + width: f64, + height: f64, +} + +#[derive(uniffi::Record, Debug)] +pub struct Ellipse { + x_radius: f64, + y_radius: f64, +} + +impl fmt::Display for Rectangle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "width: {}, height: {}", self.width, self.height) + } +} + +impl fmt::Display for Ellipse { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "x_radius: {}, y_radius: {}", self.x_radius, self.y_radius) + } +} + +uniffi::setup_scaffolding!(); diff --git a/fixtures/src/lib.rs b/fixtures/src/lib.rs index f35f0ac..f4b68b5 100644 --- a/fixtures/src/lib.rs +++ b/fixtures/src/lib.rs @@ -23,4 +23,5 @@ mod uniffi_fixtures { uniffi_cs_disposable::uniffi_reexport_scaffolding!(); uniffi_cs_optional_parameters::uniffi_reexport_scaffolding!(); stringify::uniffi_reexport_scaffolding!(); + issue_60::uniffi_reexport_scaffolding!(); }