Skip to content

Commit

Permalink
add --imports option, ensure enums are sorted
Browse files Browse the repository at this point in the history
  • Loading branch information
gereons committed Jun 19, 2024
1 parent aa5bf42 commit c6d808f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 16 deletions.
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import PackageDescription

let package = Package(
name: "ModelGen",
platforms: [.macOS(.v13)],
platforms: [.macOS(.v14)],
products: [
.executable(name: "modelgen", targets: ["modelgen"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.0"),
.package(url: "https://github.com/lukepistrol/SwiftLintPlugin", from: "0.2.2"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.4.0"),
.package(url: "https://github.com/lukepistrol/SwiftLintPlugin", from: "0.55.1"),
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.0")
],
targets: [
Expand Down
8 changes: 5 additions & 3 deletions Sources/Generator+Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
import Foundation

extension Generator {
func generate(path: String, method: String, request: Request, skipHeader: Bool = false) {
func generate(path: String, method: String, request: Request, imports: [String] = [], skipHeader: Bool = false) {
let name = request.operationId.uppercasedFirst() + "Request"

if !skipHeader {
generateFileHeader(modelName: name, schema: nil, import: "Dependencies")
let imports = imports + ["Dependencies"]
generateFileHeader(modelName: name, schema: nil, imports: imports.sorted(by: <))
}

let (_, successType, _) = successValues(for: request)
Expand All @@ -38,7 +39,8 @@ extension Generator {
}

print("")
for enumParam in (request.parameters ?? []).filter({ $0.schema.enumCases != nil }) {
let enumParams = (request.parameters ?? []).filter { $0.schema.enumCases != nil }
for enumParam in enumParams.sorted(by: { $0.name < $1.name }) {
block("public enum \(SwiftKeywords.safe(enumParam.name.uppercasedFirst())): String") {
let sortedCases = Set(enumParam.schema.enumCases ?? []).sorted()
for enumCase in sortedCases {
Expand Down
14 changes: 7 additions & 7 deletions Sources/Generator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ final class Generator {
output.buffer
}

func generate(modelName: String, skipHeader: Bool = false) {
func generate(modelName: String, imports: [String] = [], skipHeader: Bool = false) {
guard let schema = schemas[modelName] else {
fatalError("\(modelName): schema not found")
}

output.reset()

if !skipHeader {
generateFileHeader(modelName: modelName, schema: schema)
generateFileHeader(modelName: modelName, schema: schema, imports: imports)
}
if schema.discriminator != nil {
generateModelEnum(modelName: modelName, schema: schema)
Expand All @@ -50,7 +50,7 @@ final class Generator {
}

// MARK: - file header
func generateFileHeader(modelName: String, schema: Schema?, import: String? = nil) {
func generateFileHeader(modelName: String, schema: Schema?, imports: [String]) {
print("""
//
// \(modelName).swift
Expand All @@ -63,8 +63,8 @@ final class Generator {
import Foundation
""")
if let `import` {
print("import \(`import`)")
imports.forEach {
print("import \($0)")
}
print("")
if let descr = schema?.description {
Expand Down Expand Up @@ -391,8 +391,8 @@ final class Generator {
return
}

for (name, prop) in properties {
guard case .property(let prop) = prop else {
for name in properties.keys.sorted(by: <) {
guard let prop = properties[name], case .property(let prop) = prop else {
continue
}
let enumName = SwiftKeywords.safe("\(name.uppercasedFirst())")
Expand Down
10 changes: 7 additions & 3 deletions Sources/ModelGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ArgumentParser

@main
struct ModelGen: ParsableCommand {
static let version = "v0.1.11"
static let version = "v0.1.12"

@Option(name: .shortAndLong, help: "name of the input file")
var input: String = ""
Expand All @@ -29,6 +29,9 @@ struct ModelGen: ParsableCommand {
@Option(name: .shortAndLong, help: "print to stdout instead of creating files")
var stdout = false

@Option(name: .long, help: "list of additional modules to import")
var imports: String?

mutating func validate() throws {
input = NSString(string: input).expandingTildeInPath
output = NSString(string: output).expandingTildeInPath
Expand Down Expand Up @@ -60,6 +63,7 @@ struct ModelGen: ParsableCommand {

let excludes = (self.exclude ?? "").split(separator: ",").map { String($0) }
let includes = (self.include ?? "").split(separator: ",").map { String($0) }
let imports = (self.imports ?? "").split(separator: ",").map { String($0) }

if let paths = spec.paths {
for (path, requests) in paths {
Expand All @@ -70,7 +74,7 @@ struct ModelGen: ParsableCommand {
}
if includes.isEmpty || includes.contains(name) {
let generator = Generator(spec: spec, classSchemas: classSchemas)
generator.generate(path: path, method: method, request: request)
generator.generate(path: path, method: method, request: request, imports: imports)

try output(generator.buffer, to: "\(requestOutput)/\(name)Request.swift")
}
Expand All @@ -84,7 +88,7 @@ struct ModelGen: ParsableCommand {
}
if includes.isEmpty || includes.contains(name) {
let generator = Generator(spec: spec, classSchemas: classSchemas)
generator.generate(modelName: name)
generator.generate(modelName: name, imports: imports)

try output(generator.buffer, to: "\(modelOutput)/\(name).swift")
}
Expand Down
48 changes: 48 additions & 0 deletions Tests/EnumTest2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// File.swift
//
//
// Created by Gereon Steffens on 19.06.24.
//

import CustomDump
@testable import modelgen
import XCTest

final class EnumTest2: XCTestCase {
private let spec = """
{
"info": {
"title": "test spec"
},
"components": {
"schemas": {
"Enum" : {
"type" : "object",
"required": [ "bool", "ints" ],
"properties" : {
"bEnum" : {
"type" : "string",
"enum" : [ "foo", "bar", "baz" ]
},
"aEnum" : {
"type" : "string",
"enum" : [ "plugh", "xyzzy" ]
}
}
}
}
}
}
"""

private let expected = """
"""

func testEnumOrder() throws {
let spec = try JSONDecoder().decode(OpenApiSpec.self, from: spec.data(using: .utf8)!)
let generator = Generator(spec: spec)
generator.generate(modelName: "Enum", skipHeader: true)
XCTAssertNoDifference(String(generator.buffer.dropLast(1)), expected)
}
}

0 comments on commit c6d808f

Please sign in to comment.