diff --git a/Package.swift b/Package.swift index 59d7db5..43dba53 100644 --- a/Package.swift +++ b/Package.swift @@ -10,8 +10,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/soto-project/soto-smithy.git", from: "0.3.1"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"), - .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.0"), - .package(url: "https://github.com/nicklockwood/SwiftFormat.git", from: "0.48.17"), + .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.3"), .package(url: "https://github.com/apple/swift-log.git", from: "1.4.0"), ], targets: [ @@ -29,7 +28,6 @@ let package = Package( .product(name: "SotoSmithy", package: "soto-smithy"), .product(name: "SotoSmithyAWS", package: "soto-smithy"), .product(name: "HummingbirdMustache", package: "hummingbird-mustache"), - .product(name: "SwiftFormat", package: "SwiftFormat"), .product(name: "Logging", package: "swift-log") ] ), diff --git a/Package@swift-5.4.swift b/Package@swift-5.4.swift index f340657..13102aa 100644 --- a/Package@swift-5.4.swift +++ b/Package@swift-5.4.swift @@ -10,8 +10,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/soto-project/soto-smithy.git", from: "0.3.1"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"), - .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.0"), - .package(url: "https://github.com/nicklockwood/SwiftFormat.git", .exact("0.48.17")), + .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.3"), .package(url: "https://github.com/apple/swift-log.git", from: "1.4.0"), ], targets: [ @@ -29,7 +28,6 @@ let package = Package( .product(name: "SotoSmithy", package: "soto-smithy"), .product(name: "SotoSmithyAWS", package: "soto-smithy"), .product(name: "HummingbirdMustache", package: "hummingbird-mustache"), - .product(name: "SwiftFormat", package: "SwiftFormat"), .product(name: "Logging", package: "swift-log") ] ), diff --git a/Package@swift-5.5.swift b/Package@swift-5.5.swift index 583b818..2b4ba45 100644 --- a/Package@swift-5.5.swift +++ b/Package@swift-5.5.swift @@ -10,8 +10,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/soto-project/soto-smithy.git", from: "0.3.1"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"), - .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.0"), - .package(url: "https://github.com/nicklockwood/SwiftFormat.git", .exact("0.48.17")), + .package(url: "https://github.com/hummingbird-project/hummingbird-mustache.git", from: "1.0.3"), .package(url: "https://github.com/apple/swift-log.git", from: "1.4.0"), ], targets: [ @@ -29,7 +28,6 @@ let package = Package( .product(name: "SotoSmithy", package: "soto-smithy"), .product(name: "SotoSmithyAWS", package: "soto-smithy"), .product(name: "HummingbirdMustache", package: "hummingbird-mustache"), - .product(name: "SwiftFormat", package: "SwiftFormat"), .product(name: "Logging", package: "swift-log") ] ), diff --git a/Sources/SotoCodeGenerator/main.swift b/Sources/SotoCodeGenerator/main.swift index 6eff16d..fe50c4b 100644 --- a/Sources/SotoCodeGenerator/main.swift +++ b/Sources/SotoCodeGenerator/main.swift @@ -42,9 +42,6 @@ struct Command: ParsableCommand, SotoCodeGenCommand { @Flag(name: .long, inversion: .prefixedNo, help: "Output files") var output: Bool = true - @Flag(name: [.customShort("f"), .customLong("format")], inversion: .prefixedNo, help: "Run swift format on output") - var swiftFormat: Bool = false - @Flag(name: .long, help: "HTML comments") var htmlComments: Bool = false diff --git a/Sources/SotoCodeGeneratorLib/AwsService+shapes.swift b/Sources/SotoCodeGeneratorLib/AwsService+shapes.swift index 2fee29c..2e66075 100644 --- a/Sources/SotoCodeGeneratorLib/AwsService+shapes.swift +++ b/Sources/SotoCodeGeneratorLib/AwsService+shapes.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2022 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -75,7 +75,7 @@ extension AwsService { if key.allLetterIsNumeric() { key = "\(shapeName.toSwiftVariableCase())\(key)" } - valueContexts.append(EnumMemberContext(case: key, documentation: processDocs(value.documentation), string: value.value)) + valueContexts.append(EnumMemberContext(case: key, documentation: processDocs(value.documentation), rawValue: value.value)) } return EnumContext( name: shapeName.toSwiftClassCase(), @@ -113,7 +113,7 @@ extension AwsService { return EnumMemberContext( case: key, documentation: documentation.map { processDocs($0.value) } ?? [], - string: value + rawValue: value ) } return EnumContext( @@ -370,11 +370,16 @@ extension AwsService { else { return nil } - var codingKey: String = name + var rawValue: String = name if let aliasTrait = member.traits?.first(where: { $0 is AliasTrait }) as? AliasTrait { - codingKey = aliasTrait.alias + rawValue = aliasTrait.alias } - return CodingKeysContext(variable: name.toSwiftVariableCase(), codingKey: codingKey, duplicate: false) + let variable = name.toSwiftVariableCase() + return CodingKeysContext( + variable: variable, + rawValue: rawValue, + duplicate: false + ) } /// Generate array/dictionary encoding contexts diff --git a/Sources/SotoCodeGeneratorLib/AwsService.swift b/Sources/SotoCodeGeneratorLib/AwsService.swift index 245c0c0..9d38dfc 100644 --- a/Sources/SotoCodeGeneratorLib/AwsService.swift +++ b/Sources/SotoCodeGeneratorLib/AwsService.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2022 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -300,8 +300,8 @@ struct AwsService { } /// process documenation string - func processDocs(from shape: Shape) -> [String.SubSequence] { - var docs: [String.SubSequence] + func processDocs(from shape: Shape) -> [Substring] { + var docs: [Substring] let documentation = shape.trait(type: DocumentationTrait.self)?.value if self.outputHTMLComments { @@ -311,7 +311,8 @@ struct AwsService { .tagStriped() .replacingOccurrences(of: "\n +", with: " ", options: .regularExpression, range: nil) .split(separator: "\n") - .compactMap { $0.isEmpty ? nil : $0 } ?? [] + .compactMap { $0.isEmpty ? nil : $0 } + .map { $0.dropLast(while: { $0.isWhitespace }) } ?? [] } if let externalDocumentation = shape.trait(type: ExternalDocumentationTrait.self)?.value { @@ -323,7 +324,7 @@ struct AwsService { } /// process documenation string - func processMemberDocs(from shape: MemberShape) -> [String.SubSequence] { + func processMemberDocs(from shape: MemberShape) -> [Substring] { guard var documentation = shape.trait(type: DocumentationTrait.self)?.value else { return [] } if let recommendation = shape.trait(type: RecommendedTrait.self)?.reason { documentation += "\n\(recommendation)" @@ -333,6 +334,7 @@ struct AwsService { .replacingOccurrences(of: "\n +", with: " ", options: .regularExpression, range: nil) .split(separator: "\n") .compactMap { $0.isEmpty ? nil : $0 } + .map { $0.dropLast(while: { $0.isWhitespace }) } } /// process documentation string @@ -672,7 +674,7 @@ extension AwsService { struct EnumMemberContext { let `case`: String let documentation: [String.SubSequence] - let string: String + let rawValue: String } struct ArrayEncodingPropertiesContext: EncodingPropertiesContext { @@ -752,7 +754,7 @@ extension AwsService { struct CodingKeysContext { let variable: String - let codingKey: String + let rawValue: String var duplicate: Bool } diff --git a/Sources/SotoCodeGeneratorLib/SotoCodeGen.swift b/Sources/SotoCodeGeneratorLib/SotoCodeGen.swift index f86aaf5..fac4c5b 100644 --- a/Sources/SotoCodeGeneratorLib/SotoCodeGen.swift +++ b/Sources/SotoCodeGeneratorLib/SotoCodeGen.swift @@ -17,7 +17,6 @@ import HummingbirdMustache import Logging import SotoSmithy import SotoSmithyAWS -import SwiftFormat public protocol SotoCodeGenCommand { var inputFile: String? { get } @@ -28,7 +27,6 @@ public protocol SotoCodeGenCommand { var endpoints: String { get } var module: String? { get } var output: Bool { get } - var swiftFormat: Bool { get } var htmlComments: Bool { get } var smithy: Bool { get } var logLevel: String? { get } @@ -40,22 +38,6 @@ public struct SotoCodeGen { let error: Error } - enum SwiftFormatConfig { - static let disabledRules = FormatRules.disabledByDefault + ["redundantReturn", "redundantBackticks", "trailingCommas", "extensionAccessControl"] - static let ruleNames = Set(FormatRules.byName.keys).subtracting(disabledRules) - static let rules: [FormatRule] = ruleNames.map { FormatRules.byName[$0]! } - static let formatOptions = FormatOptions( - ifdefIndent: .noIndent, - wrapArguments: .beforeFirst, - wrapParameters: .beforeFirst, - wrapCollections: .beforeFirst, - hoistPatternLet: false, - stripUnusedArguments: .unnamedOnly, - explicitSelf: .insert, - noSpaceOperators: ["...", "..<"] - ) - } - let command: SotoCodeGenCommand let library: HBMustacheLibrary let logger: Logging.Logger @@ -196,15 +178,6 @@ public struct SotoCodeGen { }) { left, _ in left } } - /// Run swift format on String - func format(_ string: String) throws -> String { - if self.command.swiftFormat { - return try SwiftFormat.format(string, rules: Self.SwiftFormatConfig.rules, options: Self.SwiftFormatConfig.formatOptions) - } else { - return string - } - } - /// Generate service files from AWSService /// - Parameter codeGenerator: service generated from JSON func generateFiles(with service: AwsService, config: ConfigFile) throws { @@ -232,13 +205,13 @@ public struct SotoCodeGen { } let api = self.library.render(apiContext, withTemplate: "api")! - if try self.format(api) + if try api .writeIfChanged(toFile: "\(basePath)/\(prefix)_api.swift") { self.logger.info("Wrote \(prefix)_api.swift") } let apiAsync = self.library.render(apiContext, withTemplate: "api_async")! - if self.command.output, try self.format(apiAsync).writeIfChanged( + if self.command.output, try apiAsync.writeIfChanged( toFile: "\(basePath)/\(prefix)_api+async.swift" ) { self.logger.info("Wrote \(prefix)_api+async.swift") @@ -252,7 +225,7 @@ public struct SotoCodeGen { } let shapes = self.library.render(shapesContext, withTemplate: "shapes")! - if self.command.output, try self.format(shapes).writeIfChanged( + if self.command.output, try shapes.writeIfChanged( toFile: "\(basePath)/\(prefix)_shapes.swift" ) { self.logger.info("Wrote \(prefix)_shapes.swift") diff --git a/Sources/SotoCodeGeneratorLib/String.swift b/Sources/SotoCodeGeneratorLib/String.swift index 7d757a9..b751708 100644 --- a/Sources/SotoCodeGeneratorLib/String.swift +++ b/Sources/SotoCodeGeneratorLib/String.swift @@ -162,6 +162,19 @@ extension StringProtocol { return true } + func dropLast(while: (Self.Element) throws -> Bool) rethrows -> Self.SubSequence { + var position = self.endIndex + var count = 0 + while position != self.startIndex { + position = self.index(before: position) + if try !`while`(self[position]) { + break + } + count += 1 + } + return self.dropLast(count) + } + private func lowerFirst() -> String { return String(self[startIndex]).lowercased() + self[index(after: startIndex)...] } diff --git a/Sources/SotoCodeGeneratorLib/Templates/Templates.swift b/Sources/SotoCodeGeneratorLib/Templates/Templates.swift index fd8282e..87c4081 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/Templates.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/Templates.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -18,6 +18,7 @@ enum Templates { static var values: [String: String] = [ "api": apiTemplate, "api_async": apiAsyncTemplate, + "comment": commentTemplate, "enum": enumTemplate, "enumWithValues": enumWithValuesTemplate, "errors": errorTemplate, diff --git a/Sources/SotoCodeGeneratorLib/Templates/api+async.swift b/Sources/SotoCodeGeneratorLib/Templates/api+async.swift index 548f91e..067c3a1 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/api+async.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/api+async.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -23,18 +23,17 @@ extension Templates { @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) extension {{ name }} { - // MARK: Async API Calls {{#operations}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#documentationUrl}} /// {{.}} {{/documentationUrl}} {{#deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/deprecated}} {{scope}} func {{funcName}}({{#inputShape}}_ input: {{.}}, {{/inputShape}}logger: {{logger}} = AWSClient.loggingDisabled, on eventLoop: EventLoop? = nil) async throws{{#outputShape}} -> {{.}}{{/outputShape}} { return try await self.client.execute(operation: "{{name}}", path: "{{path}}", httpMethod: .{{httpMethod}}, serviceConfig: self.config{{#inputShape}}, input: input{{/inputShape}}{{#endpointRequired}}, endpointDiscovery: .init(storage: self.endpointStorage, discover: self.getEndpoint, required: {{required}}){{/endpointRequired}}{{#hostPrefix}}, hostPrefix: "{{{.}}}"{{/hostPrefix}}, logger: logger, on: eventLoop) @@ -46,13 +45,13 @@ extension Templates { {{#streamingOperations}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#documentationUrl}} /// {{.}} {{/documentationUrl}} {{#deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/deprecated}} {{scope}} func {{funcName}}Streaming({{#inputShape}}_ input: {{.}}, {{/inputShape}}logger: {{logger}} = AWSClient.loggingDisabled, on eventLoop: EventLoop? = nil, _ stream: @escaping ({{streaming}}, EventLoop) -> EventLoopFuture) async throws{{#outputShape}} -> {{.}}{{/outputShape}} { return try await self.client.execute(operation: "{{name}}", path: "{{path}}", httpMethod: .{{httpMethod}}, serviceConfig: self.config{{#inputShape}}, input: input{{/inputShape}}{{#endpointRequired}}, endpointDiscovery: .init(storage: self.endpointStorage, discover: self.getEndpoint, required: {{required}}){{/endpointRequired}}{{#hostPrefix}}, hostPrefix: "{{{.}}}"{{/hostPrefix}}, logger: logger, on: eventLoop, stream: stream) @@ -60,15 +59,16 @@ extension Templates { {{/streamingOperations}} {{/first(streamingOperations)}} } - {{#paginators}} + {{>paginators_async}} {{/paginators}} - {{#waiters}} + {{>waiters_async}} {{/waiters}} #endif // compiler(>=5.5.2) && canImport(_Concurrency) + """ } diff --git a/Sources/SotoCodeGeneratorLib/Templates/api.swift b/Sources/SotoCodeGeneratorLib/Templates/api.swift index 2b51792..a482860 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/api.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/api.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -28,7 +28,7 @@ extension Templates { {{#first(description)}} /// {{#description}} - /// {{.}} + {{>comment}} {{/description}} {{/first(description)}} {{scope}} struct {{ name }}: AWSService { @@ -88,14 +88,14 @@ extension Templates { {{#first(serviceEndpoints)}} serviceEndpoints: [ {{#serviceEndpoints}} - {{.}}{{^last()}}, {{/last()}} + {{.}}{{^last()}},{{/last()}} {{/serviceEndpoints}} ], {{/first(serviceEndpoints)}} {{#first(partitionEndpoints)}} partitionEndpoints: [ {{#partitionEndpoints}} - {{.}}{{^last()}}, {{/last()}} + {{.}}{{^last()}},{{/last()}} {{/partitionEndpoints}} ], {{/first(partitionEndpoints)}} @@ -104,9 +104,9 @@ extension Templates { {{#variantEndpoints}} [{{variant}}]: .init(endpoints: [ {{#endpoints.endpoints}} - "{{region}}": "{{hostname}}"{{^last()}}, {{/last()}} + "{{region}}": "{{hostname}}"{{^last()}},{{/last()}} {{/endpoints.endpoints}} - ]){{^last()}}, {{/last()}} + ]){{^last()}},{{/last()}} {{/variantEndpoints}} ], {{/first(variantEndpoints)}} @@ -124,7 +124,7 @@ extension Templates { options: options ) {{#endpointDiscovery}} - self.endpointStorage = .init(endpoint: self.config.endpoint) + self.endpointStorage = .init(endpoint: self.config.endpoint) {{/endpointDiscovery}} } @@ -132,13 +132,13 @@ extension Templates { {{#operations}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#documentationUrl}} /// {{.}} {{/documentationUrl}} {{#deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/deprecated}} {{^outputShape}}@discardableResult {{/outputShape}}{{scope}} func {{funcName}}({{#inputShape}}_ input: {{.}}, {{/inputShape}}logger: {{logger}} = AWSClient.loggingDisabled, on eventLoop: EventLoop? = nil) -> EventLoopFuture<{{#outputShape}}{{.}}{{/outputShape}}{{^outputShape}}Void{{/outputShape}}> { return self.client.execute(operation: "{{name}}", path: "{{path}}", httpMethod: .{{httpMethod}}, serviceConfig: self.config{{#inputShape}}, input: input{{/inputShape}}{{#endpointRequired}}, endpointDiscovery: .init(storage: self.endpointStorage, discover: self.getEndpoint, required: {{required}}){{/endpointRequired}}{{#hostPrefix}}, hostPrefix: "{{{.}}}"{{/hostPrefix}}, logger: logger, on: eventLoop) @@ -150,15 +150,15 @@ extension Templates { {{#streamingOperations}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#documentationUrl}} /// {{.}} {{/documentationUrl}} {{#deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/deprecated}} - {{^outputShape}}@discardableResult {{/outputShape}}{{scope}} func {{funcName}}Streaming({{#inputShape}}_ input: {{.}}, {{/inputShape}}logger: {{logger}} = AWSClient.loggingDisabled, on eventLoop: EventLoop? = nil{{#streaming}}, _ stream: @escaping ({{.}}, EventLoop)->EventLoopFuture{{/streaming}}) -> EventLoopFuture<{{#outputShape}}{{.}}{{/outputShape}}{{^outputShape}}Void{{/outputShape}}> { + {{^outputShape}}@discardableResult {{/outputShape}}{{scope}} func {{funcName}}Streaming({{#inputShape}}_ input: {{.}}, {{/inputShape}}logger: {{logger}} = AWSClient.loggingDisabled, on eventLoop: EventLoop? = nil{{#streaming}}, _ stream: @escaping ({{.}}, EventLoop) -> EventLoopFuture{{/streaming}}) -> EventLoopFuture<{{#outputShape}}{{.}}{{/outputShape}}{{^outputShape}}Void{{/outputShape}}> { return self.client.execute(operation: "{{name}}", path: "{{path}}", httpMethod: .{{httpMethod}}, serviceConfig: self.config{{#inputShape}}, input: input{{/inputShape}}{{#endpointRequired}}, endpointDiscovery: .init(storage: self.endpointStorage, discover: self.getEndpoint, required: {{required}}){{/endpointRequired}}{{#hostPrefix}}, hostPrefix: "{{{.}}}"{{/hostPrefix}}, logger: logger, on: eventLoop{{#streaming}}, stream: stream{{/streaming}}) } {{/streamingOperations}} @@ -166,7 +166,7 @@ extension Templates { {{#endpointDiscovery}} func getEndpoint(logger: Logger, eventLoop: EventLoop) -> EventLoopFuture { - return describeEndpoints(.init(), logger: logger, on: eventLoop).map { + return self.describeEndpoints(.init(), logger: logger, on: eventLoop).map { .init(endpoints: $0.endpoints.map { .init(address: "https://\($0.address)", cachePeriodInMinutes: $0.cachePeriodInMinutes) }) @@ -186,13 +186,14 @@ extension Templates { {{/endpointDiscovery}} } } - {{#paginators}} + {{>paginators}} {{/paginators}} - {{#waiters}} + {{>waiters}} {{/waiters}} + """# } diff --git a/Sources/SotoCodeGeneratorLib/Templates/comment.swift b/Sources/SotoCodeGeneratorLib/Templates/comment.swift new file mode 100644 index 0000000..f288fda --- /dev/null +++ b/Sources/SotoCodeGeneratorLib/Templates/comment.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Soto for AWS open source project +// +// Copyright (c) 2017-2023 the Soto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Soto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension Templates { + static let commentTemplate = """ + {{%CONTENT_TYPE:TEXT}} + {{^empty(.)}} + /// {{.}} + {{/empty(.)}} + {{#empty(.)}} + ///{{.}} + {{/empty(.)}} + + """ +} diff --git a/Sources/SotoCodeGeneratorLib/Templates/enum.swift b/Sources/SotoCodeGeneratorLib/Templates/enum.swift index 50061b2..5364c54 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/enum.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/enum.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -22,25 +22,26 @@ extension Templates { {{scope}} init(rawValue: String) { self.rawValue = rawValue } + {{#values}} {{#documentation}} - /// {{.}} + {{>comment}} {{/documentation}} - {{scope}} static var {{case}}: Self { .init(rawValue: "{{string}}")} + {{scope}} static var {{case}}: Self { .init(rawValue: "{{rawValue}}") } {{/values}} } - {{/isExtensible}} {{^isExtensible}} {{scope}} enum {{name}}: String, CustomStringConvertible, Codable, _SotoSendable { {{#values}} {{#documentation}} - /// {{.}} + {{>comment}} {{/documentation}} - case {{case}} = "{{string}}" + case {{case}} = "{{rawValue}}" {{/values}} {{scope}} var description: String { return self.rawValue } } {{/isExtensible}} + """ } diff --git a/Sources/SotoCodeGeneratorLib/Templates/enumWithValues.swift b/Sources/SotoCodeGeneratorLib/Templates/enumWithValues.swift index ec0e185..a452360 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/enumWithValues.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/enumWithValues.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -32,7 +32,7 @@ extension Templates { {{! enum cases }} {{#members}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} case {{variable}}({{type}}) {{/members}} @@ -113,7 +113,7 @@ extension Templates { {{/withDictionaryContexts(.)}} {{! validate min,max,pattern }} {{#sorted(reqs)}} - try validate(value, name: "{{name}}", parent: name, {{key}}: {{value}}) + try self.validate(value, name: "{{name}}", parent: name, {{key}}: {{value}}) {{/sorted(reqs)}} {{/validation}} {{#requiresDefaultValidation}} @@ -126,22 +126,23 @@ extension Templates { {{/first(validation)}} {{! CodingKeys enum }} {{#first(members)}} - {{^first(codingKeys)}} + {{#empty(codingKeys)}} private enum CodingKeys: CodingKey {} - {{/first(codingKeys)}} - {{#first(codingKeys)}} + {{/empty(codingKeys)}} + {{^empty(codingKeys)}} private enum CodingKeys: String, CodingKey { {{#codingKeys}} - {{#duplicate}} - case {{variable}} = "_{{codingKey}}" // TODO this is temporary measure for avoiding CodingKey duplication. - {{/duplicate}} - {{^duplicate}} - case {{variable}} = "{{codingKey}}" - {{/duplicate}} + {{#rawValue}} + case {{variable}} = "{{.}}" + {{/rawValue}} + {{^rawValue}} + case {{variable}} + {{/rawValue}} {{/codingKeys}} } - {{/first(codingKeys)}} + {{/empty(codingKeys)}} {{/first(members)}} } + """# } diff --git a/Sources/SotoCodeGeneratorLib/Templates/error.swift b/Sources/SotoCodeGeneratorLib/Templates/error.swift index 40bb3c7..4d90352 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/error.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/error.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -14,7 +14,8 @@ extension Templates { static let errorTemplate = #""" - // MARK - Errors + {{%CONTENT_TYPE:TEXT}} + // MARK: - Errors /// Error enum for {{name}} {{scope}} struct {{errorName}}: AWSErrorType { @@ -44,7 +45,7 @@ extension Templates { {{#errors}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{scope}} static var {{enum}}: Self { .init(.{{enum}}) } {{/errors}} @@ -61,5 +62,6 @@ extension Templates { return "\(self.error.rawValue): \(self.message ?? "")" } } + """# } diff --git a/Sources/SotoCodeGeneratorLib/Templates/header.swift b/Sources/SotoCodeGeneratorLib/Templates/header.swift index 65c7a8b..dc87fd7 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/header.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/header.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2022 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -18,7 +18,7 @@ extension Templates { // // This source file is part of the Soto for AWS open source project // - // Copyright (c) 2017-2022 the Soto project authors + // Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information diff --git a/Sources/SotoCodeGeneratorLib/Templates/paginators+async.swift b/Sources/SotoCodeGeneratorLib/Templates/paginators+async.swift index 3a2678e..13b8626 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/paginators+async.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/paginators+async.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -21,7 +21,7 @@ extension Templates { extension {{name}} { {{#paginators}} {{#operation.comment}} - /// {{.}} + {{>comment}} {{/operation.comment}} /// Return PaginatorSequence for operation. /// @@ -30,7 +30,7 @@ extension Templates { /// - logger: Logger used flot logging /// - eventLoop: EventLoop to run this process on {{#operation.deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/operation.deprecated}} {{scope}} func {{operation.funcName}}Paginator( _ input: {{operation.inputShape}}, @@ -39,7 +39,7 @@ extension Templates { ) -> AWSClient.PaginatorSequence<{{operation.inputShape}}, {{operation.outputShape}}> { return .init( input: input, - command: {{operation.funcName}}, + command: self.{{operation.funcName}}, {{#inputKey}} inputKey: \{{operation.inputShape}}.{{.}}, {{/inputKey}} diff --git a/Sources/SotoCodeGeneratorLib/Templates/paginators.swift b/Sources/SotoCodeGeneratorLib/Templates/paginators.swift index 0c12d05..91210ef 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/paginators.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/paginators.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -20,7 +20,7 @@ extension Templates { extension {{name}} { {{#paginators}} {{#operation.comment}} - /// {{.}} + {{>comment}} {{/operation.comment}} /// /// Provide paginated results to closure `onPage` for it to combine them into one result. @@ -34,7 +34,7 @@ extension Templates { /// - onPage: closure called with each paginated response. It combines an accumulating result with the contents of response. This combined result is then returned /// along with a boolean indicating if the paginate operation should continue. {{#operation.deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/operation.deprecated}} {{scope}} func {{operation.funcName}}Paginator( _ input: {{operation.inputShape}}, @@ -43,10 +43,10 @@ extension Templates { on eventLoop: EventLoop? = nil, onPage: @escaping (Result, {{operation.outputShape}}, EventLoop) -> EventLoopFuture<(Bool, Result)> ) -> EventLoopFuture { - return client.paginate( + return self.client.paginate( input: input, initialValue: initialValue, - command: {{operation.funcName}}, + command: self.{{operation.funcName}}, {{#inputKey}} inputKey: \{{operation.inputShape}}.{{.}}, outputKey: \{{operation.outputShape}}.{{outputKey}}, @@ -70,7 +70,7 @@ extension Templates { /// - eventLoop: EventLoop to run this process on /// - onPage: closure called with each block of entries. Returns boolean indicating whether we should continue. {{#operation.deprecated}} - @available(*, deprecated, message:"{{.}}") + @available(*, deprecated, message: "{{.}}") {{/operation.deprecated}} {{scope}} func {{operation.funcName}}Paginator( _ input: {{operation.inputShape}}, @@ -78,9 +78,9 @@ extension Templates { on eventLoop: EventLoop? = nil, onPage: @escaping ({{operation.outputShape}}, EventLoop) -> EventLoopFuture ) -> EventLoopFuture { - return client.paginate( + return self.client.paginate( input: input, - command: {{operation.funcName}}, + command: self.{{operation.funcName}}, {{#inputKey}} inputKey: \{{operation.inputShape}}.{{.}}, outputKey: \{{operation.outputShape}}.{{outputKey}}, @@ -115,5 +115,6 @@ extension Templates { {{/last()}} {{/paginatorShapes}} + """# } diff --git a/Sources/SotoCodeGeneratorLib/Templates/shapes.swift b/Sources/SotoCodeGeneratorLib/Templates/shapes.swift index afd5ac9..f6e27a9 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/shapes.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/shapes.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -43,8 +43,8 @@ extension Templates { {{/struct}} {{/shapes}} } - {{#errors}} + {{>errors}} {{/errors}} diff --git a/Sources/SotoCodeGeneratorLib/Templates/struct.swift b/Sources/SotoCodeGeneratorLib/Templates/struct.swift index 04ec03d..0fe7299 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/struct.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/struct.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -31,24 +31,32 @@ extension Templates { {{#first(awsShapeMembers)}} {{scope}} static var _encoding = [ {{#awsShapeMembers}} - AWSMemberEncoding(label: "{{name}}"{{#location}}, location: {{.}}{{/location}}){{^last()}}, {{/last()}} + AWSMemberEncoding(label: "{{name}}"{{#location}}, location: {{.}}{{/location}}){{^last()}},{{/last()}} {{/awsShapeMembers}} ] + {{/first(awsShapeMembers)}} + {{^empty(encoding)}} {{#encoding}} {{! Is encoding a dictionary }} {{#key}} - {{scope}} struct {{name}}: DictionaryCoderProperties { static {{scope}} let entry: String? = {{#entry}}"{{.}}"{{/entry}}{{^entry}}nil{{/entry}}; static {{scope}} let key = "{{key}}"; static {{scope}} let value = "{{value}}" } + {{scope}} struct {{name}}: DictionaryCoderProperties { + {{scope}} static let entry: String? = {{#entry}}"{{.}}"{{/entry}}{{^entry}}nil{{/entry}} + {{scope}} static let key = "{{key}}" + {{scope}} static let value = "{{value}}" + } {{/key}} {{^key}} - {{scope}} struct {{name}}: ArrayCoderProperties { static {{scope}} let member = "{{member}}" } + {{scope}} struct {{name}}: ArrayCoderProperties { {{scope}} static let member = "{{member}}" } {{/key}} {{/encoding}} + {{/empty(encoding)}} {{! Member variables }} + {{^empty(members)}} {{#members}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#propertyWrapper}} {{.}} @@ -56,7 +64,12 @@ extension Templates { {{scope}} {{#propertyWrapper}}var{{/propertyWrapper}}{{^propertyWrapper}}let{{/propertyWrapper}} {{variable}}: {{type}} {{/members}} + {{/empty(members)}} {{! init() function }} + {{#empty(members)}} + {{scope}} init() {} + {{/empty(members)}} + {{^empty(members)}} {{scope}} init({{#initParameters}}{{parameter}}: {{type}}{{#default}} = {{.}}{{/default}}{{^last()}}, {{/last()}}{{/initParameters}}) { {{#members}} {{^deprecated}} @@ -67,9 +80,11 @@ extension Templates { {{/deprecated}} {{/members}} } + {{/empty(members)}} {{! deprecated init() function }} {{^empty(deprecatedMembers)}} - @available(*, deprecated, message:"Members {{#deprecatedMembers}}{{.}}{{^last()}}, {{/last()}}{{/deprecatedMembers}} have been deprecated") + + @available(*, deprecated, message: "Members {{#deprecatedMembers}}{{.}}{{^last()}}, {{/last()}}{{/deprecatedMembers}} have been deprecated") {{scope}} init({{#members}}{{parameter}}: {{type}}{{#default}} = {{.}}{{/default}}{{^last()}}, {{/last()}}{{/members}}) { {{#members}} self.{{variable}} = {{variable}} @@ -124,25 +139,21 @@ extension Templates { {{/validation}} } {{/first(validation)}} - {{! CodingKeys enum }} - {{#first(members)}} - {{^first(codingKeys)}} + {{^empty(members)}} + + {{#empty(codingKeys)}} private enum CodingKeys: CodingKey {} - {{/first(codingKeys)}} - {{#first(codingKeys)}} + {{/empty(codingKeys)}} + {{^empty(codingKeys)}} private enum CodingKeys: String, CodingKey { {{#codingKeys}} - {{#duplicate}} - case {{variable}} = "_{{codingKey}}" // TODO this is temporary measure for avoiding CodingKey duplication. - {{/duplicate}} - {{^duplicate}} - case {{variable}} = "{{codingKey}}" - {{/duplicate}} + case {{variable}} = "{{rawValue}}" {{/codingKeys}} } - {{/first(codingKeys)}} - {{/first(members)}} + {{/empty(codingKeys)}} + {{/empty(members)}} } + """# } diff --git a/Sources/SotoCodeGeneratorLib/Templates/waiters+async.swift b/Sources/SotoCodeGeneratorLib/Templates/waiters+async.swift index d842774..0d155b3 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/waiters+async.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/waiters+async.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -55,11 +55,11 @@ extension Templates { {{#maxDelayTime}} maxDelayTime: .seconds({{.}}), {{/maxDelayTime}} - command: {{operation.funcName}} + command: self.{{operation.funcName}} ) return try await self.client.waitUntil(input, waiter: waiter, maxWaitTime: maxWaitTime, logger: logger, on: eventLoop) } - {{#last()}} + {{^last()}} {{/last()}} {{/waiters}} diff --git a/Sources/SotoCodeGeneratorLib/Templates/waiters.swift b/Sources/SotoCodeGeneratorLib/Templates/waiters.swift index ae42080..4910489 100644 --- a/Sources/SotoCodeGeneratorLib/Templates/waiters.swift +++ b/Sources/SotoCodeGeneratorLib/Templates/waiters.swift @@ -2,7 +2,7 @@ // // This source file is part of the Soto for AWS open source project // -// Copyright (c) 2017-2021 the Soto project authors +// Copyright (c) 2017-2023 the Soto project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -20,7 +20,7 @@ extension Templates { extension {{name}} { {{#waiters}} {{#comment}} - /// {{.}} + {{>comment}} {{/comment}} {{#deprecated}} @available(*, deprecated) @@ -60,7 +60,7 @@ extension Templates { {{#maxDelayTime}} maxDelayTime: .seconds({{.}}), {{/maxDelayTime}} - command: {{operation.funcName}} + command: self.{{operation.funcName}} ) return self.client.waitUntil(input, waiter: waiter, maxWaitTime: maxWaitTime, logger: logger, on: eventLoop) } @@ -69,5 +69,6 @@ extension Templates { {{/last()}} {{/waiters}} } + """ } diff --git a/Tests/SotoCodeGeneratorTests/StringTests.swift b/Tests/SotoCodeGeneratorTests/StringTests.swift new file mode 100644 index 0000000..3a2b0c8 --- /dev/null +++ b/Tests/SotoCodeGeneratorTests/StringTests.swift @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Soto for AWS open source project +// +// Copyright (c) 2017-2023 the Soto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Soto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@testable import SotoCodeGeneratorLib +import XCTest + +/// Tests for String extensions +final class StringTests: XCTestCase { + func testDropLast() { + let s = "abc " + let result = s.dropLast { $0.isWhitespace } + XCTAssertEqual(result, "abc") + } + + func testDropLastEmptyString() { + let s = "\t\t " + let result = s.dropLast { $0.isWhitespace } + XCTAssertEqual(result, "") + } +}