diff --git a/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinWriter.kt b/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinWriter.kt index 977426e39..e8bd1ea64 100644 --- a/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinWriter.kt +++ b/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinWriter.kt @@ -295,7 +295,7 @@ private val commonHtmlTags = setOf( // NOTE: Currently we look for specific strings of Html tags commonly found in docs // and remove them. A better solution would be to generally convert from HTML to "pure" // markdown such that formatting is preserved. -// TODO: https://www.pivotaltracker.com/story/show/177053427 +// TODO: https://github.com/awslabs/smithy-kotlin/issues/136 private fun sanitizeDocumentation(doc: String): String = doc .stripAll(commonHtmlTags) // Docs can have valid $ characters that shouldn't run through formatters. diff --git a/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessor.kt b/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessor.kt new file mode 100644 index 000000000..295932ffb --- /dev/null +++ b/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessor.kt @@ -0,0 +1,37 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.kotlin.codegen.lang + +import software.amazon.smithy.kotlin.codegen.KotlinSettings +import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.traits.DocumentationTrait +import software.amazon.smithy.model.transform.ModelTransformer + +/** + * Sanitize all instances of [DocumentationTrait] + */ +class DocumentationPreprocessor : KotlinIntegration { + + override fun preprocessModel(model: Model, settings: KotlinSettings): Model { + val transformer = ModelTransformer.create() + return transformer.mapTraits(model) { _, trait -> + when (trait) { + is DocumentationTrait -> { + val docs = sanitize(trait.value) + DocumentationTrait(docs, trait.sourceLocation) + } + else -> trait + } + } + } + + // KDoc comments use inline markdown. Replace square brackets with escaped equivalents so that they + // are not rendered as invalid links + private fun sanitize(str: String): String = + str.replace("[", "[") + .replace("]", "]") +} diff --git a/smithy-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration b/smithy-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration index 01d560c86..427dd7e30 100644 --- a/smithy-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration +++ b/smithy-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration @@ -1 +1,2 @@ software.amazon.smithy.kotlin.codegen.lang.BuiltinPreprocessor +software.amazon.smithy.kotlin.codegen.lang.DocumentationPreprocessor diff --git a/smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessorTest.kt b/smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessorTest.kt new file mode 100644 index 000000000..e5b5c8874 --- /dev/null +++ b/smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/lang/DocumentationPreprocessorTest.kt @@ -0,0 +1,71 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.kotlin.codegen.lang + +import org.junit.jupiter.api.Test +import software.amazon.smithy.kotlin.codegen.KotlinSettings +import software.amazon.smithy.kotlin.codegen.model.expectTrait +import software.amazon.smithy.kotlin.codegen.test.toSmithyModel +import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.model.traits.DocumentationTrait +import kotlin.test.assertEquals + +class DocumentationPreprocessorTest { + @Test + fun itEscapesSquareBrackets() { + // https://github.com/awslabs/aws-sdk-kotlin/issues/153 + val model = """ + namespace com.test + + service FooService { + version: "1.0.0" + } + + @documentation("This should not be modified") + structure Foo { + @documentation("member docs") + Unit: Unit, + Str: String + } + + @documentation("UserName@[SubDomain.]Domain.TopLevelDomain") + structure Unit { + Int: Integer + } + + union MyUnion { + @documentation("foo [bar [baz] qux] quux") + Integer: Integer, + String: String, + Unit: Unit + } + """.toSmithyModel() + + val settings = KotlinSettings( + ShapeId.from("com.test#FooService"), + KotlinSettings.PackageSettings( + "test", + "1.0", + "" + ), + "Foo" + ) + + val integration = DocumentationPreprocessor() + val modified = integration.preprocessModel(model, settings) + val expectedDocs = listOf( + "com.test#Foo" to "This should not be modified", + "com.test#Foo\$Unit" to "member docs", + "com.test#Unit" to "UserName@[SubDomain.]Domain.TopLevelDomain", + "com.test#MyUnion\$Integer" to "foo [bar [baz] qux] quux", + ) + expectedDocs.forEach { (shapeId, expected) -> + val shape = modified.expectShape(ShapeId.from(shapeId)) + val docs = shape.expectTrait().value + assertEquals(expected, docs) + } + } +}