diff --git a/README.md b/README.md index 938e839..ff497d7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ to your Package.swift- ```swift dependencies: [ - .package(url: "https://github.com/amzn/service-model-swift-code-generate.git", .upToNextMajor(from: "0.1.0")) + .package(url: "https://github.com/amzn/service-model-swift-code-generate.git", from: "3.0.0") ] ``` @@ -45,10 +45,15 @@ extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport ...) throws { let myClientDelegate = ... let myModelErrorsDelegate = ... + let defaultTraceContextType = DefaultTraceContextType(...) + let operationsReportingType = OperationsReportingType(...) + let invocationReportingType = InvocationReportingType(...) - generateClient(delegate: myClientDelegate) + generateClient(delegate: myClientDelegate, fileType: .clientImplementation, + defaultTraceContextType: defaultTraceContextType) generateModelOperationsEnum() - generateOperationsReporting() + generateOperationsReporting(operationsReportingType: operationsReportingType) + generateInvocationsReporting(invocationReportingType: invocationReportingType) generateModelOperationClientInput() generateModelOperationClientOutput() generateModelOperationHTTPInput() diff --git a/Sources/ServiceModelGenerate/MockClientDelegate.swift b/Sources/ServiceModelGenerate/MockClientDelegate.swift index e586c06..5888bbf 100644 --- a/Sources/ServiceModelGenerate/MockClientDelegate.swift +++ b/Sources/ServiceModelGenerate/MockClientDelegate.swift @@ -31,6 +31,7 @@ public struct MockClientDelegate: ModelClientDelegate { public let asyncAwaitAPIs: CodeGenFeatureStatus public let eventLoopFutureClientAPIs: CodeGenFeatureStatus public let minimumCompilerSupport: MinimumCompilerSupport + public let supportingTargetName: String? /** Initializer. @@ -38,16 +39,21 @@ public struct MockClientDelegate: ModelClientDelegate { - Parameters: - baseName: The base name of the Service. - isThrowingMock: true to generate a throwing mock; false for a normal mock - - asyncResultType: The name of the result type to use for async functions. + - asyncAwaitAPIs: If APIs using Swift Concurrency should be generated. + - eventLoopFutureClientAPIs: If APIs using EventLoopFutures should be generated. + - supportingTargetName: the target name to be imported to provide the implementation for EventLoopFuture-based APIs. + - minimumCompilerSupport: the minimum compiler version that needs to be supported by the client. */ public init(baseName: String, isThrowingMock: Bool, asyncAwaitAPIs: CodeGenFeatureStatus, eventLoopFutureClientAPIs: CodeGenFeatureStatus = .enabled, + supportingTargetName: String? = nil, minimumCompilerSupport: MinimumCompilerSupport = .unknown) { self.baseName = baseName self.isThrowingMock = isThrowingMock self.asyncAwaitAPIs = asyncAwaitAPIs self.eventLoopFutureClientAPIs = eventLoopFutureClientAPIs + self.supportingTargetName = supportingTargetName self.minimumCompilerSupport = minimumCompilerSupport let name: String @@ -62,8 +68,13 @@ public struct MockClientDelegate: ModelClientDelegate { self.defaultBehaviourDescription = "return the `__default` property of its return type." } + var conformingProtocolNames = ["\(baseName)ClientProtocol"] + if case .enabled = eventLoopFutureClientAPIs { + conformingProtocolNames.append(implementationProviderProtocol) + } + self.clientType = .struct(name: name, genericParameters: [], - conformingProtocolNames: ["\(baseName)ClientProtocol", implementationProviderProtocol]) + conformingProtocolNames: conformingProtocolNames) } public func addTypeDescription(codeGenerator: ServiceModelCodeGenerator, @@ -109,9 +120,11 @@ public struct MockClientDelegate: ModelClientDelegate { delegate: Self, fileBuilder: FileBuilder, fileType: ClientFileType) { - fileBuilder.appendLine(""" - import SmokeAWSHttp - """) + if let supportingTargetName = self.supportingTargetName { + fileBuilder.appendLine(""" + import \(supportingTargetName) + """) + } } private func addCommonFunctionsForOperation(name: String, index: Int, diff --git a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateClient.swift b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateClient.swift index 37decf9..50a0233 100644 --- a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateClient.swift +++ b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateClient.swift @@ -21,6 +21,16 @@ import ServiceModelEntities internal let asyncAwaitCondition = "#if (os(Linux) && compiler(>=5.5)) || (!os(Linux) && compiler(>=5.5.2)) && canImport(_Concurrency)" +public struct DefaultTraceContextType { + public let typeName: String + public let importTargetName: String? + + public init(typeName: String, importTargetName: String?) { + self.typeName = typeName + self.importTargetName = importTargetName + } +} + public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport & ClientTargetSupport { private struct OperationSignature { let input: String @@ -35,8 +45,11 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS - Parameters: - delegate: The delegate to use when generating this client. + - fileType: the type of client to be generated. + - defaultTraceContextType: the trace context type to be used by default by the client. */ - func generateClient(delegate: DelegateType, fileType: ClientFileType) + func generateClient(delegate: DelegateType, fileType: ClientFileType, + defaultTraceContextType: DefaultTraceContextType) where DelegateType.TargetSupportType == TargetSupportType { let fileBuilder = FileBuilder() let clientTargetName = self.targetSupport.clientTargetName @@ -66,7 +79,8 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS delegate.addCustomFileHeader(codeGenerator: self, delegate: delegate, fileBuilder: fileBuilder, fileType: fileType) - let defaultInvocationReportingType = "StandardHTTPClientCoreInvocationReporting" + let defaultTraceContextTypeName = defaultTraceContextType.typeName + let defaultInvocationReportingType = "StandardHTTPClientCoreInvocationReporting<\(defaultTraceContextTypeName)>" switch fileType { case .clientImplementation: @@ -576,7 +590,9 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS import Foundation import \(modelTargetName) - import SmokeAWSCore + """) + + fileBuilder.appendLine(""" import SmokeHTTPClient """) diff --git a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelInvocationsReporting.swift b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelInvocationsReporting.swift index c831a74..d26d981 100644 --- a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelInvocationsReporting.swift +++ b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelInvocationsReporting.swift @@ -19,11 +19,27 @@ import Foundation import ServiceModelCodeGeneration import ServiceModelEntities +public struct InvocationReportingType { + public let typeName: String + public let targetImportName: String? + public let initializeFromOperationsReporting: (_ variableName: String, _ prefix: String, _ fileBuilder: FileBuilder) -> () + + public init(typeName: String, targetImportName: String?, + initializeFromOperationsReporting: @escaping (_ variableName: String, _ prefix: String, _ fileBuilder: FileBuilder) -> Void) { + self.typeName = typeName + self.targetImportName = targetImportName + self.initializeFromOperationsReporting = initializeFromOperationsReporting + } +} + public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport & ClientTargetSupport { /** Generate an operation enumeration for the model. + + - Parameters: + - invocationReportingType: The type to use for invocation reporting. */ - func generateInvocationsReporting() { + func generateInvocationsReporting(invocationReportingType: InvocationReportingType) { let fileBuilder = FileBuilder() let baseName = applicationDescription.baseName @@ -42,7 +58,13 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS import Foundation import SmokeHTTPClient - import SmokeAWSHttp + """) + + if let invocationReportingTypeTargetName = invocationReportingType.targetImportName { + fileBuilder.appendLine("import \(invocationReportingTypeTargetName)") + } + + fileBuilder.appendLine(""" import \(modelTargetName) """) @@ -67,10 +89,12 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS let sortedOperations = model.operationDescriptions.sorted { (left, right) in left.key < right.key } fileBuilder.incIndent() - addOperationReportingParameters(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations) + addOperationReportingParameters(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations, + invocationReportingType: invocationReportingType) fileBuilder.appendEmptyLine() - addOperationReportingInitializer(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations) + addOperationReportingInitializer(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations, + invocationReportingType: invocationReportingType) fileBuilder.decIndent() fileBuilder.appendLine("}") @@ -81,29 +105,28 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS } private func addOperationReportingParameters(fileBuilder: FileBuilder, baseName: String, - sortedOperations: [(String, OperationDescription)]) { + sortedOperations: [(String, OperationDescription)], + invocationReportingType: InvocationReportingType) { sortedOperations.forEach { (name, operation) in let variableName = getNormalizedVariableName(modelTypeName: name) fileBuilder.appendLine(""" - public let \(variableName): SmokeAWSHTTPClientInvocationReporting + public let \(variableName): \(invocationReportingType.typeName) """) } } private func addOperationReportingInitializer(fileBuilder: FileBuilder, baseName: String, - sortedOperations: [(String, OperationDescription)]) { + sortedOperations: [(String, OperationDescription)], + invocationReportingType: InvocationReportingType) { fileBuilder.appendLine(""" public init(reporting: InvocationReportingType, operationsReporting: \(baseName)OperationsReporting) { """) fileBuilder.incIndent() sortedOperations.forEach { (name, operation) in let variableName = getNormalizedVariableName(modelTypeName: name) - - fileBuilder.appendLine(""" - self.\(variableName) = SmokeAWSHTTPClientInvocationReporting(smokeAWSInvocationReporting: reporting, - smokeAWSOperationReporting: operationsReporting.\(variableName)) - """) + + invocationReportingType.initializeFromOperationsReporting(variableName, "self.\(variableName) = ", fileBuilder) } fileBuilder.appendLine("}", preDec: true) diff --git a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelOperationsReporting.swift b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelOperationsReporting.swift index 39b9c7a..a1e7e3c 100644 --- a/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelOperationsReporting.swift +++ b/Sources/ServiceModelGenerate/ServiceModelCodeGenerator+generateModelOperationsReporting.swift @@ -19,11 +19,27 @@ import Foundation import ServiceModelCodeGeneration import ServiceModelEntities +public struct OperationsReportingType { + public let typeName: String + public let targetImportName: String? + public let initializeFromConfiguration: (_ variableName: String, _ prefix: String, _ fileBuilder: FileBuilder) -> () + + public init(typeName: String, targetImportName: String?, + initializeFromConfiguration: @escaping (_ variableName: String, _ prefix: String, _ fileBuilder: FileBuilder) -> Void) { + self.typeName = typeName + self.targetImportName = targetImportName + self.initializeFromConfiguration = initializeFromConfiguration + } +} + public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport & ClientTargetSupport { /** Generate an operation enumeration for the model. + + - Parameters: + - operationsReportingType: The type to use for operations reporting. */ - func generateOperationsReporting() { + func generateOperationsReporting(operationsReportingType: OperationsReportingType) { let fileBuilder = FileBuilder() let baseName = applicationDescription.baseName @@ -41,7 +57,14 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS // import Foundation - import SmokeAWSCore + import SmokeHTTPClient + """) + + if let operationsReportingTypeTargetName = operationsReportingType.targetImportName { + fileBuilder.appendLine("import \(operationsReportingTypeTargetName)") + } + + fileBuilder.appendLine(""" import \(modelTargetName) """) @@ -60,10 +83,12 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS let sortedOperations = model.operationDescriptions.sorted { (left, right) in left.key < right.key } fileBuilder.incIndent() - addOperationReportingParameters(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations) + addOperationReportingParameters(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations, + operationsReportingType: operationsReportingType) fileBuilder.appendEmptyLine() - addOperationReportingInitializer(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations) + addOperationReportingInitializer(fileBuilder: fileBuilder, baseName: baseName, sortedOperations: sortedOperations, + operationsReportingType: operationsReportingType) fileBuilder.decIndent() fileBuilder.appendLine("}") @@ -74,27 +99,26 @@ public extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetS } private func addOperationReportingParameters(fileBuilder: FileBuilder, baseName: String, - sortedOperations: [(String, OperationDescription)]) { + sortedOperations: [(String, OperationDescription)], + operationsReportingType: OperationsReportingType) { sortedOperations.forEach { (name, operation) in let variableName = getNormalizedVariableName(modelTypeName: name) fileBuilder.appendLine(""" - public let \(variableName): StandardSmokeAWSOperationReporting<\(baseName)ModelOperations> + public let \(variableName): \(operationsReportingType.typeName)<\(baseName)ModelOperations> """) } } private func addOperationReportingInitializer(fileBuilder: FileBuilder, baseName: String, - sortedOperations: [(String, OperationDescription)]) { - fileBuilder.appendLine("public init(clientName: String, reportingConfiguration: SmokeAWSClientReportingConfiguration<\(baseName)ModelOperations>) {", + sortedOperations: [(String, OperationDescription)], + operationsReportingType: OperationsReportingType) { + fileBuilder.appendLine("public init(clientName: String, reportingConfiguration: HTTPClientReportingConfiguration<\(baseName)ModelOperations>) {", postInc: true) sortedOperations.forEach { (name, operation) in let variableName = getNormalizedVariableName(modelTypeName: name) - - fileBuilder.appendLine(""" - self.\(variableName) = StandardSmokeAWSOperationReporting( - clientName: clientName, operation: .\(variableName), configuration: reportingConfiguration) - """) + + operationsReportingType.initializeFromConfiguration(variableName, "self.\(variableName) = ", fileBuilder) } fileBuilder.appendLine("}", preDec: true)