Loading codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenContext.kt +24 −0 Original line number Diff line number Diff line Loading @@ -13,12 +13,36 @@ import software.amazon.smithy.model.shapes.ShapeId * Configuration needed to generate the client for a given Service<->Protocol pair */ data class CodegenContext( /** * The smithy model. * * Note: This model may or not be pruned to the given service closure, so ensure that `serviceShape` is used as * an entry point. */ val model: Model, val symbolProvider: RustSymbolProvider, /** * Configuration of the runtime package: * - Where are the runtime crates (smithy-*) located on the file system? Or are they versioned? * - What are they called? */ val runtimeConfig: RuntimeConfig, /** * Entrypoint service shape for code generation */ val serviceShape: ServiceShape, /** * Smithy Protocol to generate, eg. RestJson1 */ val protocol: ShapeId, /** * The name of the cargo crate to generate eg. `aws-sdk-s3` * This is loaded from the smithy-build.json during codegen. */ val moduleName: String, /** * Settings loaded from smithy-build.json */ val settings: RustSettings, ) { constructor( Loading codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenDelegator.kt +39 −0 Original line number Diff line number Diff line Loading @@ -21,18 +21,46 @@ import software.amazon.smithy.rust.codegen.smithy.generators.LibRsCustomization import software.amazon.smithy.rust.codegen.smithy.generators.LibRsGenerator import software.amazon.smithy.rust.codegen.smithy.generators.ManifestCustomizations /** * RustCrate abstraction. * * **Note**: This is the only implementation, `open` only for test purposes. * * All code-generation at some point goes through this class. `RustCrate` maintains a `CodegenWriterDelegator` internally * which tracks a set of file-writer pairs and allows them to be loaded and cached (see: [useShapeWriter]) * * On top of this, it adds Rust specific features: * - Generation of a `lib.rs` which adds `mod` statements automatically for every module that was used * - Tracking dependencies and crate features used during code generation, enabling generation of `Cargo.toml` * * Users will generally want to use two main entry points: * 1. [useShapeWriter]: Find or create a writer that will contain a given shape. See [locatedIn] for context about how * shape locations are determined. * 2. [finalize]: Write the crate out to the file system, generating a lib.rs and Cargo.toml */ open class RustCrate( fileManifest: FileManifest, symbolProvider: SymbolProvider, /** * For core modules like `input`, `output`, and `error`, we need to specify whether these modules should be public or * private as well as any other metadata. [baseModules] enables configuring this. See [DefaultPublicModules]. */ baseModules: Map<String, RustModule> ) { private val inner = CodegenWriterDelegator(fileManifest, symbolProvider, RustWriter.Factory) private val modules: MutableMap<String, RustModule> = baseModules.toMutableMap() private val features: MutableSet<Feature> = mutableSetOf() /** * Write into the module that this shape is [locatedIn] */ fun useShapeWriter(shape: Shape, f: (RustWriter) -> Unit) { inner.useShapeWriter(shape, f) } /** * Write directly into lib.rs */ fun lib(moduleWriter: (RustWriter) -> Unit) { inner.useFileWriter("src/lib.rs", "crate", moduleWriter) } Loading @@ -51,6 +79,11 @@ open class RustCrate( } } /** * Finalize Cargo.toml and lib.rs and flush the writers to the file system. * * This is also where inline dependencies are actually reified and written, potentially recursively. */ fun finalize( settings: RustSettings, model: Model, Loading Loading @@ -82,6 +115,9 @@ open class RustCrate( } } /** * Create a new module directly. The resulting module will be placed in `src/<modulename>.rs` */ fun withModule( module: RustModule, moduleWriter: (RustWriter) -> Unit Loading @@ -92,6 +128,9 @@ open class RustCrate( return this } /** * Create a new file directly */ fun withFile(filename: String, fileWriter: (RustWriter) -> Unit) { inner.useFileWriter(filename) { fileWriter(it) Loading codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RuntimeTypes.kt +56 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,20 @@ import software.amazon.smithy.rust.codegen.rustlang.RustWriter import software.amazon.smithy.rust.codegen.rustlang.asType import java.util.Optional /** * Location of the runtime crates (smithy-http, smithy-types etc.) * * This can be configured via the `runtimeConfig.version` field in smithy-build.json */ sealed class RuntimeCrateLocation { /** * Relative path to find the runtime crates, eg. `../` */ data class Path(val path: String) : RuntimeCrateLocation() /** * Version for the runtime crates, eg. `v0.0.1-alpha` */ data class Versioned(val version: String) : RuntimeCrateLocation() } Loading @@ -30,12 +42,18 @@ fun RuntimeCrateLocation.crateLocation(): DependencyLocation = when (this) { is RuntimeCrateLocation.Versioned -> CratesIo(this.version) } /** * Prefix & crate location for the runtime crates. */ data class RuntimeConfig( val cratePrefix: String = "smithy", val runtimeCrateLocation: RuntimeCrateLocation = RuntimeCrateLocation.Path("../") ) { companion object { /** * Load a `RuntimeConfig` from an [ObjectNode] (JSON) */ fun fromNode(node: Optional<ObjectNode>): RuntimeConfig { return if (node.isPresent) { val runtimeCrateLocation = if (node.get().containsMember("version")) { Loading @@ -57,7 +75,31 @@ data class RuntimeConfig( CargoDependency("$cratePrefix-$runtimeCrateName", runtimeCrateLocation.crateLocation(), optional = optional) } /** * `RuntimeType` captures all necessary information to render a type into a Rust file: * - [name]: What type is this? * - [dependency]: What other crates, if any, are required to use this type? * - [namespace]: Where can we find this type. * * For example: * * `http::header::HeaderName` * ------------ ---------- * | | * [namespace] [name] * * This type would have a [CargoDependency] pointing to the `http` crate. * * By grouping all of this information, when we render a type into a [RustWriter], we can not only render a fully qualified * name, but also ensure that we automatically add any dependencies **as they are used**. */ data class RuntimeType(val name: String?, val dependency: RustDependency?, val namespace: String) { /** * Convert this [RuntimeType] into a [Symbol]. * * This is not commonly required, but is occasionally useful when you want to force an import without referencing a type * (eg. when bringing a trait into scope). See [CodegenWriter.addUseImports]. */ fun toSymbol(): Symbol { val builder = Symbol.builder().name(name).namespace(namespace, "::") .rustType(RustType.Opaque(name ?: "", namespace = namespace)) Loading @@ -66,17 +108,31 @@ data class RuntimeType(val name: String?, val dependency: RustDependency?, val n return builder.build() } /** * Create a new [RuntimeType] with a nested name. * * # Example * ```kotlin * val http = CargoDependency.http.member("Request") * ``` */ fun member(member: String): RuntimeType { val newName = name?.let { "$name::$member" } ?: member return copy(name = newName) } /** * Returns the fully qualified name for this type */ fun fullyQualifiedName(): String { val postFix = name?.let { "::$name" } ?: "" return "$namespace$postFix" } // TODO: refactor to be RuntimeTypeProvider a la Symbol provider that packages the `RuntimeConfig` state. /** * The companion object contains commonly used RuntimeTypes */ companion object { fun errorKind(runtimeConfig: RuntimeConfig) = RuntimeType( "ErrorKind", Loading codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RetryConfigDecorator.kt→codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/RetryConfigDecorator.kt +1 −1 File changed and moved.Contains only whitespace changes. Show changes gradle/jvm.gradledeleted 100644 → 0 +0 −39 Original line number Diff line number Diff line /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ kotlin { targets { fromPreset(presets.jvm, 'jvm') } sourceSets { jvmMain.dependencies { api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlinVersion implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" } jvmTest.dependencies { api 'org.jetbrains.kotlin:kotlin-test' api 'org.jetbrains.kotlin:kotlin-test-junit' api 'junit:junit:$junitVersion' // api "org.junit.jupiter:junit-jupiter-api" api group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlinVersion // api group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit5', version: kotlinVersion api group: 'junit', name: 'junit', version: junitVersion // api group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junitVersion implementation "org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutinesVersion" implementation "io.kotest:kotest-assertions-core-jvm:$kotestVersion" } } } jvmTest { testLogging { events("passed", "skipped", "failed") showStandardStreams = true } } Loading
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenContext.kt +24 −0 Original line number Diff line number Diff line Loading @@ -13,12 +13,36 @@ import software.amazon.smithy.model.shapes.ShapeId * Configuration needed to generate the client for a given Service<->Protocol pair */ data class CodegenContext( /** * The smithy model. * * Note: This model may or not be pruned to the given service closure, so ensure that `serviceShape` is used as * an entry point. */ val model: Model, val symbolProvider: RustSymbolProvider, /** * Configuration of the runtime package: * - Where are the runtime crates (smithy-*) located on the file system? Or are they versioned? * - What are they called? */ val runtimeConfig: RuntimeConfig, /** * Entrypoint service shape for code generation */ val serviceShape: ServiceShape, /** * Smithy Protocol to generate, eg. RestJson1 */ val protocol: ShapeId, /** * The name of the cargo crate to generate eg. `aws-sdk-s3` * This is loaded from the smithy-build.json during codegen. */ val moduleName: String, /** * Settings loaded from smithy-build.json */ val settings: RustSettings, ) { constructor( Loading
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/CodegenDelegator.kt +39 −0 Original line number Diff line number Diff line Loading @@ -21,18 +21,46 @@ import software.amazon.smithy.rust.codegen.smithy.generators.LibRsCustomization import software.amazon.smithy.rust.codegen.smithy.generators.LibRsGenerator import software.amazon.smithy.rust.codegen.smithy.generators.ManifestCustomizations /** * RustCrate abstraction. * * **Note**: This is the only implementation, `open` only for test purposes. * * All code-generation at some point goes through this class. `RustCrate` maintains a `CodegenWriterDelegator` internally * which tracks a set of file-writer pairs and allows them to be loaded and cached (see: [useShapeWriter]) * * On top of this, it adds Rust specific features: * - Generation of a `lib.rs` which adds `mod` statements automatically for every module that was used * - Tracking dependencies and crate features used during code generation, enabling generation of `Cargo.toml` * * Users will generally want to use two main entry points: * 1. [useShapeWriter]: Find or create a writer that will contain a given shape. See [locatedIn] for context about how * shape locations are determined. * 2. [finalize]: Write the crate out to the file system, generating a lib.rs and Cargo.toml */ open class RustCrate( fileManifest: FileManifest, symbolProvider: SymbolProvider, /** * For core modules like `input`, `output`, and `error`, we need to specify whether these modules should be public or * private as well as any other metadata. [baseModules] enables configuring this. See [DefaultPublicModules]. */ baseModules: Map<String, RustModule> ) { private val inner = CodegenWriterDelegator(fileManifest, symbolProvider, RustWriter.Factory) private val modules: MutableMap<String, RustModule> = baseModules.toMutableMap() private val features: MutableSet<Feature> = mutableSetOf() /** * Write into the module that this shape is [locatedIn] */ fun useShapeWriter(shape: Shape, f: (RustWriter) -> Unit) { inner.useShapeWriter(shape, f) } /** * Write directly into lib.rs */ fun lib(moduleWriter: (RustWriter) -> Unit) { inner.useFileWriter("src/lib.rs", "crate", moduleWriter) } Loading @@ -51,6 +79,11 @@ open class RustCrate( } } /** * Finalize Cargo.toml and lib.rs and flush the writers to the file system. * * This is also where inline dependencies are actually reified and written, potentially recursively. */ fun finalize( settings: RustSettings, model: Model, Loading Loading @@ -82,6 +115,9 @@ open class RustCrate( } } /** * Create a new module directly. The resulting module will be placed in `src/<modulename>.rs` */ fun withModule( module: RustModule, moduleWriter: (RustWriter) -> Unit Loading @@ -92,6 +128,9 @@ open class RustCrate( return this } /** * Create a new file directly */ fun withFile(filename: String, fileWriter: (RustWriter) -> Unit) { inner.useFileWriter(filename) { fileWriter(it) Loading
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RuntimeTypes.kt +56 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,20 @@ import software.amazon.smithy.rust.codegen.rustlang.RustWriter import software.amazon.smithy.rust.codegen.rustlang.asType import java.util.Optional /** * Location of the runtime crates (smithy-http, smithy-types etc.) * * This can be configured via the `runtimeConfig.version` field in smithy-build.json */ sealed class RuntimeCrateLocation { /** * Relative path to find the runtime crates, eg. `../` */ data class Path(val path: String) : RuntimeCrateLocation() /** * Version for the runtime crates, eg. `v0.0.1-alpha` */ data class Versioned(val version: String) : RuntimeCrateLocation() } Loading @@ -30,12 +42,18 @@ fun RuntimeCrateLocation.crateLocation(): DependencyLocation = when (this) { is RuntimeCrateLocation.Versioned -> CratesIo(this.version) } /** * Prefix & crate location for the runtime crates. */ data class RuntimeConfig( val cratePrefix: String = "smithy", val runtimeCrateLocation: RuntimeCrateLocation = RuntimeCrateLocation.Path("../") ) { companion object { /** * Load a `RuntimeConfig` from an [ObjectNode] (JSON) */ fun fromNode(node: Optional<ObjectNode>): RuntimeConfig { return if (node.isPresent) { val runtimeCrateLocation = if (node.get().containsMember("version")) { Loading @@ -57,7 +75,31 @@ data class RuntimeConfig( CargoDependency("$cratePrefix-$runtimeCrateName", runtimeCrateLocation.crateLocation(), optional = optional) } /** * `RuntimeType` captures all necessary information to render a type into a Rust file: * - [name]: What type is this? * - [dependency]: What other crates, if any, are required to use this type? * - [namespace]: Where can we find this type. * * For example: * * `http::header::HeaderName` * ------------ ---------- * | | * [namespace] [name] * * This type would have a [CargoDependency] pointing to the `http` crate. * * By grouping all of this information, when we render a type into a [RustWriter], we can not only render a fully qualified * name, but also ensure that we automatically add any dependencies **as they are used**. */ data class RuntimeType(val name: String?, val dependency: RustDependency?, val namespace: String) { /** * Convert this [RuntimeType] into a [Symbol]. * * This is not commonly required, but is occasionally useful when you want to force an import without referencing a type * (eg. when bringing a trait into scope). See [CodegenWriter.addUseImports]. */ fun toSymbol(): Symbol { val builder = Symbol.builder().name(name).namespace(namespace, "::") .rustType(RustType.Opaque(name ?: "", namespace = namespace)) Loading @@ -66,17 +108,31 @@ data class RuntimeType(val name: String?, val dependency: RustDependency?, val n return builder.build() } /** * Create a new [RuntimeType] with a nested name. * * # Example * ```kotlin * val http = CargoDependency.http.member("Request") * ``` */ fun member(member: String): RuntimeType { val newName = name?.let { "$name::$member" } ?: member return copy(name = newName) } /** * Returns the fully qualified name for this type */ fun fullyQualifiedName(): String { val postFix = name?.let { "::$name" } ?: "" return "$namespace$postFix" } // TODO: refactor to be RuntimeTypeProvider a la Symbol provider that packages the `RuntimeConfig` state. /** * The companion object contains commonly used RuntimeTypes */ companion object { fun errorKind(runtimeConfig: RuntimeConfig) = RuntimeType( "ErrorKind", Loading
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RetryConfigDecorator.kt→codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/RetryConfigDecorator.kt +1 −1 File changed and moved.Contains only whitespace changes. Show changes
gradle/jvm.gradledeleted 100644 → 0 +0 −39 Original line number Diff line number Diff line /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ kotlin { targets { fromPreset(presets.jvm, 'jvm') } sourceSets { jvmMain.dependencies { api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlinVersion implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" } jvmTest.dependencies { api 'org.jetbrains.kotlin:kotlin-test' api 'org.jetbrains.kotlin:kotlin-test-junit' api 'junit:junit:$junitVersion' // api "org.junit.jupiter:junit-jupiter-api" api group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlinVersion // api group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit5', version: kotlinVersion api group: 'junit', name: 'junit', version: junitVersion // api group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junitVersion implementation "org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutinesVersion" implementation "io.kotest:kotest-assertions-core-jvm:$kotestVersion" } } } jvmTest { testLogging { events("passed", "skipped", "failed") showStandardStreams = true } }