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

Basic support of @deprecated trait in Smithy model #1570

Merged
merged 20 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6804312
Add helper for creating deprecated attribute
weihanglo Jul 25, 2022
b1f5bc5
Test `@deprecated` trait for RustWriter
weihanglo Jul 25, 2022
e5f2357
Support `@deprecated` trait for StructureGenerator
weihanglo Jul 25, 2022
33831a8
Support `@deprecated` trait for UnionGenerator
weihanglo Jul 25, 2022
1d0fe8d
Support `@deprecated` trait for EnumGenerator
weihanglo Jul 25, 2022
43cfd8f
Support `@deprecated` trait for TopLevelErrorGenerator
weihanglo Jul 25, 2022
399bdda
Support `@deprecated` trait for CombinedErrorGenerator
weihanglo Jul 25, 2022
0582908
Support `@deprecated` trait for ServerCombinedErrorGenerator
weihanglo Jul 25, 2022
77ab717
Support `@deprecated` trait for FluentClient
weihanglo Jul 25, 2022
c051519
Support `@deprecated` trait for BuilderGenerator
weihanglo Jul 25, 2022
fe8749c
Cleanup leftover in test
weihanglo Jul 26, 2022
1899b55
Use `dq()` helper method instead of escaping by hands
weihanglo Jul 26, 2022
774ee15
Leverage Kotlin null safety well
weihanglo Jul 26, 2022
6ab77ed
Allow `deprecated` rustc lint rule
weihanglo Jul 26, 2022
f8e6644
Allow deprecated in unit tests
weihanglo Jul 26, 2022
b8161d4
Leverage kotlin null safety check again
weihanglo Jul 26, 2022
3006aac
changelog: Support @deprecated trait
weihanglo Jul 26, 2022
c42dfe7
Merge branch 'main' into weihanglo-issue-356
weihanglo Jul 27, 2022
8a7545c
Merge branch 'main' into weihanglo-issue-356
crisidev Jul 27, 2022
b5db8ea
Merge branch 'main' into weihanglo-issue-356
weihanglo Jul 28, 2022
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
6 changes: 6 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,9 @@ Add explicit cast during JSON deserialization in case of custom Symbol providers
references = ["smithy-rs#1520"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "crisidev"

[[smithy-rs]]
message = "Support @deprecated trait for aggregate shapes"
references = ["smithy-rs#1570"]
meta = { "breaking" = true, "tada" = true, "bug" = false }
author = "weihanglo"
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ServerCombinedErrorGeneratorTest {
namespace error

operation Greeting {
errors: [InvalidGreeting, ComplexError, FooException]
errors: [InvalidGreeting, ComplexError, FooException, Deprecated]
}

@error("client")
Expand All @@ -42,6 +42,10 @@ class ServerCombinedErrorGeneratorTest {
abc: String,
other: Integer
}

@error("server")
@deprecated
structure Deprecated { }
""".asSmithyModel()
private val model = OperationNormalizer.transform(baseModel)
private val symbolProvider = serverTestSymbolProvider(model)
Expand All @@ -50,7 +54,7 @@ class ServerCombinedErrorGeneratorTest {
fun `generates combined error enums`() {
val project = TestWorkspace.testProject(symbolProvider)
project.withModule(RustModule.public("error")) { writer ->
listOf("FooException", "ComplexError", "InvalidGreeting").forEach {
listOf("FooException", "ComplexError", "InvalidGreeting", "Deprecated").forEach {
model.lookup<StructureShape>("error#$it").renderWithModelBuilder(model, symbolProvider, writer, CodegenTarget.SERVER)
}
val errors = listOf("FooException", "ComplexError", "InvalidGreeting").map { model.lookup<StructureShape>("error#$it") }
Expand All @@ -76,7 +80,10 @@ class ServerCombinedErrorGeneratorTest {

// Indicate the original name in the display output.
let error = FooException::builder().build();
assert_eq!(format!("{}", error), "FooException")
assert_eq!(format!("{}", error), "FooException");

let error = Deprecated::builder().build();
assert_eq!(error.to_string(), "Deprecated");
"""
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,29 @@ sealed class Attribute {
writer.addDependency(it.dependency)
}
}

companion object {
/**
* Renders a
* [`#[deprecated]`](https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute)
* attribute.
*/
fun deprecated(note: String? = null, since: String? = null): Custom {
val builder = StringBuilder()
builder.append("deprecated")

if (note != null && since != null) {
builder.append("(note = ${note.dq()}, since = ${since.dq()})")
} else if (note != null) {
builder.append("(note = ${note.dq()})")
} else if (since != null) {
builder.append("(since = ${since.dq()})")
} else {
// No-op. Rustc would emit a default message.
}
return Custom(builder.toString())
}
}
}

