Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify Plugin trait #2740

Merged
merged 15 commits into from
Jun 12, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.module
import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait
import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait
import software.amazon.smithy.rust.codegen.core.util.hasTrait
import software.amazon.smithy.rust.codegen.core.util.toPascalCase
import software.amazon.smithy.rust.codegen.core.util.toSnakeCase
import software.amazon.smithy.rust.codegen.server.smithy.generators.DocHandlerGenerator
import software.amazon.smithy.rust.codegen.server.smithy.generators.handlerImports
Expand Down Expand Up @@ -73,49 +72,22 @@ class ServerModuleDocProvider(private val codegenContext: ServerCodegenContext)
val operations = index.getContainedOperations(codegenContext.serviceShape).toSortedSet(compareBy { it.id })

val firstOperation = operations.first() ?: return@writable
val firstOperationSymbol = codegenContext.symbolProvider.toSymbol(firstOperation)
val firstOperationName = firstOperationSymbol.name.toPascalCase()
val crateName = codegenContext.settings.moduleName.toSnakeCase()

rustTemplate(
"""
/// A collection of types representing each operation defined in the service closure.
///
/// ## Constructing an [`Operation`](#{SmithyHttpServer}::operation::OperationShapeExt)
///
/// To apply middleware to specific operations the [`Operation`](#{SmithyHttpServer}::operation::Operation)
/// API must be used.
///
/// Using the [`OperationShapeExt`](#{SmithyHttpServer}::operation::OperationShapeExt) trait
/// implemented on each ZST we can construct an [`Operation`](#{SmithyHttpServer}::operation::Operation)
/// with appropriate constraints given by Smithy.
///
/// #### Example
///
/// ```no_run
/// use $crateName::operation_shape::$firstOperationName;
/// use #{SmithyHttpServer}::operation::OperationShapeExt;
///
#{HandlerImports:W}
///
#{Handler:W}
///
/// let operation = $firstOperationName::from_handler(handler)
/// .layer(todo!("Provide a layer implementation"));
/// ```
///
/// ## Use as Marker Structs
///
/// The [plugin system](#{SmithyHttpServer}::plugin) also makes use of these
/// The [plugin system](#{SmithyHttpServer}::plugin) makes use of these
/// [zero-sized types](https://doc.rust-lang.org/nomicon/exotic-sizes.html##zero-sized-types-zsts) (ZSTs) to
/// parameterize [`Plugin`](#{SmithyHttpServer}::plugin::Plugin) implementations. The traits, such as
/// [`OperationShape`](#{SmithyHttpServer}::operation::OperationShape) can be used to provide
/// parameterize [`Plugin`](#{SmithyHttpServer}::plugin::Plugin) implementations. Their traits, such as
/// [`OperationShape`](#{SmithyHttpServer}::operation::OperationShape), can be used to provide
/// operation specific information to the [`Layer`](#{Tower}::Layer) being applied.
""".trimIndent(),
"SmithyHttpServer" to
ServerCargoDependency.smithyHttpServer(codegenContext.runtimeConfig).toType(),
"Tower" to ServerCargoDependency.Tower.toType(),
"Handler" to DocHandlerGenerator(codegenContext, firstOperation, "handler", commentToken = "///")::render,
"Handler" to DocHandlerGenerator(codegenContext, firstOperation, "handler", commentToken = "///").docSignature(),
"HandlerImports" to handlerImports(crateName, operations, commentToken = "///"),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
package software.amazon.smithy.rust.codegen.server.smithy.generators

import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext
import software.amazon.smithy.rust.codegen.core.util.inputShape
Expand Down Expand Up @@ -55,14 +53,21 @@ class DocHandlerGenerator(
}
}

fun render(writer: RustWriter) {
// This assumes that the `error` (if applicable) `input`, and `output` modules have been imported by the
// caller and hence are in scope.
writer.rustTemplate(
"""
#{Handler:W}
""",
"Handler" to docSignature(),
)
fun docFixedSignature(): Writable {
hlbarber marked this conversation as resolved.
Show resolved Hide resolved
val outputT = if (operation.errors.isEmpty()) {
"Result<${OutputModule.name}::${outputSymbol.name}, std::convert::Infallible>"
} else {
"Result<${OutputModule.name}::${outputSymbol.name}, ${ErrorModule.name}::${errorSymbol.name}>"
}

return writable {
rust(
"""
$commentToken async fn $handlerName(input: ${InputModule.name}::${inputSymbol.name}) -> $outputT {
$commentToken todo!()
$commentToken }
""".trimIndent(),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ open class ServerRootGenerator(
val hasErrors = operations.any { it.errors.isNotEmpty() }
val handlers: Writable = operations
.map { operation ->
DocHandlerGenerator(codegenContext, operation, builderFieldNames[operation]!!, "//!")::render
DocHandlerGenerator(codegenContext, operation, builderFieldNames[operation]!!, "//!").docSignature()
}
.join("//!\n")

Expand Down Expand Up @@ -110,6 +110,7 @@ open class ServerRootGenerator(
//! Plugins allow you to build middleware which is aware of the operation it is being applied to.
//!
//! ```rust
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin;
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin as LoggingPlugin;
//! ## use #{SmithyHttpServer}::plugin::IdentityPlugin as MetricsPlugin;
//! ## use #{Hyper}::Body;
Expand All @@ -119,7 +120,7 @@ open class ServerRootGenerator(
//! let plugins = PluginPipeline::new()
//! .push(LoggingPlugin)
//! .push(MetricsPlugin);
//! let builder: $builderName<Body, _> = $serviceName::builder_with_plugins(plugins);
//! let builder: $builderName<Body, _, _> = $serviceName::builder_with_plugins(plugins, IdentityPlugin);
//! ```
//!
//! Check out [`#{SmithyHttpServer}::plugin`] to learn more about plugins.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class ServerRuntimeTypesReExportsGenerator(
}
pub mod operation {
pub use #{SmithyHttpServer}::operation::OperationShape;
pub use #{SmithyHttpServer}::operation::Operation;
}
pub mod plugin {
pub use #{SmithyHttpServer}::plugin::Plugin;
Expand Down
Loading