Skip to content

Commit

Permalink
bugfix: ensure field names and error interface function don't clash (#34
Browse files Browse the repository at this point in the history
)

* bugfix: ensure field names and error interface function don't clash

Fixes #30

* Review comments

* Review comments

* Also assert Error_
  • Loading branch information
kegsay authored Jan 8, 2024
1 parent 4095f60 commit a2d2500
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 6 deletions.
10 changes: 10 additions & 0 deletions bindgen/src/gen_go/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,16 @@ pub mod filters {
Ok(nm.to_string().to_upper_camel_case())
}

pub fn error_field_name(nm: &str) -> Result<String, askama::Error> {
// Fields called 'Error' can clash with structs which implement the error
// interface, causing a compilation error. Suffix with _ similar to reserved
// keywords in var names.
if nm == "error" {
return Ok(String::from("Error_"));
}
Ok(nm.to_string().to_upper_camel_case())
}

pub fn type_name(type_: &impl AsType) -> Result<String, askama::Error> {
Ok(oracle().find(type_).type_label())
}
Expand Down
12 changes: 6 additions & 6 deletions bindgen/templates/ErrorTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type {{ variant_class_name }} struct {
message string
{%- else %}
{%- for field in variant.fields() %}
{{ field.name()|field_name }} {{ field|type_name}}
{{ field.name()|error_field_name }} {{ field|type_name}}
{%- endfor %}
{%- endif %}
}
Expand All @@ -44,7 +44,7 @@ func New{{ variant_class_name }}(
err: &{{ variant_class_name }}{
{%- if !e.is_flat() %}
{%- for field in variant.fields() %}
{{ field.name()|field_name }}: {{ field.name()|var_name }},
{{ field.name()|error_field_name }}: {{ field.name()|var_name }},
{%- endfor %}
{%- endif %}
},
Expand All @@ -60,8 +60,8 @@ func (err {{ variant_class_name }}) Error() string {
{% if !variant.fields().is_empty() %}": ",{% endif %}
{%- for field in variant.fields() %}
{% if !loop.first %}", ",{% endif %}
"{{ field.name()|field_name }}=",
err.{{ field.name()|field_name }},
"{{ field.name()|error_field_name }}=",
err.{{ field.name()|error_field_name }},
{%- endfor %}
)
}
Expand Down Expand Up @@ -107,7 +107,7 @@ func (c {{ e|ffi_converter_name }}) Read(reader io.Reader) error {
case {{ loop.index }}:
return &{{ type_name|class_name }}{&{{ type_name|class_name }}{{ variant.name()|class_name }}{
{%- for field in variant.fields() %}
{{ field.name()|field_name }}: {{ field|read_fn }}(reader),
{{ field.name()|error_field_name }}: {{ field|read_fn }}(reader),
{%- endfor %}
}}
{%- endfor %}
Expand All @@ -124,7 +124,7 @@ func (c {{ e|ffi_converter_name }}) Write(writer io.Writer, value *{{ type_name|
case *{{ type_name }}{{ variant.name()|class_name }}:
writeInt32(writer, {{ loop.index }})
{%- for field in variant.fields() %}
{{ field|write_fn }}(writer, variantValue.{{ field.name()|field_name }})
{{ field|write_fn }}(writer, variantValue.{{ field.name()|error_field_name }})
{%- endfor %}
{%- endfor %}
default:
Expand Down
10 changes: 10 additions & 0 deletions binding_tests/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,13 @@ func TestComplexErrorAsBase(t *testing.T) {
assert.ErrorAs(t, err, &expectedError)
assert.EqualError(t, expectedError, "ValidationError: InvalidUserAndMessage: UserId=100, Message=byebye")
}

func TestErrorNamedError(t *testing.T) {
// this test exists to ensure ErrorNamedError is not removed from the UDL without causing test failures.
// The purpose of ErrorNamedError is to ensure that the generated bindings produce compilable Go code,
// so there isn't really anything to actually test at runtime.
err := errors.NewErrorNamedErrorError("it's an error")
var expectedError *errors.ErrorNamedError
assert.ErrorAs(t, err, &expectedError)
assert.Equal(t, "it's an error", expectedError.Unwrap().(*errors.ErrorNamedErrorError).Error_)
}
5 changes: 5 additions & 0 deletions fixtures/errors/src/errors.udl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ interface ValidationError {
UnknownError();
};

[Error]
interface ErrorNamedError {
Error(string error);
};

[Error]
interface ComplexError {
Struct(Vec2 position_a, Vec2 position_b);
Expand Down
6 changes: 6 additions & 0 deletions fixtures/errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ pub enum ValidationError {
UnknownError,
}

#[derive(Debug, thiserror::Error)]
pub enum ErrorNamedError {
#[error("Error {error}")]
Error { error: String },
}

#[derive(Debug, thiserror::Error)]
pub enum ComplexError {
#[error("Struct")]
Expand Down

0 comments on commit a2d2500

Please sign in to comment.