data class Cfg(val cond: String) : Attribute() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import software.amazon.smithy.model.shapes.CollectionShape
import software.amazon.smithy.model.shapes.NumberShape
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.DeprecatedTrait
import software.amazon.smithy.model.traits.DocumentationTrait
import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.isOptional
import software.amazon.smithy.rust.codegen.smithy.rustType
import software.amazon.smithy.rust.codegen.util.getTrait
import software.amazon.smithy.rust.codegen.util.orNull
import software.amazon.smithy.utils.AbstractCodeWriter
import java.io.File
Expand Down Expand Up @@ -269,6 +271,20 @@ fun <T : AbstractCodeWriter<T>> T.docs(text: String, vararg args: Any, newlinePr
return this
}

/**
* Generates a `#[deprecated]` attribute for [shape].
*/
fun RustWriter.deprecatedShape(shape: Shape): RustWriter {
val deprecatedTrait = shape.getTrait<DeprecatedTrait>() ?: return this

val note = deprecatedTrait.message.orNull()
val since = deprecatedTrait.since.orNull()

Attribute.Custom.deprecated(note, since).render(this)

return this
}

/** Escape the [expressionStart] character to avoid problems during formatting */
fun <T : AbstractCodeWriter<T>> T.escape(text: String): String =
text.replace("$expressionStart", "$expressionStart$expressionStart")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ 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

