Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
495f2e1
Disable input/output serializers
jbelkins Nov 4, 2025
ca5b331
add ShapeID, doc comments
jbelkins Nov 5, 2025
212120e
Re-enable serde code
jbelkins Nov 5, 2025
fcdf1bf
Cleanup
jbelkins Nov 5, 2025
b2152c2
Merge branch 'main' into jbe/add_schema
jbelkins Nov 7, 2025
88f7be9
Merge branch 'main' into jbe/add_schema
jbelkins Nov 8, 2025
aa823be
feat: Add Swift-native codegen plugin
jbelkins Nov 9, 2025
e817d55
Fix lint
jbelkins Nov 9, 2025
6a9c537
Make service trait optional
jbelkins Nov 9, 2025
33cc093
Fix ktlint again
jbelkins Nov 9, 2025
6b54575
Refactor code generator plugin
jbelkins Nov 9, 2025
ae474f1
Convert smithy model info file to .json
jbelkins Nov 9, 2025
70f7669
Fix Swift 5.9 URL initializer
jbelkins Nov 9, 2025
3d623e6
Code cleanup
jbelkins Nov 9, 2025
d535e66
Revert disabling of schemas
jbelkins Nov 9, 2025
52f9532
Schemas generate for entire SDK
jbelkins Nov 15, 2025
1fa7fbd
Merge branch 'epic/sbs' into jbe/swift_codegen_schema
jbelkins Nov 19, 2025
70e8a15
Fix method name renderSchema
jbelkins Nov 19, 2025
b1548a7
Fix swiftlint
jbelkins Nov 19, 2025
94a901d
Fix ktlint
jbelkins Nov 19, 2025
54a4300
Fix SmithyCodegenCoreTests
jbelkins Nov 19, 2025
6b860df
Merge branch 'epic/sbs' into jbe/swift_codegen_schema
jbelkins Nov 22, 2025
1eb996b
Merge branch 'epic/sbs' into jbe/swift_codegen_schema
jbelkins Nov 26, 2025
3fd9854
Cleanup
jbelkins Dec 5, 2025
64dd13a
Merge branch 'epic/sbs' into jbe/swift_codegen_schema
jbelkins Dec 9, 2025
6a65655
Fixes
jbelkins Dec 9, 2025
db5b76a
Merge branch 'epic/sbs' into jbe/swift_codegen_schema
jbelkins Dec 12, 2025
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
10 changes: 10 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,15 @@ let package = Package(
.executableTarget(
name: "SmithyCodegenCLI",
dependencies: [
"SmithyCodegenCore",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
]
),
.target(
name: "SmithyCodegenCore",
dependencies: ["SmithySerialization"],
resources: [ .process("Resources") ]
),
.testTarget(
name: "ClientRuntimeTests",
dependencies: [
Expand Down Expand Up @@ -393,5 +399,9 @@ let package = Package(
name: "SmithyStreamsTests",
dependencies: ["SmithyStreams", "Smithy"]
),
.testTarget(
name: "SmithyCodegenCoreTests",
dependencies: ["SmithyCodegenCore"]
),
].compactMap { $0 }
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import protocol SmithyHTTPAuthAPI.AuthSchemeResolver
import protocol SmithyHTTPAuthAPI.AuthSchemeResolverParameters
import struct SmithyRetries.DefaultRetryStrategy
import struct SmithyRetries.ExponentialBackoffStrategy
import SmithyTelemetryAPI
import protocol SmithyRetriesAPI.RetryErrorInfoProvider
import protocol SmithyRetriesAPI.RetryStrategy
import struct SmithyRetriesAPI.RetryStrategyOptions
import SmithyTelemetryAPI

public struct DefaultSDKRuntimeConfiguration<DefaultSDKRuntimeRetryStrategy: RetryStrategy,
DefaultSDKRuntimeRetryErrorInfoProvider: RetryErrorInfoProvider> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import protocol SmithyHTTPAPI.HTTPClient
import class SmithyHTTPAPI.HTTPRequest
import class SmithyHTTPAPI.HTTPResponse
import enum SmithyHTTPAPI.HTTPStatusCode
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class SmithyHTTPClientAPI.HttpTelemetry
import class SmithyStreams.BufferedStream
import SmithyTelemetryAPI
#if os(Linux)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import AwsCommonRuntimeKit
import struct Smithy.Attributes
import enum Smithy.ByteStream
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class SmithyHTTPClientAPI.HttpTelemetry

extension HTTP2Stream {
/// Returns the recommended size, in bytes, for the data to write
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import class Foundation.DispatchQueue
import class Foundation.InputStream
import class Foundation.NSObject
import class Foundation.OutputStream
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class Foundation.RunLoop
import class Foundation.Stream
import protocol Foundation.StreamDelegate
Expand All @@ -24,6 +22,8 @@ import class Foundation.Timer
import struct Smithy.Attributes
import protocol Smithy.LogAgent
import protocol Smithy.ReadableStream
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class SmithyHTTPClientAPI.HttpTelemetry

/// Reads data from a smithy-swift native `ReadableStream` and streams the data through to a Foundation `InputStream`.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import class Foundation.NSRecursiveLock
import var Foundation.NSURLAuthenticationMethodClientCertificate
import var Foundation.NSURLAuthenticationMethodServerTrust
import struct Foundation.TimeInterval
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class Foundation.URLAuthenticationChallenge
import struct Foundation.URLComponents
import class Foundation.URLCredential
Expand All @@ -29,7 +27,6 @@ import class Foundation.URLResponse
import class Foundation.URLSession
import class Foundation.URLSessionConfiguration
import protocol Foundation.URLSessionDataDelegate
import SmithyTelemetryAPI
import class Foundation.URLSessionDataTask
import class Foundation.URLSessionTask
import class Foundation.URLSessionTaskMetrics
Expand All @@ -44,7 +41,10 @@ import protocol SmithyHTTPAPI.HTTPClient
import class SmithyHTTPAPI.HTTPRequest
import class SmithyHTTPAPI.HTTPResponse
import enum SmithyHTTPAPI.HTTPStatusCode
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class SmithyHTTPClientAPI.HttpTelemetry
import class SmithyStreams.BufferedStream
import SmithyTelemetryAPI

/// A client that can be used to make requests to AWS services using `Foundation`'s `URLSession` HTTP client.
///
Expand Down
File renamed without changes.
9 changes: 3 additions & 6 deletions Sources/SmithyCodegenCLI/SmithyCodegenCLI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import ArgumentParser
import Foundation
import struct SmithyCodegenCore.CodeGenerator

@main
struct SmithyCodegenCLI: AsyncParsableCommand {
Expand All @@ -31,12 +32,8 @@ struct SmithyCodegenCLI: AsyncParsableCommand {
// If --schemas-path was supplied, create the schema file URL
let schemasFileURL = resolve(paramName: "--schemas-path", path: schemasPath)

// All file URLs needed for code generation have now been resolved.
// Implement code generation here.
if let schemasFileURL {
print("Schemas file path: \(schemasFileURL)")
FileManager.default.createFile(atPath: schemasFileURL.path, contents: Data())
}
// Use resolved file URLs to run code generator
try CodeGenerator(modelFileURL: modelFileURL, schemasFileURL: schemasFileURL).run()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the "placeholder" for code generation is replaced with a call to the actual code generator, implemented below.

}

private func currentWorkingDirectoryFileURL() -> URL {
Expand Down
14 changes: 14 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the other AST... types below are used to read the model file (JSON AST format) from disk.

Once the JSON AST is loaded, it is transformed into a Model (see Model.swift below.)

public struct ASTError: Error {
public let localizedDescription: String

init(_ localizedDescription: String) {
self.localizedDescription = localizedDescription
}
}
11 changes: 11 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTMember.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

struct ASTMember: Decodable {
let target: String
let traits: [String: ASTNode]?
}
12 changes: 12 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

struct ASTModel: Decodable {
let smithy: String
let metadata: ASTNode?
let shapes: [String: ASTShape]
}
45 changes: 45 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTNode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

/// Contains the value of a Smithy Node, as used in a JSON AST.
///
/// Smithy node data is basically the same as the data that can be stored in JSON.
/// The root of a Smithy node may be of any type, i.e. unlike JSON, the root element is not limited to object or list.
///
/// See the definition of node value in the Smithy spec: https://smithy.io/2.0/spec/model.html#node-values
enum ASTNode: Sendable {
case object([String: ASTNode])
case list([ASTNode])
case string(String)
case number(Double)
case boolean(Bool)
case null
}

extension ASTNode: Decodable {

init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() {
self = .null
} else if let bool = try? container.decode(Bool.self) {
self = .boolean(bool)
} else if let int = try? container.decode(Int.self) {
self = .number(Double(int))
} else if let double = try? container.decode(Double.self) {
self = .number(double)
} else if let string = try? container.decode(String.self) {
self = .string(string)
} else if let array = try? container.decode([ASTNode].self) {
self = .list(array)
} else if let dictionary = try? container.decode([String: ASTNode].self) {
self = .object(dictionary)
} else {
throw ASTError("Undecodable value in AST node")
}
}
}
10 changes: 10 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTReference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

struct ASTReference: Decodable {
let target: String
}
31 changes: 31 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTShape.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

struct ASTShape: Decodable {
let type: ASTType
let traits: [String: ASTNode]?
let member: ASTMember?
let key: ASTMember?
let value: ASTMember?
let members: [String: ASTMember]?
let version: String?
let operations: [ASTReference]?
let resources: [ASTReference]?
let errors: [ASTReference]?
let rename: [String: String]?
let identifiers: [String: ASTReference]?
let properties: [String: ASTReference]?
let create: ASTReference?
let put: ASTReference?
let read: ASTReference?
let update: ASTReference?
let delete: ASTReference?
let list: ASTReference?
let collectionOperations: [ASTReference]?
let input: ASTReference?
let output: ASTReference?
}
37 changes: 37 additions & 0 deletions Sources/SmithyCodegenCore/AST/ASTType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

enum ASTType: String, Decodable {
// These cases are all the Smithy shape types
case blob
case boolean
case string
case timestamp
case byte
case short
case integer
case long
case float
case document
case double
case bigDecimal
case bigInteger
case `enum`
case intEnum
case list
case set
case map
case structure
case union
case member
case service
case resource
case operation

// Special for AST, added 'apply' case
case apply
}
30 changes: 30 additions & 0 deletions Sources/SmithyCodegenCore/CodeGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import struct Foundation.Data
import struct Foundation.URL

public struct CodeGenerator {
let modelFileURL: URL
let schemasFileURL: URL?

public init(modelFileURL: URL, schemasFileURL: URL?) {
self.modelFileURL = modelFileURL
self.schemasFileURL = schemasFileURL
}

public func run() throws {
// Load the model from the model file
let model = try Model(modelFileURL: modelFileURL)

// If a schema file URL was provided, generate it
if let schemasFileURL {
let schemaContents = try SmithySchemaCodegen().generate(model: model)
try Data(schemaContents.utf8).write(to: schemasFileURL)
}
}
}
14 changes: 14 additions & 0 deletions Sources/SmithyCodegenCore/CodegenError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

struct CodegenError: Error {
let localizedDescription: String

init(_ localizedDescription: String) {
self.localizedDescription = localizedDescription
}
}
Loading
Loading