diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ed8a99ff5..29e53ee59e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ vNext (Month Day, Year) ======================= **New this week** +- Fix typos in module documentation for generated crates (smithy-rs#920) **Breaking changes** diff --git a/aws/SDK_CHANGELOG.md b/aws/SDK_CHANGELOG.md index 727069730b..33d1bdcbfe 100644 --- a/aws/SDK_CHANGELOG.md +++ b/aws/SDK_CHANGELOG.md @@ -1,6 +1,7 @@ vNext (Month Day, Year) ======================= **New this release** +- Fix typos in module documentation for generated crates (smithy-rs#920) v0.2.0 (December 2nd, 2021) =========================== diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsReadmeDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsReadmeDecorator.kt index 2c2edf7a3c..91953af765 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsReadmeDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsReadmeDecorator.kt @@ -47,7 +47,7 @@ class AwsReadmeDecorator : RustCodegenDecorator { """ # $moduleName - **Please Note: The SDK is currently released as an alpha and is intended strictly for + **Please Note: The SDK is currently in Developer Preview and is intended strictly for feedback purposes only. Do not use this SDK for production workloads.** """.trimIndent() + "\n\n$description\n\n" + diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt index 34899cbe99..a97c043923 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/rustlang/RustWriter.kt @@ -276,6 +276,12 @@ fun writable(w: Writable): Writable = w fun writable(w: String): Writable = writable { rust(w) } +fun Writable.isEmpty(): Boolean { + val writer = RustWriter.root() + this(writer) + return writer.toString() == RustWriter.root().toString() +} + class RustWriter private constructor( private val filename: String, val namespace: String, diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt index 5755932d3f..72833316ad 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/RustCodegenPlugin.kt @@ -11,6 +11,7 @@ import software.amazon.smithy.codegen.core.ReservedWordSymbolProvider import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.rust.codegen.rustlang.RustReservedWordSymbolProvider +import software.amazon.smithy.rust.codegen.smithy.customizations.ClientCustomizations import software.amazon.smithy.rust.codegen.smithy.customize.CombinedCodegenDecorator import java.util.logging.Level import java.util.logging.Logger @@ -31,7 +32,7 @@ class RustCodegenPlugin : SmithyBuildPlugin { // - location (e.g. the mutate section of an operation) // - context (e.g. the of the operation) // - writer: The active RustWriter at the given location - val codegenDecorator = CombinedCodegenDecorator.fromClasspath(context) + val codegenDecorator = CombinedCodegenDecorator.fromClasspath(context, ClientCustomizations()) // CodegenVisitor is the main driver of code generation that traverses the model and generates code CodegenVisitor(context, codegenDecorator).execute() diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientCustomizations.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientCustomizations.kt new file mode 100644 index 0000000000..d257c82abb --- /dev/null +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientCustomizations.kt @@ -0,0 +1,25 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.rust.codegen.smithy.customizations + +import software.amazon.smithy.rust.codegen.smithy.CodegenContext +import software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator +import software.amazon.smithy.rust.codegen.smithy.generators.LibRsCustomization + +/** + * Customizations that apply only to generated clients + */ +class ClientCustomizations : RustCodegenDecorator { + override val name: String = "ClientCustomizations" + override val order: Byte = 0 + + override fun libRsCustomizations( + codegenContext: CodegenContext, + baseCustomizations: List + ): List { + return baseCustomizations + ClientDocsGenerator() + } +} diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientDocsGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientDocsGenerator.kt new file mode 100644 index 0000000000..dc90a27438 --- /dev/null +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customizations/ClientDocsGenerator.kt @@ -0,0 +1,39 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.rust.codegen.smithy.customizations + +import software.amazon.smithy.rust.codegen.rustlang.Writable +import software.amazon.smithy.rust.codegen.rustlang.containerDocs +import software.amazon.smithy.rust.codegen.rustlang.writable +import software.amazon.smithy.rust.codegen.smithy.generators.LibRsCustomization +import software.amazon.smithy.rust.codegen.smithy.generators.LibRsSection + +class ClientDocsGenerator : LibRsCustomization() { + override fun section(section: LibRsSection): Writable { + return when (section) { + is LibRsSection.ModuleDocumentation -> if (section.subsection == LibRsSection.CrateOrganization) { + crateLayout() + } else emptySection + else -> emptySection + } + } +} + +private fun crateLayout(): Writable = writable { + containerDocs( + """ + The entry point for most customers will be [`Client`]. [`Client`] exposes one method for each API offered + by the service. + + Some APIs require complex or nested arguments. These exist in [`model`]. + + Lastly, errors that can be returned by the service are contained within [`error`]. [`Error`] defines a meta + error encompassing all possible errors that can be returned by the service. + + The other modules within this crate are not required for normal usage. + """.trimEnd() + ) +} diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customize/RustCodegenDecorator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customize/RustCodegenDecorator.kt index 9afba419be..b98d013ebb 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customize/RustCodegenDecorator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/customize/RustCodegenDecorator.kt @@ -147,7 +147,7 @@ open class CombinedCodegenDecorator(decorators: List) : Ru companion object { private val logger = Logger.getLogger("RustCodegenSPILoader") - fun fromClasspath(context: PluginContext): CombinedCodegenDecorator { + fun fromClasspath(context: PluginContext, vararg extras: RustCodegenDecorator): CombinedCodegenDecorator { val decorators = ServiceLoader.load( RustCodegenDecorator::class.java, context.pluginClassLoader.orElse(RustCodegenDecorator::class.java.classLoader) @@ -155,7 +155,7 @@ open class CombinedCodegenDecorator(decorators: List) : Ru .onEach { logger.info("Adding Codegen Decorator: ${it.javaClass.name}") }.toList() - return CombinedCodegenDecorator(decorators + RequiredCustomizations() + FluentClientDecorator()) + return CombinedCodegenDecorator(decorators + RequiredCustomizations() + FluentClientDecorator() + extras) } } } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/LibRsGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/LibRsGenerator.kt index 47f4ed3d9f..6c79a8b741 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/LibRsGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/LibRsGenerator.kt @@ -11,8 +11,8 @@ import software.amazon.smithy.rust.codegen.rustlang.RustModule import software.amazon.smithy.rust.codegen.rustlang.RustWriter import software.amazon.smithy.rust.codegen.rustlang.containerDocs import software.amazon.smithy.rust.codegen.rustlang.escape +import software.amazon.smithy.rust.codegen.rustlang.isEmpty import software.amazon.smithy.rust.codegen.rustlang.rust -import software.amazon.smithy.rust.codegen.rustlang.writable import software.amazon.smithy.rust.codegen.smithy.RustSettings import software.amazon.smithy.rust.codegen.smithy.customize.NamedSectionGenerator import software.amazon.smithy.rust.codegen.smithy.customize.Section @@ -22,6 +22,10 @@ sealed class LibRsSection(name: String) : Section(name) { object Attributes : LibRsSection("Attributes") data class ModuleDocumentation(val subsection: String) : LibRsSection("ModuleDocumentation") object Body : LibRsSection("Body") + companion object { + val Examples = "Examples" + val CrateOrganization = "CrateOrganization" + } } typealias LibRsCustomization = NamedSectionGenerator @@ -43,26 +47,16 @@ class LibRsGenerator( val libraryDocs = settings.getService(model).getTrait()?.value ?: settings.moduleName containerDocs(escape(libraryDocs)) // TODO: replace "service" below with the title trait - containerDocs( - """ - ## Crate Organization - - The entry point for most customers will be [`Client`]. [`Client`] exposes one method for each API offered - by the service. - - Some APIs require complex or nested arguments. These exist in [`model`]. - - Lastly, errors that can be returned by the service are contained within [`error`]. [`Error`] defines a meta - error encompassing all possible errors that can be returned by the service. - - The other modules within this crate and not required for normal usage. - """ - ) + val crateLayout = customizations.map { it.section(LibRsSection.ModuleDocumentation(LibRsSection.CrateOrganization)) }.filter { !it.isEmpty() } + if (crateLayout.isNotEmpty()) { + containerDocs("\n## Crate Organization") + crateLayout.forEach { it(this) } + } - val examples = customizations.map { it.section(LibRsSection.ModuleDocumentation("Examples")) } - .filter { it != writable { } } + val examples = customizations.map { it.section(LibRsSection.ModuleDocumentation(LibRsSection.Examples)) } + .filter { section -> !section.isEmpty() } if (examples.isNotEmpty() || settings.examplesUri != null) { - containerDocs("## Examples") + containerDocs("\n## Examples") examples.forEach { it(this) } // TODO: Render a basic example for all crates (eg. select first operation and render an example of usage) diff --git a/codegen/src/test/kotlin/software/amazon/smithy/rust/lang/RustWriterTest.kt b/codegen/src/test/kotlin/software/amazon/smithy/rust/lang/RustWriterTest.kt index 758204c9a5..1091718003 100644 --- a/codegen/src/test/kotlin/software/amazon/smithy/rust/lang/RustWriterTest.kt +++ b/codegen/src/test/kotlin/software/amazon/smithy/rust/lang/RustWriterTest.kt @@ -6,6 +6,7 @@ package software.amazon.smithy.rust.lang import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldContainOnlyOnce import org.junit.jupiter.api.Test @@ -18,7 +19,9 @@ import software.amazon.smithy.rust.codegen.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.rustlang.RustType import software.amazon.smithy.rust.codegen.rustlang.RustWriter import software.amazon.smithy.rust.codegen.rustlang.docs +import software.amazon.smithy.rust.codegen.rustlang.isEmpty import software.amazon.smithy.rust.codegen.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.rustlang.writable import software.amazon.smithy.rust.codegen.smithy.RuntimeType import software.amazon.smithy.rust.codegen.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.testutil.compileAndRun @@ -102,4 +105,10 @@ class RustWriterTest { sut.docs("A link! #D", symbol) sut.toString() shouldContain "/// A link! [`Foo`](crate::model::Foo)" } + + @Test + fun `empty writable`() { + val w = writable {} + w.isEmpty() shouldBe true + } }