val ClippyAllowLints = listOf(
val AllowedRustcLints = listOf(
// Deprecated items should be safe to compile, so don't block the compilation.
"deprecated",
)

val AllowedClippyLints = listOf(
// Sometimes operations are named the same as our module e.g. output leading to `output::output`.
"module_inception",

Expand All @@ -36,26 +41,26 @@ val ClippyAllowLints = listOf(
"type_complexity",
)

val AllowDocsLints = listOf(
val AllowedRustdocLints = listOf(
// Rust >=1.53.0 requires links to be wrapped in `<link>`. This is extremely hard to enforce for
// docs that come from the modeled documentation, so we need to disable this lint
"bare_urls"
)

class AllowLintsGenerator(
private val bareLints: List<String> = listOf(),
private val clippyLints: List<String> = ClippyAllowLints,
private val docsLints: List<String> = AllowDocsLints
private val rustcLints: List<String> = AllowedRustcLints,
private val clippyLints: List<String> = AllowedClippyLints,
private val rustdocLints: List<String> = AllowedRustdocLints,
) : LibRsCustomization() {
override fun section(section: LibRsSection) = when (section) {
is LibRsSection.Attributes -> writable {
bareLints.forEach {
rustcLints.forEach {
Attribute.Custom("allow($it)", container = true).render(this)
}
clippyLints.forEach {
Attribute.Custom("allow(clippy::$it)", container = true).render(this)
}
docsLints.forEach {
rustdocLints.forEach {
Attribute.Custom("allow(rustdoc::$it)", container = true).render(this)
}
// add a newline at the end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asArgument
import software.amazon.smithy.rust.codegen.rustlang.asOptional
import software.amazon.smithy.rust.codegen.rustlang.conditionalBlock
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.docs
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.render
Expand Down Expand Up @@ -124,6 +125,7 @@ class BuilderGenerator(
val input = coreType.asArgument("input")

writer.documentShape(member, model)
writer.deprecatedShape(member)
writer.rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") {
write("self.$memberName = Some(${input.value});")
write("self")
Expand All @@ -146,6 +148,7 @@ class BuilderGenerator(
val inputType = outerType.asOptional()

writer.documentShape(member, model)
writer.deprecatedShape(member)
writer.rustBlock("pub fn ${member.setterName()}(mut self, input: ${inputType.render(true)}) -> Self") {
rust("self.$memberName = input; self")
}
Expand Down Expand Up @@ -195,6 +198,7 @@ class BuilderGenerator(
docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).")
rust("///")
documentShape(member, model, autoSuppressMissingDocs = false)
deprecatedShape(member)
val input = coreType.member.asArgument("input")

rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") {
Expand All @@ -215,6 +219,7 @@ class BuilderGenerator(
docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).")
rust("///")
documentShape(member, model, autoSuppressMissingDocs = false)
deprecatedShape(member)
val k = coreType.key.asArgument("k")
val v = coreType.member.asArgument("v")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import software.amazon.smithy.model.traits.DocumentationTrait
import software.amazon.smithy.model.traits.EnumDefinition
import software.amazon.smithy.model.traits.EnumTrait
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.docs
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.escape
Expand Down Expand Up @@ -47,10 +48,17 @@ class EnumMemberModel(private val definition: EnumDefinition, private val symbol
)
}

private fun renderDeprecated(writer: RustWriter) {
if (definition.isDeprecated) {
writer.rust("##[deprecated]")
}
}

fun derivedName() = checkNotNull(symbolProvider.toEnumVariantName(definition)).name

fun render(writer: RustWriter) {
renderDocumentation(writer)
renderDeprecated(writer)
writer.write("${derivedName()},")
}
}
Expand Down Expand Up @@ -116,6 +124,7 @@ open class EnumGenerator(

private fun renderUnnamedEnum() {
writer.documentShape(shape, model)
writer.deprecatedShape(shape)
meta.render(writer)
writer.write("struct $enumName(String);")
writer.rustBlock("impl $enumName") {
Expand Down Expand Up @@ -150,6 +159,7 @@ open class EnumGenerator(
shape.getTrait<DocumentationTrait>()?.value,
renamedWarning.ifBlank { null }
)
writer.deprecatedShape(shape)

meta.render(writer)
writer.rustBlock("enum $enumName") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asDeref
import software.amazon.smithy.rust.codegen.rustlang.asRef
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.isCopy
import software.amazon.smithy.rust.codegen.rustlang.isDeref
Expand Down Expand Up @@ -133,6 +134,7 @@ open class StructureGenerator(
// Render field accessor methods
forEachMember(accessorMembers) { member, memberName, memberSymbol ->
renderMemberDoc(member, memberSymbol)
writer.deprecatedShape(member)
val memberType = memberSymbol.rustType()
val returnType = when {
memberType.isCopy() -> memberType
Expand All @@ -155,6 +157,7 @@ open class StructureGenerator(

open fun renderStructureMember(writer: RustWriter, member: MemberShape, memberName: String, memberSymbol: Symbol) {
writer.renderMemberDoc(member, memberSymbol)
writer.deprecatedShape(member)
memberSymbol.expectRustMetadata().render(writer)
writer.write("$memberName: #T,", symbolProvider.toSymbol(member))
}
Expand All @@ -163,6 +166,7 @@ open class StructureGenerator(
val symbol = symbolProvider.toSymbol(shape)
val containerMeta = symbol.expectRustMetadata()
writer.documentShape(shape, model)
writer.deprecatedShape(shape)
val withoutDebug = containerMeta.derives.copy(derives = containerMeta.derives.derives - RuntimeType.Debug)
containerMeta.copy(derives = withoutDebug).render(writer)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.UnionShape
import software.amazon.smithy.rust.codegen.rustlang.Attribute
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.docs
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.rust
Expand Down Expand Up @@ -52,6 +53,7 @@ class UnionGenerator(

private fun renderUnion() {
writer.documentShape(shape, model)
writer.deprecatedShape(shape)

val unionSymbol = symbolProvider.toSymbol(shape)
val containerMeta = unionSymbol.expectRustMetadata()
Expand All @@ -62,6 +64,7 @@ class UnionGenerator(
val note =
memberSymbol.renamedFrom()?.let { oldName -> "This variant has been renamed from `$oldName`." }
documentShape(member, model, note = note)
deprecatedShape(member)
memberSymbol.expectRustMetadata().renderAttributes(this)
write("${symbolProvider.toMemberName(member)}(#T),", symbolProvider.toSymbol(member))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asArgument
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.docs
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.rust
Expand All @@ -26,6 +27,7 @@ class FluentClientCore(private val model: Model) {
val input = coreType.member.asArgument("input")

documentShape(member, model)
deprecatedShape(member)
rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") {
write("self.inner = self.inner.$memberName(${input.value});")
write("self")
Expand All @@ -42,6 +44,7 @@ class FluentClientCore(private val model: Model) {
val v = coreType.member.asArgument("v")

documentShape(member, model)
deprecatedShape(member)
rustBlock("pub fn $memberName(mut self, ${k.argument}, ${v.argument}) -> Self") {
write("self.inner = self.inner.$memberName(${k.value}, ${v.value});")
write("self")
Expand All @@ -58,6 +61,7 @@ class FluentClientCore(private val model: Model) {
val functionInput = coreType.asArgument("input")

documentShape(member, model)
deprecatedShape(member)
rustBlock("pub fn $memberName(mut self, ${functionInput.argument}) -> Self") {
write("self.inner = self.inner.$memberName(${functionInput.value});")
write("self")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import software.amazon.smithy.rust.codegen.rustlang.Writable
import software.amazon.smithy.rust.codegen.rustlang.asArgumentType
import software.amazon.smithy.rust.codegen.rustlang.asOptional
import software.amazon.smithy.rust.codegen.rustlang.asType
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.docLink
import software.amazon.smithy.rust.codegen.rustlang.docs
import software.amazon.smithy.rust.codegen.rustlang.documentShape
Expand Down Expand Up @@ -466,6 +467,7 @@ class FluentClientGenerator(
)

documentShape(operation, model, autoSuppressMissingDocs = false)
deprecatedShape(operation)
baseDerives.copy(derives = derives).render(this)
rustTemplate(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import software.amazon.smithy.rust.codegen.rustlang.RustModule
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.Visibility
import software.amazon.smithy.rust.codegen.rustlang.Writable
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.rust
import software.amazon.smithy.rust.codegen.rustlang.rustBlock
Expand Down Expand Up @@ -157,6 +158,7 @@ class CombinedErrorGenerator(
writer.rustBlock("enum ${errorSymbol.name}Kind") {
errors.forEach { errorVariant ->
documentShape(errorVariant, model)
deprecatedShape(errorVariant)
val errorVariantSymbol = symbolProvider.toSymbol(errorVariant)
write("${errorVariantSymbol.name}(#T),", errorVariantSymbol)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.rustlang.RustMetadata
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.Visibility
import software.amazon.smithy.rust.codegen.rustlang.Writable
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.rust
import software.amazon.smithy.rust.codegen.rustlang.rustBlock
Expand Down Expand Up @@ -53,6 +54,7 @@ open class ServerCombinedErrorGenerator(
writer.rustBlock("enum ${errorSymbol.name}") {
errors.forEach { errorVariant ->
documentShape(errorVariant, model)
deprecatedShape(errorVariant)
val errorVariantSymbol = symbolProvider.toSymbol(errorVariant)
write("${errorVariantSymbol.name}(#T),", errorVariantSymbol)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.rustlang.RustModule
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.Visibility
import software.amazon.smithy.rust.codegen.rustlang.asType
import software.amazon.smithy.rust.codegen.rustlang.deprecatedShape
import software.amazon.smithy.rust.codegen.rustlang.documentShape
import software.amazon.smithy.rust.codegen.rustlang.rust
import software.amazon.smithy.rust.codegen.rustlang.rustBlock
Expand Down Expand Up @@ -131,6 +132,7 @@ class TopLevelErrorGenerator(private val coreCodegenContext: CoreCodegenContext,
rustBlock("enum Error") {
allErrors.forEach { error ->
documentShape(error, model)
deprecatedShape(error)
val sym = symbolProvider.toSymbol(error)
rust("${sym.name}(#T),", sym)
}
Expand Down
Loading