-
Notifications
You must be signed in to change notification settings - Fork 133
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
RUMM-1000 Add support for additional properties to the models generation pipeline #399
RUMM-1000 Add support for additional properties to the models generation pipeline #399
Conversation
…ToSwiftTypeTransformer
…iftType transformer
…s in Objc Interop
…dditionalProperties
…e and use it for additionalProperties
…r after adding support for additionalProperties
…additional properties to a later stage in RUMSwiftTypeTransformer
…we introduce a model with addional properties
) | ||
propertyWrapper.objcInteropType = try objcInteropType(for: swiftArray) | ||
return propertyWrapper | ||
case let swiftDictionary as SwiftDictionary where swiftDictionary.value is SwiftPrimitiveType: |
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 whole function comes from the block of code previously starting at line 35. But I want to draw attention to this case that handles a SwiftDictionary
.
@@ -89,11 +129,59 @@ public class SwiftPrinter: BasePrinter { | |||
writeLine("}") | |||
} | |||
|
|||
private func printCodableMethods(for properties: [SwiftStruct.Property], additionalProperties: SwiftStruct.Property) throws { |
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.
Please see the associated tests for a preview of the output:
https://github.com/DataDog/dd-sdk-ios/pull/399/files#diff-fcc08ef045de4c9d692921649cfe668e0900e3900473a1e5702383cc67c37efa
…onalProperties as simple Swift Dictionaries
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.
Looks way simpler and much more straightforward now 🚀. I left some comments that we may consider to simplify it even further - let me know WDYT.
let isRequired: Bool | ||
let isReadOnly: Bool | ||
} | ||
|
||
let name: String | ||
let comment: String? | ||
let properties: [Property] | ||
let additionalProperties: Property? |
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 think that we're using the Property
type here with a wrong purpose. Looking at how "additionalProperties" work, only Property.type
, Property.isReadOnly
and Property.comment
apply to it and we force artificial / uncontrolled values for name
, defaultValue
and isRequired
. Maybe it's worth introducing separate type: JSONObject.AdditionalProperties(comment:type:isReadOnly)
, WDYT?
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 think that it's a good point and good idea!
case let swiftDictionary as SwiftDictionary where swiftDictionary.key is SwiftEnum || swiftDictionary.value is SwiftEnum: | ||
throw Exception.unimplemented( | ||
"Objc Interop for `SwiftDictionary`s with an Enum as key or value is not supported." | ||
) |
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.
Maybe it's easier to change SwiftDictionary.value
to be SwiftPrimitiveType
to have compile-time check for this?
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.
That's a good idea, and similarly SwiftDictionary.key
should be a SwiftPrimitiveType
for now.
internal struct SwiftDictionary: SwiftType { | ||
var key: SwiftType | ||
var value: SwiftType | ||
} |
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.
IMO we can save some control flows / tests if being more tailored on that, i.e.:
var key: SwiftPrimitive<String>
var value: SwiftPrimitiveType
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.
Yes you're right!
…ect.AdditionalProperties
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.
LVG 🎸
What and why?
We ultimately want to add support for custom timings. This was previously introduced to the schema in rum-events-format #25 relying on JSON Schema's
additionalProperty
.Our Swift/Objc pipeline that generates models from a schema doesn't know how to handle
additionalProperties
at this point. To prevent from mis-generating the model for custom timings we previously had to put a dedicated filter until we add the support foradditionalProperties
.In this PR we add the plumbing needed for a basic support of
additionalProperty
. It will allow us to remove the filter and generate the model for custom timings.How?
As of 8e6fbbf the approach has been simplified. To sum-up, we model
additionalProperties
as dictionaries while adding a relatively restrictive support ofSwiftDictionary
(only primitive types).Any future gaps between an improved use of JSON Schema in the input files and the current limitations of the pipeline should be caught by exceptions at runtime, and prior to shipping the generated code inside the SDK.
JSON
We add an
additionalProperties
property to theJSONSchema
. It is optional and of typeJSONSchema
itself as required by the spec.We map that schema to a
JSONObject.AdditionalProperties
struct which is a subset of aJSONObject.Property
. It holds atype
that is aJSONPrimitive
, meaning that we only supportbool, double, integer, string
at this point. The mapping happens in theJSONSchemaToJSONTypeTransformer
.Swift
To support additional properties in
SwiftStruct
, we introduce a basicSwiftDictionary
. Note that keys areString
and values must beSwiftPrimitiveType
, i.e.Bool, Int, Int64, String, Double
.From that point we can declare a
SwiftStruct.Property
of typeSwiftDictionary
to model JSONSchema'sadditionalProperties
. The mapping fromJSONObject
toSwiftStruct
is done inJSONToSwiftTypeTransformer
.JSONToSwiftTypeTransformer
enforces a couple of new rules:additionalProperties
that would require a mapping to a dictionary.additionalProperties
.Objc Interop
To mirror additions to the Swift type system and transformer, we introduce a
ObjcInteropNSDictionary
and add the expected mapping methods insideSwiftToObjcInteropTypeTransformer
.RUM
We just add some basic expect methods to allow traversing a
SwiftDictionary
and transforming any primitive types, e.g.Int
->Int64
.Printers
This has been simplified a lot compared to the initial approach (41a1ac8 and before), they only need to know how to print dictionaries while converting some core Swift <-> Objc types.
Review checklist
Next
tools/rum-models-generator/run.sh generate
to add custom timingsSpoiler this should generate something to resolve this: