-
Notifications
You must be signed in to change notification settings - Fork 35
feat: Add generation context #1011
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
base: epic/sbs
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,10 +5,13 @@ | |
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| /// Represents a single Smithy shape ID. | ||
| /// Represents a Smithy shape ID. | ||
| /// | ||
| /// The id that ShapeID is created from is presumed to be properly formed, since this type will usually | ||
| /// be constructed from previously validated models. | ||
| /// | ||
| /// Shape ID is described in the Smithy 2.0 spec [here](https://smithy.io/2.0/spec/model.html#shape-id). | ||
| public struct ShapeID: Sendable, Hashable { | ||
| public struct ShapeID: Hashable, Sendable { | ||
| public let namespace: String | ||
| public let name: String | ||
| public let member: String? | ||
|
|
@@ -27,16 +30,61 @@ public struct ShapeID: Sendable, Hashable { | |
| self.name = name | ||
| self.member = member | ||
| } | ||
| } | ||
|
|
||
| extension ShapeID: CustomStringConvertible { | ||
| public init(_ id: String) throws { | ||
| let splitOnPound = id.split(separator: "#") | ||
| guard splitOnPound.count == 2 else { | ||
| throw ShapeIDError("id \"\(id)\" does not have a #") | ||
| } | ||
| guard let namespace = splitOnPound.first, !namespace.isEmpty else { | ||
| throw ShapeIDError("id \"\(id)\" does not have a nonempty namespace") | ||
| } | ||
| self.namespace = String(namespace) | ||
| let splitOnDollar = splitOnPound.last!.split(separator: "$") | ||
| switch splitOnDollar.count { | ||
| case 2: | ||
| self.name = String(splitOnDollar.first!) | ||
| self.member = String(splitOnDollar.last!) | ||
| case 1: | ||
| self.name = String(splitOnDollar.first!) | ||
| self.member = nil | ||
| default: | ||
| throw ShapeIDError("id \"\(id)\" has more than one $") | ||
| } | ||
| } | ||
|
|
||
| /// Returns the absolute Shape ID in a single, printable string. | ||
| public var description: String { | ||
| if let member = self.member { | ||
| public init(id: ShapeID, member: String) { | ||
| self.namespace = id.namespace | ||
| self.name = id.name | ||
| self.member = member | ||
| } | ||
|
|
||
| public var id: String { | ||
| if let member { | ||
| return "\(namespace)#\(name)$\(member)" | ||
| } else { | ||
| return "\(namespace)#\(name)" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| extension ShapeID: Comparable { | ||
|
|
||
| public static func < (lhs: ShapeID, rhs: ShapeID) -> Bool { | ||
| return lhs.id.lowercased() < rhs.id.lowercased() | ||
| } | ||
| } | ||
|
|
||
| extension ShapeID: CustomStringConvertible { | ||
|
|
||
| /// Returns the absolute Shape ID in a single, printable string. | ||
| public var description: String { id } | ||
| } | ||
|
|
||
| public struct ShapeIDError: Error { | ||
| public let localizedDescription: String | ||
|
|
||
| init(_ localizedDescription: String) { | ||
| self.localizedDescription = localizedDescription | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,8 +5,10 @@ | |
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| import enum Smithy.Node | ||
|
|
||
| // See https://smithy.io/2.0/spec/json-ast.html#ast-member | ||
| struct ASTMember: Decodable { | ||
| let target: String | ||
| let traits: [String: ASTNode]? | ||
| let traits: [String: Node]? | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,24 +5,11 @@ | |
| // 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 { | ||
| case object([String: ASTNode]) | ||
| case list([ASTNode]) | ||
| case string(String) | ||
| case number(Double) | ||
| case boolean(Bool) | ||
| case null | ||
| } | ||
| import enum Smithy.Node | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The |
||
|
|
||
| extension ASTNode: Decodable { | ||
| extension Node: Decodable { | ||
|
|
||
| init(from decoder: any Decoder) throws { | ||
| public init(from decoder: any Decoder) throws { | ||
| let container = try decoder.singleValueContainer() | ||
| if container.decodeNil() { | ||
| self = .null | ||
|
|
@@ -34,9 +21,9 @@ extension ASTNode: Decodable { | |
| self = .number(double) | ||
| } else if let string = try? container.decode(String.self) { | ||
| self = .string(string) | ||
| } else if let array = try? container.decode([ASTNode].self) { | ||
| } else if let array = try? container.decode([Node].self) { | ||
| self = .list(array) | ||
| } else if let dictionary = try? container.decode([String: ASTNode].self) { | ||
| } else if let dictionary = try? container.decode([String: Node].self) { | ||
| self = .object(dictionary) | ||
| } else { | ||
| throw ASTError("Undecodable value in AST node") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // | ||
| // Copyright Amazon.com Inc. or its affiliates. | ||
| // All Rights Reserved. | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
|
|
||
| public struct GenerationContext { | ||
| public let service: ServiceShape | ||
| public let model: Model | ||
| public let symbolProvider: SymbolProvider | ||
|
|
||
| /// Creates a ``GenerationContext`` from a model. | ||
| /// | ||
| /// The model must contain exactly one service. | ||
| /// - Parameter model: The ``Model`` to create the generation context from. | ||
| /// - Throws: ``ModelError`` if the model does not contain exactly one service. | ||
| init(model: Model) throws { | ||
| let services = model.shapes.values.filter { $0.type == .service } | ||
| guard services.count == 1, let service = services.first as? ServiceShape else { | ||
| throw ModelError("Model contains \(services.count) services") | ||
| } | ||
| self.service = service | ||
| self.model = model | ||
| self.symbolProvider = SymbolProvider(service: service, model: model) | ||
| } | ||
| } |
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.
Swiftlint rearranged imports in a few files here & below.