Add Polly, ApiGateway, fix bugs. (#283)

* wip

* Fixes for Polly & API Gateway

* Add ApiGateway and Polly Models

* Fix ktLint issues

* backport clippy ignores

* remap timeout error

* Format

* Fix error handling on timeout

* Ignore another clippy lint
This commit is contained in:
Russell Cohen 2021-03-31 18:52:37 -04:00 committed by GitHub
parent 138320e99e
commit 9aa7881a1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 13326 additions and 33 deletions

View File

@ -21,7 +21,6 @@ val kotestVersion: String by project
dependencies {
implementation(project(":codegen"))
implementation("software.amazon.smithy:smithy-aws-protocol-tests:$smithyVersion")
implementation("software.amazon.smithy:smithy-protocol-test-traits:$smithyVersion")
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
testImplementation("org.junit.jupiter:junit-jupiter:5.6.1")

View File

@ -31,7 +31,6 @@ buildscript {
dependencies {
implementation(project(":aws:sdk-codegen"))
implementation("software.amazon.smithy:smithy-aws-protocol-tests:$smithyVersion")
implementation("software.amazon.smithy:smithy-protocol-test-traits:$smithyVersion")
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
}
@ -221,8 +220,7 @@ tasks.register<Exec>("cargoDocs") {
tasks.register<Exec>("cargoClippy") {
workingDir(sdkOutputDir)
// disallow warnings
environment("RUSTFLAGS", "-D warnings")
commandLine("cargo", "clippy")
commandLine("cargo", "clippy", "--", "-D", "warnings", "-Aclippy::upper_case_acronyms", "-Aclippy::large-enum-variant", "-Aclippy::module-inception")
dependsOn("assemble")
}

11301
aws/sdk/models/apigateway.json Normal file

File diff suppressed because one or more lines are too long

1940
aws/sdk/models/polly.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -132,8 +132,7 @@ tasks.register<Exec>("cargoDocs") {
tasks.register<Exec>("cargoClippy") {
workingDir("build/smithyprojections/codegen-test/")
// disallow warnings
environment("RUSTFLAGS", "-D warnings")
commandLine("cargo", "clippy")
commandLine("cargo", "clippy", "--", "-D", "warnings", "-Aclippy::upper_case_acronyms", "-Aclippy::large-enum-variant")
dependsOn("assemble")
}

View File

@ -5,6 +5,7 @@ namespace aws.protocoltests.restjson
use aws.protocols#restJson1
use aws.api#service
use smithy.test#httpRequestTests
use smithy.test#httpResponseTests
/// A REST JSON service that sends JSON requests and responses.
@ -12,7 +13,7 @@ use smithy.test#httpRequestTests
@restJson1
service RestJsonExtras {
version: "2019-12-16",
operations: [EnumPayload, StringPayload]
operations: [EnumPayload, StringPayload, PrimitiveIntHeader, EnumQuery]
}
@http(uri: "/EnumPayload", method: "POST")
@ -59,3 +60,45 @@ structure StringPayloadInput {
@httpPayload
payload: String
}
@httpResponseTests([
{
id: "DeserPrimitiveHeader",
protocol: "aws.protocols#restJson1",
code: 200,
headers: { "x-field": "123" },
params: { field: 123 }
}
])
@http(uri: "/primitive", method: "POST")
operation PrimitiveIntHeader {
output: PrimitiveIntHeaderInput
}
integer PrimitiveInt
structure PrimitiveIntHeaderInput {
@httpHeader("x-field")
@required
field: PrimitiveInt
}
@http(uri: "/foo/{enum}", method: "GET")
@httpRequestTests([
{
id: "EnumQueryRequest",
uri: "/foo/enumvalue",
params: { enum: "enumvalue" },
method: "GET",
protocol: "aws.protocols#restJson1"
}
])
operation EnumQuery {
input: EnumQueryInput
}
structure EnumQueryInput {
@httpLabel
@required
enum: StringEnum
}

View File

@ -17,7 +17,6 @@ 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.DocumentationTrait
import software.amazon.smithy.model.traits.EnumTrait
import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.isOptional
import software.amazon.smithy.rust.codegen.smithy.rustType
@ -309,14 +308,6 @@ class RustWriter private constructor(
return formatter.apply(r, "")
}
fun useAs(target: Shape, base: String): String {
return if (target.hasTrait(EnumTrait::class.java)) {
"$base.as_str()"
} else {
base
}
}
fun addDepsRecursively(symbol: Symbol) {
addDependency(symbol)
symbol.references.forEach { addDepsRecursively(it.symbol) }

View File

@ -91,7 +91,7 @@ class CodegenVisitor(context: PluginContext, private val codegenDecorator: RustC
)
)
try {
"cargo fmt".runCommand(fileManifest.baseDir, timeout = 5)
"cargo fmt".runCommand(fileManifest.baseDir, timeout = 10)
} catch (_: CommandFailed) {
logger.warning("Generated output did not parse [${service.id}]")
}

View File

@ -45,6 +45,11 @@ class EnumGenerator(
writer.insertTrailingNewline()
// impl Blah { pub fn as_str(&self) -> &str
implBlock()
writer.rustBlock("impl AsRef<str> for $enumName") {
writer.rustBlock("fn as_ref(&self) -> &str") {
rust("self.as_str()")
}
}
} else {
renderUnamedEnum()
}
@ -132,9 +137,9 @@ class EnumGenerator(
}
private fun renderFromStr() {
writer.rustBlock("impl <T> #T<T> for $enumName where T: #T<str>", RuntimeType.From, RuntimeType.AsRef) {
writer.rustBlock("fn from(s: T) -> Self") {
writer.rustBlock("match s.as_ref()") {
writer.rustBlock("impl #T<&str> for $enumName", RuntimeType.From) {
writer.rustBlock("fn from(s: &str) -> Self") {
writer.rustBlock("match s") {
sortedMembers.forEach { member ->
write(""""${member.value}" => $enumName::${member.derivedName()},""")
}

View File

@ -203,12 +203,11 @@ class RequestBindingGenerator(
private fun headerFmtFun(target: Shape, member: MemberShape, targetName: String): String {
return when {
target.isStringShape -> {
/*val func = */ if (target.hasTrait(MediaTypeTrait::class.java)) {
if (target.hasTrait(MediaTypeTrait::class.java)) {
val func = writer.format(RuntimeType.Base64Encode(runtimeConfig))
"$func(&${writer.useAs(target, targetName)})"
"$func(&$targetName)"
} else {
writer.useAs(target, targetName)
// writer.format(RuntimeType.QueryFormat(runtimeConfig, "fmt_string"))
"AsRef::<str>::as_ref($targetName)"
}
}
target.isTimestampShape -> {
@ -311,7 +310,7 @@ class RequestBindingGenerator(
return when {
target.isStringShape -> {
val func = writer.format(RuntimeType.QueryFormat(runtimeConfig, "fmt_string"))
"$func(&${writer.useAs(target, targetName)})"
"$func(&$targetName)"
}
target.isTimestampShape -> {
val timestampFormat =

View File

@ -181,6 +181,7 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
*/
private fun RustWriter.deserializeFromHeader(targetType: Shape, memberShape: MemberShape) {
val rustType = symbolProvider.toSymbol(targetType).rustType().stripOuter<RustType.Option>()
val fieldRequired = symbolProvider.toSymbol(memberShape).rustType() !is RustType.Option
val (coreType, coreShape) = if (targetType is CollectionShape) {
rustType.stripOuter<RustType.Container>() to model.expectShape(targetType.member.target)
} else {
@ -240,8 +241,9 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
"""
)
else ->
rustTemplate(
"""
if (!fieldRequired) {
rustTemplate(
"""
if $parsedValue.len() > 1 {
Err(#{header_util}::ParseError)
} else {
@ -249,8 +251,21 @@ class ResponseBindingGenerator(protocolConfig: ProtocolConfig, private val opera
Ok($parsedValue.pop())
}
""",
"header_util" to headerUtil
)
"header_util" to headerUtil
)
} else {
rustTemplate(
"""
if $parsedValue.len() > 1 {
Err(#{header_util}::ParseError)
} else {
let mut $parsedValue = $parsedValue;
$parsedValue.pop().ok_or(#{header_util}::ParseError)
}
""",
"header_util" to headerUtil
)
}
}
}
}

View File

@ -23,13 +23,16 @@ fun String.runCommand(workdir: Path? = null, environment: Map<String, String> =
val env = builder.environment()
environment.forEach { (k, v) -> env[k] = v }
val proc = builder.start()
proc.waitFor(timeout, TimeUnit.SECONDS)
val stdErr = proc.errorStream.bufferedReader().readText()
val stdOut = proc.inputStream.bufferedReader().readText()
val output = "$stdErr\n$stdOut"
return when (proc.exitValue()) {
0 -> output
else -> throw CommandFailed("Command Failed\n$output")
try {
return when (proc.exitValue()) {
0 -> output
else -> throw CommandFailed("Command Failed\n$output")
}
} catch (_: IllegalThreadStateException) {
throw CommandFailed("Timeout")
}
}