Unverified Commit 40245a15 authored by david-perez's avatar david-perez Committed by GitHub
Browse files

Improve RustDocs for constrained types (#2095)

* We decided not to generate `parse` method in #1342.
* Fix link to `try_from` constructor.
* Always mention the type is the result of a constrained shape, even if
  the shape has no documentation.
parent 30c6828d
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -77,13 +77,21 @@ class ConstraintViolationSymbolProvider(
        false -> Visibility.PUBCRATE
    }

    private fun Shape.shapeModule() = RustModule.new(
        // need to use the context name so we get the correct name for maps
    private fun Shape.shapeModule(): RustModule.LeafModule {
        val documentation = if (publicConstrainedTypes && this.isDirectlyConstrained(base)) {
            "See [`${this.contextName(serviceShape)}`]."
        } else {
            null
        }
        return RustModule.new(
            // Need to use the context name so we get the correct name for maps.
            name = RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase(),
            visibility = visibility,
            parent = ModelsModule,
            inline = true,
            documentation = documentation,
        )
    }

    private fun constraintViolationSymbolForCollectionOrMapOrUnionShape(shape: Shape): Symbol {
        check(shape is CollectionShape || shape is MapShape || shape is UnionShape)
+2 −1
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ class ConstrainedCollectionGenerator(
            "ConstraintViolation" to constraintViolation,
        )

        writer.documentShape(shape, model, note = rustDocsNote(name))
        writer.documentShape(shape, model)
        writer.docs(rustDocsConstrainedTypeEpilogue(name))
        constrainedTypeMetadata.render(writer)
        writer.rustTemplate(
            """
+3 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Attribute
import software.amazon.smithy.rust.codegen.core.rustlang.RustMetadata
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Visibility
import software.amazon.smithy.rust.codegen.core.rustlang.docs
import software.amazon.smithy.rust.codegen.core.rustlang.documentShape
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
@@ -74,7 +75,8 @@ class ConstrainedMapGenerator(
            "ConstraintViolation" to constraintViolation,
        )

        writer.documentShape(shape, model, note = rustDocsNote(name))
        writer.documentShape(shape, model)
        writer.docs(rustDocsConstrainedTypeEpilogue(name))
        constrainedTypeMetadata.render(writer)
        writer.rustTemplate("struct $name(pub(crate) $inner);", *codegenScope)
        if (constrainedTypeVisibility == Visibility.PUBCRATE) {
+10 −9
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ class ConstrainedNumberGenerator(
        val rangeTrait = shape.expectTrait<RangeTrait>()

        val symbol = constrainedShapeSymbolProvider.toSymbol(shape)
        val constrainedTypeName = symbol.name
        val name = symbol.name
        val unconstrainedTypeName = unconstrainedType.render()
        val constraintViolation = constraintViolationSymbolProvider.toSymbol(shape)
        val constraintsInfo = listOf(Range(rangeTrait).toTraitInfo(unconstrainedTypeName))
@@ -94,16 +94,17 @@ class ConstrainedNumberGenerator(
            visibility = constrainedTypeVisibility,
        )

        writer.documentShape(shape, model, note = rustDocsNote(constrainedTypeName))
        writer.documentShape(shape, model)
        writer.docs(rustDocsConstrainedTypeEpilogue(name))
        constrainedTypeMetadata.render(writer)
        writer.rust("struct $constrainedTypeName(pub(crate) $unconstrainedTypeName);")
        writer.rust("struct $name(pub(crate) $unconstrainedTypeName);")

        if (constrainedTypeVisibility == Visibility.PUBCRATE) {
            Attribute.AllowUnused.render(writer)
        }
        writer.rustTemplate(
            """
            impl $constrainedTypeName {
            impl $name {
                /// ${rustDocsInnerMethod(unconstrainedTypeName)}
                pub fn inner(&self) -> &$unconstrainedTypeName {
                    &self.0
@@ -115,7 +116,7 @@ class ConstrainedNumberGenerator(
                }
            }

            impl #{ConstrainedTrait} for $constrainedTypeName  {
            impl #{ConstrainedTrait} for $name  {
                type Unconstrained = $unconstrainedTypeName;
            }

@@ -125,14 +126,14 @@ class ConstrainedNumberGenerator(
                }
            }

            impl #{Display} for $constrainedTypeName {
            impl #{Display} for $name {
                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                   ${shape.redactIfNecessary(model, "self.0")}.fmt(f)
                }
            }

            impl #{From}<$constrainedTypeName> for $unconstrainedTypeName {
                fn from(value: $constrainedTypeName) -> Self {
            impl #{From}<$name> for $unconstrainedTypeName {
                fn from(value: $name) -> Self {
                    value.into_inner()
                }
            }
@@ -146,7 +147,7 @@ class ConstrainedNumberGenerator(
            "AsRef" to RuntimeType.AsRef,
        )

        writer.renderTryFrom(unconstrainedTypeName, constrainedTypeName, constraintViolation, constraintsInfo)
        writer.renderTryFrom(unconstrainedTypeName, name, constraintViolation, constraintsInfo)

        writer.withInlineModule(constraintViolation.module()) {
            rust(
+6 −4
Original line number Diff line number Diff line
@@ -9,10 +9,12 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators
 * Functions shared amongst the constrained shape generators, to keep them DRY and consistent.
 */

fun rustDocsNote(typeName: String) =
    "this is a constrained type because its corresponding modeled Smithy shape has one or more " +
        "[constraint traits]. Use [`parse`] or [`$typeName::TryFrom`] to construct values of this type." +
        "[constraint traits]: https://awslabs.github.io/smithy/1.0/spec/core/constraint-traits.html"
fun rustDocsConstrainedTypeEpilogue(typeName: String) = """
This is a constrained type because its corresponding modeled Smithy shape has one or more 
[constraint traits]. Use [`$typeName::try_from`] to construct values of this type.

[constraint traits]: https://awslabs.github.io/smithy/1.0/spec/core/constraint-traits.html
"""

fun rustDocsTryFromMethod(typeName: String, inner: String) =
    "Constructs a `$typeName` from an [`$inner`], failing when the provided value does not satisfy the modeled constraints."
Loading