-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #940 from DataDog/ncreated/RUMM-2266-generate-sess…
…ion-replay-models RUMM-2266 Reorganise `rum-models-generator` package for Session Replay code generation
- Loading branch information
Showing
42 changed files
with
600 additions
and
356 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
tools/rum-models-generator/Sources/CodeDecoration/SRCodeDecorator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
* Copyright 2019-2020 Datadog, Inc. | ||
*/ | ||
|
||
import Foundation | ||
import CodeGeneration | ||
|
||
/// Adjusts naming and structure of generated code for Session Replay. | ||
public class SRCodeDecorator: CodeDecorator { | ||
public init() {} | ||
|
||
// MARK: - CodeDecorator | ||
|
||
public func decorate(code: GeneratedCode) throws -> GeneratedCode { | ||
return code // RUMM-2266 Implement actual decoration | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
168 changes: 168 additions & 0 deletions
168
...s/rum-models-generator/Sources/CodeGeneration/Generate/Transformers/Swift/SwiftType.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
/* | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
* Copyright 2019-2020 Datadog, Inc. | ||
*/ | ||
|
||
import Foundation | ||
|
||
/// Type-safe Swift schema. | ||
public protocol SwiftType {} | ||
|
||
/// Swift primitive type. | ||
public protocol SwiftPrimitiveType: SwiftType {} | ||
/// An allowed value of Swift primitive type. | ||
public protocol SwiftPrimitiveValue {} | ||
/// An allowed default value of Swift property. | ||
public protocol SwiftPropertyDefaultValue {} | ||
/// An allowed value of Swift with no obj-c interoperability. | ||
public protocol SwiftPrimitiveNoObjcInteropType: SwiftPrimitiveType {} | ||
|
||
extension Bool: SwiftPrimitiveValue, SwiftPropertyDefaultValue {} | ||
extension Int: SwiftPrimitiveValue, SwiftPropertyDefaultValue {} | ||
extension Int64: SwiftPrimitiveValue, SwiftPropertyDefaultValue {} | ||
extension String: SwiftPrimitiveValue, SwiftPropertyDefaultValue {} | ||
extension Double: SwiftPrimitiveValue, SwiftPropertyDefaultValue {} | ||
|
||
/// Represents `Swift.Codable` - we need to define utility type because it cannot be declared as `extension` to `Codable`. | ||
public struct SwiftCodable: SwiftPrimitiveNoObjcInteropType {} | ||
|
||
/// Represents `Swift.Encodable` - we need to define utility type because it cannot be declared as `extension` to `Encodable`. | ||
public struct SwiftEncodable: SwiftPrimitiveNoObjcInteropType {} | ||
|
||
public struct SwiftPrimitive<T: SwiftPrimitiveValue>: SwiftPrimitiveType { | ||
public init() {} | ||
} | ||
|
||
public struct SwiftArray: SwiftType { | ||
public var element: SwiftType | ||
} | ||
|
||
public struct SwiftDictionary: SwiftType { | ||
public let key = SwiftPrimitive<String>() | ||
public var value: SwiftPrimitiveType | ||
} | ||
|
||
/// An `enum` with raw-type cases. | ||
public struct SwiftEnum: SwiftType { | ||
public struct Case: SwiftType, SwiftPropertyDefaultValue { | ||
public enum RawValue { | ||
case string(value: String) | ||
case integer(value: Int) | ||
} | ||
public var label: String | ||
public var rawValue: RawValue | ||
} | ||
|
||
public var name: String | ||
public var comment: String? | ||
public var cases: [Case] | ||
public var conformance: [SwiftProtocol] | ||
} | ||
|
||
/// An `enum` with associated-type cases. | ||
public struct SwiftAssociatedTypeEnum: SwiftType { | ||
public struct Case: SwiftType, SwiftPropertyDefaultValue { | ||
public var label: String | ||
public var associatedType: SwiftType | ||
} | ||
|
||
public var name: String | ||
public var comment: String? | ||
public var cases: [Case] | ||
public var conformance: [SwiftProtocol] | ||
} | ||
|
||
public struct SwiftStruct: SwiftType { | ||
public struct Property: SwiftType { | ||
/// Mutability levels of a property. | ||
/// From the lowest `immutable` to the highest `mutable`. | ||
public enum Mutability: Int { | ||
case immutable | ||
case mutableInternally | ||
case mutable | ||
} | ||
|
||
public enum CodingKey { | ||
/// Static coding key with fixed value. | ||
case `static`(value: String) | ||
/// Dynamic coding key with value determined at runtime. | ||
case `dynamic` | ||
|
||
public var isStatic: Bool { | ||
switch self { | ||
case .static: return true | ||
case .dynamic: return false | ||
} | ||
} | ||
} | ||
|
||
public var name: String | ||
public var comment: String? | ||
public var type: SwiftType | ||
public var isOptional: Bool | ||
public var mutability: Mutability | ||
public var defaultValue: SwiftPropertyDefaultValue? | ||
public var codingKey: CodingKey | ||
} | ||
|
||
public var name: String | ||
public var comment: String? | ||
public var properties: [Property] | ||
public var conformance: [SwiftProtocol] | ||
} | ||
|
||
public struct SwiftProtocol: SwiftType { | ||
public var name: String | ||
public var conformance: [SwiftProtocol] | ||
|
||
public init(name: String, conformance: [SwiftProtocol]) { | ||
self.name = name | ||
self.conformance = conformance | ||
} | ||
} | ||
|
||
/// Reference to any other Swift type. | ||
public struct SwiftTypeReference: SwiftType { | ||
public var referencedTypeName: String | ||
|
||
public init(referencedTypeName: String) { | ||
self.referencedTypeName = referencedTypeName | ||
} | ||
} | ||
|
||
public let codableProtocol = SwiftProtocol(name: "Codable", conformance: []) | ||
|
||
// MARK: - Helpers | ||
|
||
public extension SwiftType { | ||
/// The name of this type (or `nil` if this type is unnamed). | ||
var typeName: String? { | ||
let `struct` = self as? SwiftStruct | ||
let `enum` = self as? SwiftEnum | ||
let associatedTypeEnum = self as? SwiftAssociatedTypeEnum | ||
return `struct`?.name ?? `enum`?.name ?? associatedTypeEnum?.name | ||
} | ||
} | ||
|
||
// MARK: - Equatable | ||
|
||
extension SwiftStruct: Equatable { | ||
public static func == (lhs: SwiftStruct, rhs: SwiftStruct) -> Bool { | ||
return String(describing: lhs) == String(describing: rhs) | ||
} | ||
} | ||
|
||
extension SwiftEnum: Equatable { | ||
public static func == (lhs: SwiftEnum, rhs: SwiftEnum) -> Bool { | ||
return String(describing: lhs) == String(describing: rhs) | ||
} | ||
} | ||
|
||
public func == (lhs: SwiftType, rhs: SwiftType) -> Bool { | ||
return String(describing: lhs) == String(describing: rhs) | ||
} | ||
|
||
public func != (lhs: SwiftType, rhs: SwiftType) -> Bool { | ||
return !(lhs == rhs) | ||
} |
74 changes: 74 additions & 0 deletions
74
tools/rum-models-generator/Sources/CodeGeneration/ModelsGenerator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
* Copyright 2019-2020 Datadog, Inc. | ||
*/ | ||
|
||
import Foundation | ||
|
||
/// Generates code from provided JSON schema file. | ||
public struct ModelsGenerator { | ||
public init() {} | ||
|
||
/// Generates code from JSON schema file. | ||
/// - Parameter schemaFileURL: the URL of schema file | ||
/// - Returns: schema for generated code. | ||
public func generateCode(from schemaFileURL: URL) throws -> GeneratedCode { | ||
let jsonSchema = try JSONSchemaReader().read(schemaFileURL) | ||
let jsonType = try JSONSchemaToJSONTypeTransformer().transform(jsonSchema: jsonSchema) | ||
let swiftTypes = try JSONToSwiftTypeTransformer().transform(jsonType: jsonType) | ||
return GeneratedCode(swiftTypes: swiftTypes) | ||
} | ||
} | ||
|
||
/// Schema describing generated code. | ||
public struct GeneratedCode { | ||
/// An array of Swift schemas describing root constructs in generated code. | ||
public let swiftTypes: [SwiftType] | ||
|
||
/// Changes this schema by applying provided decoration. | ||
/// It can be used to adjust naming and structure of generated code. | ||
public func decorate(using decorator: CodeDecorator) throws -> GeneratedCode { | ||
return try decorator.decorate(code: self) | ||
} | ||
|
||
/// Renders generated code with provided template. | ||
public func print(using template: OutputTemplate, and printer: CodePrinter) throws -> String { | ||
let codeText = try printer.print(code: self) | ||
return template.render(code: codeText) | ||
} | ||
|
||
public init(swiftTypes: [SwiftType]) { | ||
self.swiftTypes = swiftTypes | ||
} | ||
} | ||
|
||
/// A type decorating generated code. | ||
/// Decoration can be used to adjust naming and structure in generated code before it is printed. | ||
public protocol CodeDecorator { | ||
func decorate(code: GeneratedCode) throws -> GeneratedCode | ||
} | ||
|
||
/// The template for generated code file. | ||
public struct OutputTemplate { | ||
let header: String | ||
let footer: String | ||
|
||
/// Initializer. | ||
/// - Parameters: | ||
/// - header: a text block to put before generated code | ||
/// - footer: a text block to put after generated code | ||
public init(header: String, footer: String) { | ||
self.header = header | ||
self.footer = footer | ||
} | ||
|
||
func render(code: String) -> String { | ||
return [header, code, footer].joined() | ||
} | ||
} | ||
|
||
/// Prints generated code. | ||
public protocol CodePrinter { | ||
func print(code: GeneratedCode) throws -> String | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.