-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow referencing previously defined named types #51
Conversation
@tPl0ch the CI error seems to be something related to uploading code coverage report, would you have any clues on how to solve that? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @fcoedno,
when seeing your contributions I feel that this library is indeed very valuable to you and that sparks great joy in my heart! ❤️
Would you mind looking at some of the comments and questions I have left so that we can get this merged?
Regarding the CI failures, I believe that the failures are either a glitch of GitHub actions themselves, or something is wrong with the action provider. I will take care of this issue.
@@ -123,7 +123,9 @@ private function schemaFromTypes(Type ...$types): Schema | |||
|
|||
return $this->applyAttributes($schema, $attributes); | |||
default: | |||
throw new \InvalidArgumentException('$type is not a valid avro type'); | |||
$schema = Schema::named($type->getTypeName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you also have the feeling that this method is doing multiple things - it processes the collection of types and a single type. I believe it makes sense to split these into schemaFromTypeCollection
and schemaFromSingleType
.
Additionally I am generally not a huge fan of large switch
/case
blocks. One possilbe other way that I have used is using a map of closures instead:
<?php
$typeProcessorMap = [
TypeName::ENUM => function (SchemaAttributes $attributes) {
return $this->applyAttributes(Schema::enum(), $attributes);
},
// ... more types
];
This map can be defined in the constructor of the SchemaGenerator
class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idd. I've refactored it and splitted in two methods. Also, I've extracted the mapping logic into a separate class and also followed your suggestion of creating an associative array with closures.
@@ -45,6 +45,7 @@ public function it_should_generate_an_empty_record() | |||
->namespace('org.acme'); | |||
|
|||
$this->assertEquals($expected, $schema); | |||
$schema->parse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to parse the schema after the expectation? Is there maybe another test assumption/condition missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not so sure also if it was the best place to do this here. My intention is just to make sure the generated schema object is parseable. There are some checks and validations that will be applied only after we actual do the parsing.
So if anything is wrong, an exception would be raised at this point.
Another idea I had was to create a data provider that would provide the class with the annotations and the expected schema. Then we would have two tests: One to actually see if the generated schema matches the expected one and the other to make sure the generated schema parses without errors.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that testing for the failure conditions should be a separate test. That test can use a data provider to provide invalid edge cases and make sure that an exception is thrown. Right now I believe the tests are mixing up different responsibilities - testing that no exception is thrown and the valid parsing of annotations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idd. Also in this case testing for failures and expect exceptions wouldn't make much sense. Because the parsing and validation of schema is responsibility of the avro-php package. I'm going to remove these "parse" calls
@@ -156,9 +159,17 @@ public function it_should_generate_records_containing_records() | |||
->name('SimpleRecord') | |||
->namespace('org.acme') | |||
->field('intType', Schema::int(), Schema\Record\FieldOption::default(42)) | |||
) | |||
->field( | |||
'union', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should use the name constant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. Here the union name does not represent the union type itself, it is just the name of the field. Maybe the best would be to give the field another name to avoid confusion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name did indeed confuse me. I like the idea of renaming it to something that indicates an example fieldname rather than the type.
It seems that this is a limitation of GitHub Actions that repository secrets are not shared with pipelines running in the forks. I will refactor the actions at a later time and would accept this PR even with this step failing. |
use FlixTech\AvroSerializer\Objects\Schema\AttributeName; | ||
use FlixTech\AvroSerializer\Objects\Schema\TypeName; | ||
|
||
class TypeMapper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This could be a final class
/** | ||
* @param array<Type> $types | ||
*/ | ||
private function schemaFromTypes(array $types): Schema |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain to me why you changed the signature to a simple array over using the variadic type argument?
private function schemaFromTypes(Type ...$types): Schema
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simply to avoid unpacking the arrays when passing arguments to this function. But thinking better about this, we loose a more strict type checking by doing so. Let me revert this change.
1c67fe5
to
b0118da
Compare
Besides fixing the problem of named types itself, I've also found another bug. It was not possible to define extra custom attributes to a record type from the field definition: <?php
/**
* @SerDe\AvroName("simpleField")
* @SerDe\AvroType("record", attributes={
* @SerDe\AvroTargetClass("\FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\SimpleRecord"),
* @SerDe\AvroDoc("This a simple record for testing purposes")
* })
*/
private $simpleRecord; |
Once a named type is defined, in order to reuse that same type it is needed to reference that type by the name (as in the primitive types). Add support for NamedTypes in both the schema builder and the schema generator, which is a way of referencing previously defined named types. Add support for adding extra attributes for records in field's definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@fcoedno Your work is awesome and much appreciated! ❤️ |
Once a named type is defined, in order to reuse that same type it is
needed to reference that type by the name (as in the primitive types).
Add support for NamedTypes in both the schema builder and the schema
generator, which is a way of referencing previously defined named types.
As an example, the following snippet wouldn't work, because the schema cannot be parsed:
With this PR we'll be able to do the following: