-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e42afe5
commit 6349ceb
Showing
21 changed files
with
549 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
186 changes: 186 additions & 0 deletions
186
...wift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/DirectedSwiftCodegen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
|
||
package software.amazon.smithy.swift.codegen | ||
|
||
import software.amazon.smithy.build.PluginContext | ||
import software.amazon.smithy.codegen.core.SymbolProvider | ||
import software.amazon.smithy.codegen.core.directed.CreateContextDirective | ||
import software.amazon.smithy.codegen.core.directed.CreateSymbolProviderDirective | ||
import software.amazon.smithy.codegen.core.directed.DirectedCodegen | ||
import software.amazon.smithy.codegen.core.directed.GenerateEnumDirective | ||
import software.amazon.smithy.codegen.core.directed.GenerateErrorDirective | ||
import software.amazon.smithy.codegen.core.directed.GenerateIntEnumDirective | ||
import software.amazon.smithy.codegen.core.directed.GenerateServiceDirective | ||
import software.amazon.smithy.codegen.core.directed.GenerateStructureDirective | ||
import software.amazon.smithy.codegen.core.directed.GenerateUnionDirective | ||
import software.amazon.smithy.model.Model | ||
import software.amazon.smithy.model.knowledge.ServiceIndex | ||
import software.amazon.smithy.model.shapes.ServiceShape | ||
import software.amazon.smithy.model.traits.SensitiveTrait | ||
import software.amazon.smithy.swift.codegen.core.GenerationContext | ||
import software.amazon.smithy.swift.codegen.integration.CustomDebugStringConvertibleGenerator | ||
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator | ||
import software.amazon.smithy.swift.codegen.integration.SwiftIntegration | ||
import software.amazon.smithy.swift.codegen.model.hasTrait | ||
import java.util.logging.Logger | ||
|
||
class DirectedSwiftCodegen(val context: PluginContext) : | ||
DirectedCodegen<GenerationContext, SwiftSettings, SwiftIntegration> { | ||
private val LOGGER = Logger.getLogger(javaClass.name) | ||
|
||
override fun createSymbolProvider(directive: CreateSymbolProviderDirective<SwiftSettings>): SymbolProvider { | ||
return SwiftSymbolProvider(directive.model(), directive.settings()) | ||
} | ||
|
||
override fun createContext(directive: CreateContextDirective<SwiftSettings, SwiftIntegration>): GenerationContext { | ||
val model = directive.model() | ||
val service = directive.service() | ||
val settings = directive.settings() | ||
val integrations = directive.integrations() | ||
|
||
val protocolGenerator = resolveProtocolGenerator(integrations, model, service, settings) | ||
|
||
for (integration in integrations) { | ||
integration.serviceErrorProtocolSymbol()?.let { | ||
protocolGenerator?.serviceErrorProtocolSymbol = it | ||
} | ||
} | ||
|
||
return GenerationContext( | ||
directive.model(), | ||
directive.symbolProvider(), | ||
directive.settings(), | ||
directive.fileManifest(), | ||
protocolGenerator, | ||
directive.integrations() | ||
) | ||
} | ||
|
||
override fun generateService(directive: GenerateServiceDirective<GenerationContext, SwiftSettings>) { | ||
val service = directive.service() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val integrations = context.integrations | ||
val fileManifest = context.fileManifest | ||
val writers = context.writerDelegator() | ||
|
||
LOGGER.info("Generating Swift client for service ${directive.settings().service}") | ||
|
||
var shouldGenerateTestTarget = false | ||
context.protocolGenerator?.apply { | ||
val ctx = ProtocolGenerator.GenerationContext(settings, model, service, symbolProvider, integrations, this.protocol, writers) | ||
LOGGER.info("[${service.id}] Generating serde for protocol ${this.protocol}") | ||
generateSerializers(ctx) | ||
generateDeserializers(ctx) | ||
generateMessageMarshallable(ctx) | ||
generateMessageUnmarshallable(ctx) | ||
generateCodableConformanceForNestedTypes(ctx) | ||
|
||
initializeMiddleware(ctx) | ||
|
||
LOGGER.info("[${service.id}] Generating unit tests for protocol ${this.protocol}") | ||
val numProtocolUnitTestsGenerated = generateProtocolUnitTests(ctx) | ||
shouldGenerateTestTarget = (numProtocolUnitTestsGenerated > 0) | ||
|
||
LOGGER.info("[${service.id}] Generating service client for protocol ${this.protocol}") | ||
|
||
generateProtocolClient(ctx) | ||
|
||
integrations.forEach { it.writeAdditionalFiles(context, ctx, writers) } | ||
} | ||
|
||
println("Flushing swift writers") | ||
val dependencies = writers.dependencies | ||
writers.flushWriters() | ||
|
||
println("Generating package manifest file") | ||
writePackageManifest(settings, fileManifest, dependencies, shouldGenerateTestTarget) | ||
} | ||
|
||
override fun generateStructure(directive: GenerateStructureDirective<GenerationContext, SwiftSettings>) { | ||
val shape = directive.shape() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val protocolGenerator = context.protocolGenerator | ||
val writers = context.writerDelegator() | ||
|
||
writers.useShapeWriter(shape) { writer: SwiftWriter -> | ||
StructureGenerator(model, symbolProvider, writer, shape, settings, protocolGenerator?.serviceErrorProtocolSymbol).render() | ||
} | ||
|
||
if (shape.hasTrait<SensitiveTrait>() || shape.members().any { it.hasTrait<SensitiveTrait>() || model.expectShape(it.target).hasTrait<SensitiveTrait>() }) { | ||
writers.useShapeExtensionWriter(shape, "CustomDebugStringConvertible") { writer: SwiftWriter -> | ||
CustomDebugStringConvertibleGenerator(symbolProvider, writer, shape, model).render() | ||
} | ||
} | ||
} | ||
|
||
override fun generateError(directive: GenerateErrorDirective<GenerationContext, SwiftSettings>) { | ||
val shape = directive.shape() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val protocolGenerator = context.protocolGenerator | ||
val writers = context.writerDelegator() | ||
|
||
writers.useShapeWriter(shape) { writer: SwiftWriter -> | ||
StructureGenerator(model, symbolProvider, writer, shape, settings, protocolGenerator?.serviceErrorProtocolSymbol).renderErrors() | ||
} | ||
} | ||
|
||
override fun generateUnion(directive: GenerateUnionDirective<GenerationContext, SwiftSettings>) { | ||
val shape = directive.shape() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val writers = context.writerDelegator() | ||
writers.useShapeWriter(shape) { writer: SwiftWriter -> UnionGenerator(model, symbolProvider, writer, shape, settings).render() } | ||
} | ||
|
||
override fun generateEnumShape(directive: GenerateEnumDirective<GenerationContext, SwiftSettings>) { | ||
val shape = directive.shape() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val writers = context.writerDelegator() | ||
writers.useShapeWriter(shape) { writer: SwiftWriter -> EnumGenerator(model, symbolProvider, writer, shape, settings).render() } | ||
} | ||
|
||
override fun generateIntEnumShape(directive: GenerateIntEnumDirective<GenerationContext, SwiftSettings>) { | ||
val shape = directive.shape() | ||
val context = directive.context() | ||
val model = directive.model() | ||
val settings = directive.settings() | ||
val symbolProvider = directive.symbolProvider() | ||
val writers = context.writerDelegator() | ||
writers.useShapeWriter(shape) { writer: SwiftWriter -> IntEnumGenerator(model, symbolProvider, writer, shape.asIntEnumShape().get(), settings).render() } | ||
} | ||
|
||
private fun resolveProtocolGenerator( | ||
integrations: List<SwiftIntegration>, | ||
model: Model, | ||
service: ServiceShape, | ||
settings: SwiftSettings | ||
): ProtocolGenerator? { | ||
val generators = integrations.flatMap { it.protocolGenerators }.associateBy { it.protocol } | ||
val serviceIndex = ServiceIndex.of(model) | ||
|
||
try { | ||
val protocolTrait = settings.resolveServiceProtocol(serviceIndex, service, generators.keys) | ||
return generators[protocolTrait] | ||
} catch (ex: UnresolvableProtocolException) { | ||
LOGGER.warning("Unable to find protocol generator for ${service.id}: ${ex.message}") | ||
} | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.