Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

129 changes: 83 additions & 46 deletions Sources/JSONAPISwiftGen/ResourceObjectSwiftGenCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,63 +62,100 @@ func documents(
}

let responseBodyTypeName = "Document_\(statusCode.rawValue)"
let examplePropName = "example_\(statusCode.rawValue)"

let example: ExampleSwiftGen?
do {
example = try jsonResponse.example.map { try ExampleSwiftGen.init(openAPIExample: $0, propertyName: examplePropName) }
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
example = nil
}

let testExampleFuncs: [TestFunctionGenerator]
do {
let responseBodyType = SwiftTypeRep(.init(name: responseBodyTypeName))
if let testPropertiesDict = jsonResponse.vendorExtensions["x-tests"]?.value as? [String: Any] {

testExampleFuncs = try OpenAPIExampleRequestTestSwiftGen.TestProperties
.properties(for: testPropertiesDict, server: server)
.map { testProps in
try OpenAPIExampleRequestTestSwiftGen(
method: httpVerb,
server: server,
pathComponents: path,
parameters: params,
testSuiteConfiguration: testSuiteConfiguration,
testProperties: testProps,
exampleResponseDataPropName: examplePropName,
responseBodyType: responseBodyType,
expectedHttpStatus: statusCode
var exampleGens = [ExampleSwiftGen]()
var testExampleFuncs = [TestFunctionGenerator]()

let responseBodyType = SwiftTypeRep(.init(name: responseBodyTypeName))

// if there is 1 example, we also see about creating test cases from x-tests (which
// don't yet support named examples, though that would be great).
if let example = jsonResponse.example {
let examplePropName = "example_\(statusCode.rawValue)"
do {
exampleGens.append(try ExampleSwiftGen.init(openAPIExample: example, propertyName: examplePropName))
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
}
do {
if let testPropertiesDict = jsonResponse.vendorExtensions["x-tests"]?.value as? [String: Any] {

testExampleFuncs = try OpenAPIExampleRequestTestSwiftGen.TestProperties
.properties(for: testPropertiesDict, server: server)
.map { testProps in
try OpenAPIExampleRequestTestSwiftGen(
method: httpVerb,
server: server,
pathComponents: path,
parameters: params,
testSuiteConfiguration: testSuiteConfiguration,
testProperties: testProps,
exampleResponseDataPropName: examplePropName,
responseBodyType: responseBodyType,
expectedHttpStatus: statusCode
)
}
} else if !(exampleGens.isEmpty) {
testExampleFuncs.append(
try OpenAPIExampleParseTestSwiftGen(
exampleDataPropName: examplePropName,
bodyType: responseBodyType,
exampleHttpStatusCode: statusCode,
exampleName: "default"
)
)
}
} else if example != nil {
testExampleFuncs = try [
OpenAPIExampleParseTestSwiftGen(
exampleDataPropName: examplePropName,
bodyType: responseBodyType,
exampleHttpStatusCode: statusCode
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
}
} else if let examples = jsonResponse.examples?.mapValues({ $0.value.b }) {
// if there are multiple examples, we simply generate tests for each named example
// because we don't yet support request-based testing for named examples.

func exampleProp(named name: String) -> String {
"example_\(statusCode.rawValue)_\(propertyCased(name))"
}

for (name, maybeExample) in examples {
guard let example = maybeExample else { continue }
let examplePropName = exampleProp(named: name)
do {
exampleGens.append(try ExampleSwiftGen.init(openAPIExample: example, propertyName: examplePropName))
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
}
do {
testExampleFuncs.append(
try OpenAPIExampleParseTestSwiftGen(
exampleDataPropName: examplePropName,
bodyType: responseBodyType,
exampleHttpStatusCode: statusCode,
exampleName: propertyCased(name)
)
)
]
} else {
testExampleFuncs = []
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
}
}
} catch let err {
print("===")
print("-> " + String(describing: err))
print("-- While parsing the HTTP \(statusCode.rawValue) response document for \(httpVerb.rawValue) at \(path.rawValue)")
print("===")
testExampleFuncs = []
}

do {
responseDocuments[statusCode] = try JSONAPIDocumentSwiftGen(
swiftTypeName: responseBodyTypeName,
structure: responseSchema,
example: example,
examples: exampleGens,
testExampleFuncs: testExampleFuncs
)
} catch let err {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public protocol DocumentSwiftGenerator: JSONSchemaSwiftGenerator {
var swiftTypeName: String { get }
var exampleGenerator: ExampleSwiftGen? { get }
var exampleGenerators: [ExampleSwiftGen] { get }
var testExampleFuncs: [TestFunctionGenerator] { get }

var swiftCodeDependencies: [SwiftGenerator] { get }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public struct JSONAPIDocumentSwiftGen: DocumentSwiftGenerator {
public let decls: [Decl]
public let swiftTypeName: String
public let resourceObjectGenerators: Set<ResourceObjectSwiftGen>
public let exampleGenerator: ExampleSwiftGen?
public let exampleGenerators: [ExampleSwiftGen]
public let testExampleFuncs: [TestFunctionGenerator]

public var swiftCodeDependencies: [SwiftGenerator] {
Expand All @@ -29,12 +29,12 @@ public struct JSONAPIDocumentSwiftGen: DocumentSwiftGenerator {
swiftTypeName: String,
structure: DereferencedJSONSchema,
allowPlaceholders: Bool = true,
example: ExampleSwiftGen? = nil,
examples: [ExampleSwiftGen] = [],
testExampleFuncs: [TestFunctionGenerator] = []
) throws {
self.swiftTypeName = swiftTypeName
self.structure = structure
self.exampleGenerator = example
self.exampleGenerators = examples
self.testExampleFuncs = testExampleFuncs

(decls, resourceObjectGenerators) = try JSONAPIDocumentSwiftGen.swiftDecls(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public struct StructDocumentSwiftGen: DocumentSwiftGenerator {
public let decls: [Decl]
public let swiftTypeName: String
public let structGenerator: StructureSwiftGen
public let exampleGenerator: ExampleSwiftGen?
public let exampleGenerators: [ExampleSwiftGen]
public let testExampleFuncs: [TestFunctionGenerator]

public let swiftCodeDependencies: [SwiftGenerator] = []
Expand All @@ -27,12 +27,12 @@ public struct StructDocumentSwiftGen: DocumentSwiftGenerator {
swiftTypeName: String,
structure: DereferencedJSONSchema,
allowPlaceholders: Bool = true,
example: ExampleSwiftGen? = nil,
examples: [ExampleSwiftGen] = [],
testExampleFuncs: [TestFunctionGenerator] = []
) throws {
self.swiftTypeName = swiftTypeName
self.structure = structure
self.exampleGenerator = example
self.exampleGenerators = examples
self.testExampleFuncs = testExampleFuncs

let structGenerator = try StructureSwiftGen(
Expand Down
14 changes: 11 additions & 3 deletions Sources/JSONAPISwiftGen/Swift Generators/ExampleSwiftGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import JSONAPI
/// A Generator that produces Swift code defining an OpenAPI example
/// request/response body as a constant `Data`.
public struct ExampleSwiftGen: SwiftGenerator {
/// The name of the property generated and stored as decl(s)
/// by this generator.
public let propertyName: String
public let decls: [Decl]

private let exampleAsDataSwiftString: String
Expand All @@ -29,6 +32,7 @@ public struct ExampleSwiftGen: SwiftGenerator {
/// - propertyName: The name of the constant the generated Swift code should
/// produce.
public init(openAPIExample: AnyCodable, propertyName: String) throws {
self.propertyName = propertyName
let encoder = JSONEncoder()
let exampleData = try encoder.encode(openAPIExample)
guard let exampleString = String(data: exampleData, encoding: .utf8) else {
Expand All @@ -41,9 +45,13 @@ public struct ExampleSwiftGen: SwiftGenerator {

exampleAsDataSwiftString = "###\"\(exampleString)\"###.data(using: .utf8)!"

let decl = StaticDecl(PropDecl.var(propName: propertyName,
swiftType: .rep(Data.self),
DynamicValue(value: exampleAsDataSwiftString)))
let decl = StaticDecl(
PropDecl.var(
propName: propertyName,
swiftType: .rep(Data.self),
DynamicValue(value: exampleAsDataSwiftString)
)
)

decls = [decl]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public struct OpenAPIExampleParseTestSwiftGen: TestFunctionGenerator {
public init(
exampleDataPropName: String,
bodyType: SwiftTypeRep,
exampleHttpStatusCode: OpenAPI.Response.StatusCode?
exampleHttpStatusCode: OpenAPI.Response.StatusCode?,
exampleName: String
) throws {

let responseBodyDecl = PropDecl.let(
Expand All @@ -43,7 +44,7 @@ public struct OpenAPIExampleParseTestSwiftGen: TestFunctionGenerator {

let context = TestFunctionLocalContext(
contextPrefix: "test_example_parse",
slug: nil,
slug: exampleName,
statusCode: exampleHttpStatusCode
)
testFunctionContext = context
Expand Down