Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import software.amazon.smithy.kotlin.codegen.model.getTrait
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.traits.TitleTrait
import java.io.IOException
import java.io.File

/**
* Maps a service's SDK ID to its code examples
Expand Down Expand Up @@ -38,17 +38,9 @@ private val CODE_EXAMPLES_SERVICES_MAP = mapOf(
"Rekognition" to "https://docs.aws.amazon.com/code-library/latest/ug/kotlin_1_rekognition_code_examples.html",
)

/**
* Maps a service's SDK ID to its handwritten module documentation file in the `resources` dir.
* The module documentation files MUST be markdown files.
*/
private val HAND_WRITTEN_SERVICES_MAP = mapOf(
"S3" to "S3.md",
)

/**
* Generates an `API.md` file that will be used as module documentation in our API ref docs.
* Some services have code examples we need to link to. Others have handwritten documentation.
* Some services have code example documentation we need to generate. Others have handwritten documentation.
* The integration renders both into the `API.md` file.
*
* See: https://kotlinlang.org/docs/dokka-module-and-package-docs.html
Expand All @@ -57,41 +49,45 @@ private val HAND_WRITTEN_SERVICES_MAP = mapOf(
*/
class ModuleDocumentationIntegration(
private val codeExamples: Map<String, String> = CODE_EXAMPLES_SERVICES_MAP,
private val handWritten: Map<String, String> = HAND_WRITTEN_SERVICES_MAP,
) : KotlinIntegration {
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean =
model.expectShape<ServiceShape>(settings.service).sdkId.let {
codeExamples.keys.contains(it) || handWritten.keys.contains(it)
}
codeExamples.keys.contains(
model
.expectShape<ServiceShape>(settings.service)
.sdkId,
) ||
handWrittenDocsFile(settings).exists()

override fun writeAdditionalFiles(ctx: CodegenContext, delegator: KotlinDelegator) {
delegator.fileManifest.writeFile(
"API.md",
generateModuleDocumentation(ctx, ctx.settings.sdkId),
generateModuleDocumentation(ctx),
)
}

internal fun generateModuleDocumentation(
ctx: CodegenContext,
sdkId: String,
) = buildString {
append(
generateBoilerPlate(ctx),
)
if (handWritten.keys.contains(sdkId)) {
val handWrittenDocsFile = handWrittenDocsFile(ctx.settings)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming: the function and the value have the same name, handWrittenDocsFile, which can be hard to read. Consider renaming function to getHandWrittenDocsFile

Also nit/style: you can check if the file exists inside getHandWrittenDocsFile and return null if it doesn't.

That would simplify this code section to just: getHandWrittenDocsFile(ctx)?.let { append(it.readText()) }

if (handWrittenDocsFile.exists()) {
append(
generateHandWrittenDocs(sdkId),
handWrittenDocsFile.readText(),
)
appendLine()
}
if (codeExamples.keys.contains(sdkId)) {
if (codeExamples.keys.contains(ctx.settings.sdkId)) {
if (!handWrittenDocsFile.exists()) {
append(
boilerPlate(ctx),
)
}
append(
generateCodeExamplesDocs(ctx),
codeExamplesDocs(ctx),
)
}
}

private fun generateBoilerPlate(ctx: CodegenContext) = buildString {
private fun boilerPlate(ctx: CodegenContext) = buildString {
// Title must be "Module" followed by the exact module name or dokka won't render it
appendLine("# Module ${ctx.settings.pkg.name.split(".").last()}")
appendLine()
Expand All @@ -106,7 +102,7 @@ class ModuleDocumentationIntegration(
}
}

private fun generateCodeExamplesDocs(ctx: CodegenContext) = buildString {
private fun codeExamplesDocs(ctx: CodegenContext) = buildString {
val sdkId = ctx.settings.sdkId
val codeExampleLink = codeExamples[sdkId]
val title = ctx
Expand All @@ -120,12 +116,11 @@ class ModuleDocumentationIntegration(
appendLine("See $codeExampleLink")
appendLine()
}
}

private fun handWrittenDocsFile(settings: KotlinSettings): File {
val sdkRootDir = System.getProperty("user.dir")
val serviceDir = "$sdkRootDir/services/${settings.pkg.name.split(".").last()}"

private fun generateHandWrittenDocs(sdkId: String): String = object {}
.javaClass
.classLoader
.getResourceAsStream("aws/sdk/kotlin/codegen/moduledocumentation/${handWritten[sdkId]}")
?.bufferedReader()
?.readText()
?: throw IOException("Unable to read from file ${handWritten[sdkId]}")
return File("$serviceDir/DOCS.md")
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,14 @@ class ModuleDocumentationIntegrationTest {
codeExamples = mapOf("Test" to "https://example.com"),
).enabledForService(model, ctx.generationCtx.settings),
)
assertTrue(
ModuleDocumentationIntegration(
handWritten = mapOf("Test" to "example.md"),
).enabledForService(model, ctx.generationCtx.settings),
)
assertTrue(
ModuleDocumentationIntegration(
codeExamples = mapOf("Test" to "https://example.com"),
handWritten = mapOf("Test" to "test.md"),
).enabledForService(model, ctx.generationCtx.settings),
)
}

@Test
fun rendersBoilerplate() =
ModuleDocumentationIntegration()
.generateModuleDocumentation(
ctx.toGenerationContext(),
"Test",
)
ModuleDocumentationIntegration(
codeExamples = mapOf("Test" to "https://example.com"),
)
.generateModuleDocumentation(ctx.toGenerationContext())
.shouldContainOnlyOnceWithDiff(
"""
# Module test
Expand All @@ -69,31 +57,11 @@ class ModuleDocumentationIntegrationTest {
ModuleDocumentationIntegration(
codeExamples = mapOf("Test" to "https://example.com"),
)
.generateModuleDocumentation(
ctx.toGenerationContext(),
"Test",
)
.generateModuleDocumentation(ctx.toGenerationContext())
.shouldContainOnlyOnceWithDiff(
"""
## Code Examples
To see full code examples, see the Test Service examples in the AWS code example library. See https://example.com
""".trimIndent(),
)

@Test
fun rendersHandWrittenDocs() =
ModuleDocumentationIntegration(
handWritten = mapOf("Test" to "test.md"),
)
.generateModuleDocumentation(
ctx.toGenerationContext(),
"Test",
).replace("\r\n", "\n") // Handle CRLF on Windows
.shouldContainOnlyOnceWithDiff(
"""
## Subtitle

Lorem Ipsum
""".trimIndent(),
)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Module s3

Amazon Simple Storage Service

## Binary Data

Binary data (streams) are represented as an [aws.smithy.kotlin.runtime.content.ByteStream].
Expand Down Expand Up @@ -54,4 +58,4 @@ println("wrote $contentSize bytes to $path")
```


This scoped response simplifies lifetime management for both the caller and the runtime.
This scoped response simplifies lifetime management for both the caller and the runtime.
Loading