From 0eed31b13843cded91caf955db091ce8691e893e Mon Sep 17 00:00:00 2001 From: Michael Dowling Date: Fri, 9 Apr 2021 21:14:11 -0700 Subject: [PATCH] Make IDL commas whitespace and newlines optional Commas are now treated as whitespace to reduce visual noise in models, reduce diff noise when changes are made to models, and prevent modelers from worrying about tricks like trailing commas. Commas are still allowed because they do make traits and JSON-like node values defined on a single line easier to read; however, they should be omitted everywhere else. The IDL previously required a newline after various statements. This wasn't grammatically necessary, but was done to force good practice in models. However, it added complexity to the grammar and parser. While models should still define all statements on different lines, to simplify parsers and the grammar, a new line after statements is no longer required. --- README.md | 12 +- .../1.0/guides/converting-to-openapi.rst | 19 +- .../generating-cloudformation-resources.rst | 4 +- docs/source/1.0/guides/model-linters.rst | 26 +- docs/source/1.0/guides/style-guide.rst | 65 +- .../source/1.0/spec/aws/amazon-apigateway.rst | 15 +- docs/source/1.0/spec/aws/aws-auth.rst | 6 +- .../1.0/spec/aws/aws-cloudformation.rst | 218 +++--- docs/source/1.0/spec/aws/aws-core.rst | 60 +- .../1.0/spec/aws/aws-ec2-query-protocol.rst | 24 +- docs/source/1.0/spec/aws/aws-iam.rst | 44 +- .../1.0/spec/aws/aws-query-protocol.rst | 38 +- docs/source/1.0/spec/core/auth-traits.rst | 18 +- docs/source/1.0/spec/core/behavior-traits.rst | 30 +- .../1.0/spec/core/constraint-traits.rst | 24 +- .../1.0/spec/core/documentation-traits.rst | 42 +- docs/source/1.0/spec/core/endpoint-traits.rst | 12 +- docs/source/1.0/spec/core/http-traits.rst | 46 +- docs/source/1.0/spec/core/idl.rst | 45 +- .../source/1.0/spec/core/model-validation.rst | 72 +- docs/source/1.0/spec/core/model.rst | 178 ++--- docs/source/1.0/spec/core/protocol-traits.rst | 8 +- docs/source/1.0/spec/core/resource-traits.rst | 56 +- docs/source/1.0/spec/core/selectors.rst | 28 +- docs/source/1.0/spec/core/stream-traits.rst | 72 +- .../1.0/spec/core/type-refinement-traits.rst | 4 +- docs/source/1.0/spec/core/xml-traits.rst | 70 +- .../spec/http-protocol-compliance-tests.rst | 56 +- docs/source/1.0/spec/mqtt.rst | 32 +- docs/source/1.0/spec/waiters.rst | 68 +- docs/source/quickstart.rst | 727 +++++------------- docs/themes/smithy/landing.html | 12 +- .../smithy/model/loader/IdlModelParser.java | 97 ++- .../smithy/model/loader/IdlNodeParser.java | 12 - .../smithy/model/loader/IdlTraitParser.java | 5 - .../ValidSmithyModelLoaderRunnerTest.java | 6 +- .../loader/dupe-trait-member-names.errors | 2 +- .../invalid/annotation-unclosed-list1.smithy | 2 +- .../invalid/annotation-unclosed-list2.smithy | 2 +- .../invalid/annotation-unclosed-list3.smithy | 2 +- .../annotation-unclosed-object3.smithy | 2 +- .../annotation-unclosed-object4.smithy | 2 +- .../invalid/apply-requires-newline.smithy | 4 - .../invalid/map-requires-newline.smithy | 6 - .../invalid/map-unclosed-parameters1.smithy | 2 +- .../invalid/map-unclosed-parameters2.smithy | 2 +- .../loader/invalid/newline-after-shape.smithy | 4 - .../invalid/use/use-requires-newline.smithy | 6 - .../valid/newlines-are-not-required.json | 14 + .../valid/newlines-are-not-required.smithy | 1 + .../model/loader/valid/optional-commas.json | 260 +++++++ .../model/loader/valid/optional-commas.smithy | 136 ++++ .../amazon/smithy/utils/SimpleParser.java | 23 +- 53 files changed, 1394 insertions(+), 1327 deletions(-) delete mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/apply-requires-newline.smithy delete mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-requires-newline.smithy delete mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/newline-after-shape.smithy delete mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/use/use-requires-newline.smithy create mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.json create mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.smithy create mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.json create mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.smithy diff --git a/README.md b/README.md index 088f17049c9..eb274eb7c96 100644 --- a/README.md +++ b/README.md @@ -19,16 +19,16 @@ shapes. namespace example.weather service Weather { - version: "2006-03-01", - resources: [City], + version: "2006-03-01" + resources: [City] operations: [GetCurrentTime] } resource City { - identifiers: { cityId: CityId }, - read: GetCity, - list: ListCities, - resources: [Forecast], + identifiers: { cityId: CityId } + read: GetCity + list: ListCities + resources: [Forecast] } // See the full example at https://awslabs.github.io/smithy/quickstart.html#complete-example diff --git a/docs/source/1.0/guides/converting-to-openapi.rst b/docs/source/1.0/guides/converting-to-openapi.rst index 05d5502c4df..6921a38789d 100644 --- a/docs/source/1.0/guides/converting-to-openapi.rst +++ b/docs/source/1.0/guides/converting-to-openapi.rst @@ -696,8 +696,8 @@ For example, given the following Smithy model: @restJson1 @httpApiKeyAuth(name: "x-api-key", in: "header") service Foo { - version: "2006-03-01", - operations: [ExampleOperation], + version: "2006-03-01" + operations: [ExampleOperation] } @http(method: "GET", uri: "/") @@ -957,12 +957,13 @@ The following Smithy model: @sigv4(name: "service") @authorizer("foo") @authorizers( - foo: {scheme: sigv4, type: "aws", uri: "arn:foo"}, - baz: {scheme: sigv4, type: "aws", uri: "arn:foo"}) + foo: {scheme: sigv4, type: "aws", uri: "arn:foo"} + baz: {scheme: sigv4, type: "aws", uri: "arn:foo"} + ) service Example { - version: "2019-06-17", - operations: [OperationA, OperationB], - resources: [ResourceA, ResourceB], + version: "2019-06-17" + operations: [OperationA, OperationB] + resources: [ResourceA, ResourceB] } // Inherits the authorizer of the service @@ -1205,8 +1206,8 @@ The following Smithy model enables API Gateway's API key usage plans on the @authorizer("api_key") @authorizers(api_key: {scheme: "smithy.api#httpApiKeyAuth"}) service Example { - version: "2019-06-17", - operations: [OperationA], + version: "2019-06-17" + operations: [OperationA] } operation OperationA {} diff --git a/docs/source/1.0/guides/generating-cloudformation-resources.rst b/docs/source/1.0/guides/generating-cloudformation-resources.rst index a4ca3e8a3e0..695ce356952 100644 --- a/docs/source/1.0/guides/generating-cloudformation-resources.rst +++ b/docs/source/1.0/guides/generating-cloudformation-resources.rst @@ -116,8 +116,8 @@ generate one Resource Schema with the ``typeName`` of ``AWS:Queues:Queue``. @service(sdkId: "Queues", cloudFormationName: "Queues") service QueueService { - version: "2020-07-02", - resources: [Queue], + version: "2020-07-02" + resources: [Queue] } .. important:: diff --git a/docs/source/1.0/guides/model-linters.rst b/docs/source/1.0/guides/model-linters.rst index 9f5265fb14a..7120c6b31b8 100644 --- a/docs/source/1.0/guides/model-linters.rst +++ b/docs/source/1.0/guides/model-linters.rst @@ -187,13 +187,13 @@ Example: metadata validators = [{ id: "FooReservedWords" - name: "ReservedWords", + name: "ReservedWords" configuration: { reserved: [ { - words: ["Codename"], - reason: "This is the internal project name.", - }, + words: ["Codename"] + reason: "This is the internal project name." + } ] } }] @@ -341,13 +341,13 @@ Example: $version: "1.0" metadata validators = [{ - name: "StandardOperationVerb", + name: "StandardOperationVerb" configuration: { - verbs: ["Register", "Deregister", "Associate"], - prefixes: ["Batch"], + verbs: ["Register", "Deregister", "Associate"] + prefixes: ["Batch"] suggestAlternatives: { - "Make": ["Create"], - "Transition": ["Update"], + "Make": ["Create"] + "Transition": ["Update"] } } }] @@ -676,7 +676,7 @@ example warns each time the word "meow" appears in documentation: metadata validators = [ { - name: "ForbiddenDocumentation", + name: "ForbiddenDocumentation" configuration: { forbid: ["meow"] } @@ -695,9 +695,9 @@ example warns each time the word "meow" appears in documentation: metadata validators = [ { - name: "EmitEachSelector", - id: "ForbiddenDocumentation", - message: "Documentation uses forbidden text", + name: "EmitEachSelector" + id: "ForbiddenDocumentation" + message: "Documentation uses forbidden text" configuration: { selector: "[trait|documentation*='meow']" } diff --git a/docs/source/1.0/guides/style-guide.rst b/docs/source/1.0/guides/style-guide.rst index eff772c7797..56e564705e0 100644 --- a/docs/source/1.0/guides/style-guide.rst +++ b/docs/source/1.0/guides/style-guide.rst @@ -39,13 +39,15 @@ Smithy models SHOULD resemble the following example: structure MyStructure { /// Documentation about the member. @required - foo: String, + foo: String } // Example of creating custom traits. @trait(selector: "string") structure myTrait {} +* Each statement should appear on its own line. + File encoding ------------- @@ -93,10 +95,65 @@ Whitespace 4. Members of an object are not horizontally aligned. -Trailing commas ---------------- +Commas +------ + +Omit commas everywhere except in traits or node values defined on a +single line. + +Do: + +.. code-block:: smithy + + $version: "1.0" + + metadata validators = [{ + name: "StandardOperationVerb" + configuration: { + verbs: ["Get", "Delete", "Create", "Update"] + prefixes: ["Batch"] + } + }] + + namespace smithy.example.namespace -Include trailing commas to limit diff noise. + /// Gets a resource by ID. + @http(method: "GET", uri: "/message/{userId}") + operation GetMessage { + input: GetMessageInput + output: GetMessageOutput + errors: [ + ValidationError + ResourceNotFoundError + ] + } + +Do not: + +.. code-block:: smithy + + $version: "1.0" + + metadata validators = [{ + name: "StandardOperationVerb", + configuration: { + verbs: ["Get" "Delete" "Create" "Update"], + prefixes: ["Batch"], + }, + },] + + namespace smithy.example.namespace + + /// Gets a resource by ID. + @http(method: "GET" uri: "/message/{userId}") + operation GetMessage { + input: GetMessageInput, + output: GetMessageOutput, + errors: [ + ValidationError, + ResourceNotFoundError, + ], + } Naming diff --git a/docs/source/1.0/spec/aws/amazon-apigateway.rst b/docs/source/1.0/spec/aws/amazon-apigateway.rst index ba492af7e71..01464e935b5 100644 --- a/docs/source/1.0/spec/aws/amazon-apigateway.rst +++ b/docs/source/1.0/spec/aws/amazon-apigateway.rst @@ -199,14 +199,15 @@ An *authorizer* definition is a structure that supports the following members: @authorizer("arbitrary-name") @authorizers( "arbitrary-name": { - scheme: sigv4, - type: "request", - uri: "arn:foo:baz", - credentials: "arn:foo:bar", - identitySource: "mapping.expression", - identityValidationExpression: "[A-Z]+", + scheme: sigv4 + type: "request" + uri: "arn:foo:baz" + credentials: "arn:foo:bar" + identitySource: "mapping.expression" + identityValidationExpression: "[A-Z]+" resultTtlInSeconds: 100 - }) + } + ) service Weather { version: "2018-03-17" } diff --git a/docs/source/1.0/spec/aws/aws-auth.rst b/docs/source/1.0/spec/aws/aws-auth.rst index f3239ba0b8e..a13c00698f1 100644 --- a/docs/source/1.0/spec/aws/aws-auth.rst +++ b/docs/source/1.0/spec/aws/aws-auth.rst @@ -54,7 +54,7 @@ Trait value @sigv4(name: "foobaz") @restJson1 service FooBaz { - version: "2018-03-17", + version: "2018-03-17" } .. code-tab:: json @@ -109,7 +109,7 @@ operation MUST NOT be used as part of the request signature calculation: @unsignedPayload operation PutThings { - input: PutThingsInput, + input: PutThingsInput output: PutThingsOutput } @@ -182,7 +182,7 @@ Trait value providerArns: ["arn:aws:cognito-idp:us-east-1:123:userpool/123"]) @restJson1 service FooBaz { - version: "2018-03-17", + version: "2018-03-17" } diff --git a/docs/source/1.0/spec/aws/aws-cloudformation.rst b/docs/source/1.0/spec/aws/aws-cloudformation.rst index f64eed1e438..d9f4fccf011 100644 --- a/docs/source/1.0/spec/aws/aws-cloudformation.rst +++ b/docs/source/1.0/spec/aws/aws-cloudformation.rst @@ -74,8 +74,8 @@ resource: @cfnResource resource Foo { identifiers: { - fooId: String, - }, + fooId: String + } } @@ -97,16 +97,16 @@ The following example provides a ``name`` value and one structure shape in the use aws.cloudformation#cfnResource @cfnResource( - name: "Foo", + name: "Foo" additionalSchemas: [AdditionalFooProperties]) resource FooResource { identifiers: { - fooId: String, - }, + fooId: String + } } structure AdditionalFooProperties { - barProperty: String, + barProperty: String } @@ -179,30 +179,30 @@ The following example defines a CloudFormation resource that excludes the @cfnResource resource Foo { identifiers: { - fooId: String, - }, - read: GetFoo, + fooId: String + } + read: GetFoo } @readonly @http(method: "GET", uri: "/foos/{fooId}", code: 200) operation GetFoo { - input: GetFooRequest, - output: GetFooResponse, + input: GetFooRequest + output: GetFooResponse } structure GetFooRequest { @httpLabel @required - fooId: String, + fooId: String } structure GetFooResponse { - fooId: String, + fooId: String @httpResponseCode @cfnExcludeProperty - responseCode: Integer, + responseCode: Integer } @@ -240,62 +240,62 @@ Given the following model without mutability traits applied, @cfnResource resource Foo { identifiers: { - fooId: String, - }, - create: CreateFoo, - read: GetFoo, - update: UpdateFoo, + fooId: String + } + create: CreateFoo + read: GetFoo + update: UpdateFoo } operation CreateFoo { - input: CreateFooRequest, - output: CreateFooResponse, + input: CreateFooRequest + output: CreateFooResponse } structure CreateFooRequest { - createProperty: ComplexProperty, - mutableProperty: ComplexProperty, - writeProperty: ComplexProperty, - createWriteProperty: ComplexProperty, + createProperty: ComplexProperty + mutableProperty: ComplexProperty + writeProperty: ComplexProperty + createWriteProperty: ComplexProperty } structure CreateFooResponse { - fooId: String, + fooId: String } @readonly operation GetFoo { - input: GetFooRequest, - output: GetFooResponse, + input: GetFooRequest + output: GetFooResponse } structure GetFooRequest { @required - fooId: String, + fooId: String } structure GetFooResponse { - fooId: String, - createProperty: ComplexProperty, - mutableProperty: ComplexProperty, - readProperty: ComplexProperty, + fooId: String + createProperty: ComplexProperty + mutableProperty: ComplexProperty + readProperty: ComplexProperty } @idempotent operation UpdateFoo { - input: UpdateFooRequest, + input: UpdateFooRequest } structure UpdateFooRequest { @required - fooId: String, + fooId: String - mutableProperty: ComplexProperty, - writeProperty: ComplexProperty, + mutableProperty: ComplexProperty + writeProperty: ComplexProperty } structure ComplexProperty { - anotherProperty: String, + anotherProperty: String } The computed resource property mutabilities are: @@ -399,28 +399,28 @@ and ``barProperty`` properties as fully mutable: @cfnResource(additionalSchemas: [FooProperties]) resource Foo { identifiers: { - fooId: String, - }, - create: CreateFoo, + fooId: String + } + create: CreateFoo } operation CreateFoo { - input: CreateFooRequest, - output: CreateFooResponse, + input: CreateFooRequest + output: CreateFooResponse } structure CreateFooRequest { @cfnMutability("full") - tags: TagList, + tags: TagList } structure CreateFooResponse { - fooId: String, + fooId: String } structure FooProperties { @cfnMutability("full") - barProperty: String, + barProperty: String } @@ -439,13 +439,13 @@ The following example defines a CloudFormation resource that marks the @cfnResource(additionalSchemas: [FooProperties]) resource Foo { identifiers: { - fooId: String, - }, + fooId: String + } } structure FooProperties { @cfnMutability("create-and-read") - immutableSetting: Boolean, + immutableSetting: Boolean } @@ -464,15 +464,15 @@ The following example defines a CloudFormation resource that marks the @cfnResource(additionalSchemas: [FooProperties]) resource Foo { identifiers: { - fooId: String, - }, - read: GetFoo, + fooId: String + } + read: GetFoo } @readonly operation GetFoo { - input: GetFooRequest, - output: GetFooResponse, + input: GetFooRequest + output: GetFooResponse } structure GetFooRequest { @@ -482,12 +482,12 @@ The following example defines a CloudFormation resource that marks the structure GetFooResponse { @cfnMutability("read") - updatedAt: Timestamp, + updatedAt: Timestamp } structure FooProperties { @cfnMutability("read") - createdAt: Timestamp, + createdAt: Timestamp } @@ -506,28 +506,28 @@ derivable ``secret`` and ``password`` properties as write only: @cfnResource(additionalSchemas: [FooProperties]) resource Foo { identifiers: { - fooId: String, - }, - create: CreateFoo, + fooId: String + } + create: CreateFoo } operation CreateFoo { - input: CreateFooRequest, - output: CreateFooResponse, + input: CreateFooRequest + output: CreateFooResponse } structure CreateFooRequest { @cfnMutability("write") - secret: String, + secret: String } structure CreateFooResponse { - fooId: String, + fooId: String } structure FooProperties { @cfnMutability("write") - password: String, + password: String } @@ -560,10 +560,10 @@ Given the following structure definition: use aws.cloudformation#cfnName structure AdditionalFooProperties { - bar: String, + bar: String @cfnName("Tags") - tagList: TagList, + tagList: TagList } the following property names are derived from it: @@ -618,22 +618,22 @@ The following example defines a CloudFormation resource that has the @cfnResource resource Foo { identifiers: { - fooId: String, - }, - read: GetFoo, + fooId: String + } + read: GetFoo } @readonly operation GetFoo { - input: GetFooRequest, + input: GetFooRequest } structure GetFooRequest { @required - fooId: String, + fooId: String @cfnAdditionalIdentifier - fooAlias: String, + fooAlias: String } @@ -662,106 +662,106 @@ Given the following model, @cfnResource(additionalSchemas: [FooProperties]) resource Foo { identifiers: { - fooId: String, - }, - create: CreateFoo, - read: GetFoo, - update: UpdateFoo, + fooId: String + } + create: CreateFoo + read: GetFoo + update: UpdateFoo } @http(method: "POST", uri: "/foos", code: 200) operation CreateFoo { - input: CreateFooRequest, - output: CreateFooResponse, + input: CreateFooRequest + output: CreateFooResponse } structure CreateFooRequest { @cfnMutability("full") - tags: TagList, + tags: TagList @cfnMutability("write") - secret: String, + secret: String - fooAlias: String, + fooAlias: String - createProperty: ComplexProperty, - mutableProperty: ComplexProperty, - writeProperty: ComplexProperty, - createWriteProperty: ComplexProperty, + createProperty: ComplexProperty + mutableProperty: ComplexProperty + writeProperty: ComplexProperty + createWriteProperty: ComplexProperty } structure CreateFooResponse { - fooId: String, + fooId: String } @readonly @http(method: "GET", uri: "/foos/{fooId}", code: 200) operation GetFoo { - input: GetFooRequest, - output: GetFooResponse, + input: GetFooRequest + output: GetFooResponse } structure GetFooRequest { @httpLabel @required - fooId: String, + fooId: String @httpQuery("fooAlias") @cfnAdditionalIdentifier - fooAlias: String, + fooAlias: String } structure GetFooResponse { - fooId: String, + fooId: String @httpResponseCode @cfnExcludeProperty - responseCode: Integer, + responseCode: Integer @cfnMutability("read") - updatedAt: Timestamp, + updatedAt: Timestamp - fooAlias: String, - createProperty: ComplexProperty, - mutableProperty: ComplexProperty, - readProperty: ComplexProperty, + fooAlias: String + createProperty: ComplexProperty + mutableProperty: ComplexProperty + readProperty: ComplexProperty } @idempotent @http(method: "PUT", uri: "/foos/{fooId}", code: 200) operation UpdateFoo { - input: UpdateFooRequest, + input: UpdateFooRequest } structure UpdateFooRequest { @httpLabel @required - fooId: String, + fooId: String - fooAlias: String, - mutableProperty: ComplexProperty, - writeProperty: ComplexProperty, + fooAlias: String + mutableProperty: ComplexProperty + writeProperty: ComplexProperty } structure FooProperties { - addedProperty: String, + addedProperty: String @cfnMutability("full") - barProperty: String, + barProperty: String @cfnName("Immutable") @cfnMutability("create-and-read") - immutableSetting: Boolean, + immutableSetting: Boolean @cfnMutability("read") - createdAt: Timestamp, + createdAt: Timestamp @cfnMutability("write") - password: String, + password: String } structure ComplexProperty { - anotherProperty: String, + anotherProperty: String } list TagList { diff --git a/docs/source/1.0/spec/aws/aws-core.rst b/docs/source/1.0/spec/aws/aws-core.rst index 8d0cdc4551a..283b522dcfb 100644 --- a/docs/source/1.0/spec/aws/aws-core.rst +++ b/docs/source/1.0/spec/aws/aws-core.rst @@ -46,7 +46,7 @@ The following example defines an AWS service that uses the default values of @service(sdkId: "Some Value") service FooBaz { - version: "2018-03-17", + version: "2018-03-17" } .. code-tab:: json @@ -78,14 +78,14 @@ The following example provides explicit values for all properties: use aws.api#service @service( - sdkId: "Some Value", - cloudFormationName: "FooBaz", - arnNamespace: "myservice", - cloudTrailEventSource: "myservice.amazon.aws", + sdkId: "Some Value" + cloudFormationName: "FooBaz" + arnNamespace: "myservice" + cloudTrailEventSource: "myservice.amazon.aws" endpointPrefix: "my-endpoint" ) service FooBaz { - version: "2018-03-17", + version: "2018-03-17" } .. code-tab:: json @@ -382,13 +382,13 @@ For example, given the following service: @service(sdkId: "Some Value") service FooBaz { - version: "2018-03-17", - resources: [MyResource], + version: "2018-03-17" + resources: [MyResource] } @arn(template: "myresource/{myId}") resource MyResource { - identifiers: {myId: MyResourceId}, + identifiers: {myId: MyResourceId} } .. code-tab:: json @@ -550,8 +550,8 @@ referenced resource. use aws.api#arnReference @arnReference( - type: "AWS::SomeService::SomeResource", - service: com.foo#SomeService, + type: "AWS::SomeService::SomeResource" + service: com.foo#SomeService resource: com.foo#SomeResource) string SomeResourceId @@ -630,12 +630,12 @@ structure, union, or collection unless overridden. @data("permissions") structure MyStructure { - name: String, + name: String @data("content") - content: String, + content: String - tags: TagList, + tags: TagList } @data("tagging") @@ -765,7 +765,7 @@ plane unless an operation or resource is marked with the @controlPlane operation PutThings { - input: PutThingsInput, + input: PutThingsInput output: PutThingsOutput } @@ -819,7 +819,7 @@ plane unless an operation or resource is marked with the @dataPlane operation PutThings { - input: PutThingsInput, + input: PutThingsInput output: PutThingsOutput } @@ -962,17 +962,17 @@ using an ``clientEndpointDiscoveryId``. .. code-tab:: smithy @aws.api#clientEndpointDiscovery( - operation: DescribeEndpoints, - error: InvalidEndpointError, + operation: DescribeEndpoints + error: InvalidEndpointError ) service FooService { - version: "2019-09-10", + version: "2019-09-10" operations: [DescribeEndpoints, GetObject] } operation DescribeEndpoints { - input: DescribeEndpointsInput, - output: DescribeEndpointsOutput, + input: DescribeEndpointsInput + output: DescribeEndpointsOutput errors: [InvalidEndpointError] } @@ -981,17 +981,17 @@ using an ``clientEndpointDiscoveryId``. structure InvalidEndpointError {} structure DescribeEndpointsInput { - Operation: String, - Identifiers: Identifiers, + Operation: String + Identifiers: Identifiers } map Identifiers { - key: String, + key: String value: String } structure DescribeEndpointsOutput { - Endpoints: Endpoints, + Endpoints: Endpoints } list Endpoints { @@ -999,24 +999,24 @@ using an ``clientEndpointDiscoveryId``. } structure Endpoint { - Address: String, - CachePeriodInMinutes: Long, + Address: String + CachePeriodInMinutes: Long } @aws.api#clientDiscoveredEndpoint(required: true) operation GetObject { - input: GetObjectInput, + input: GetObjectInput output: GetObjectOutput } structure GetObjectInput { @clientEndpointDiscoveryId @required - Id: String, + Id: String } structure GetObjectOutput { - Object: Blob, + Object: Blob } .. code-tab:: json diff --git a/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst b/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst index 3f98ceae8a7..c4f0f6696eb 100644 --- a/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst +++ b/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst @@ -239,23 +239,23 @@ For example, given the following: .. code-block:: smithy structure Ec2QueryStructuresInput { - foo: String, + foo: String @ec2QueryName("A") - HasQueryName: String, + HasQueryName: String @ec2QueryName("B") @xmlName("IgnoreMe") - HasQueryAndXmlName: String, + HasQueryAndXmlName: String @xmlName("c") - UsesXmlName: String, + UsesXmlName: String - baz: MyStructure, + baz: MyStructure } structure MyStructure { - temp: String, + temp: String } The ``x-www-form-urlencoded`` serialization is: @@ -281,19 +281,19 @@ For example, given the following: .. code-block:: smithy structure Ec2QueryListsInput { - ListArg: StringList, - ComplexListArg: GreetingList, + ListArg: StringList + ComplexListArg: GreetingList @xmlFlattened - FlattenedListArg: StringList, + FlattenedListArg: StringList - ListArgWithXmlNameMember: ListWithXmlName, + ListArgWithXmlNameMember: ListWithXmlName // Notice that the xmlName on the targeted list member is ignored. @xmlFlattened @ec2QueryName("Hi") @xmlName("IgnoreMe") - FlattenedListArgWithXmlName: ListWithXmlName, + FlattenedListArgWithXmlName: ListWithXmlName } list ListWithXmlName { @@ -310,7 +310,7 @@ For example, given the following: } structure GreetingStruct { - hi: String, + hi: String } The ``x-www-form-urlencoded`` serialization is: diff --git a/docs/source/1.0/spec/aws/aws-iam.rst b/docs/source/1.0/spec/aws/aws-iam.rst index 51a14934c54..398f98b4c18 100644 --- a/docs/source/1.0/spec/aws/aws-iam.rst +++ b/docs/source/1.0/spec/aws/aws-iam.rst @@ -96,14 +96,14 @@ The following example's ``MyResource`` resource has the @service(sdkId: "My Value", arnNamespace: "myservice") @defineConditionKeys("otherservice:Bar": { type: "String" }) service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } @conditionKeys(["otherservice:Bar"]) resource MyResource { - identifiers: {foo: String}, - operations: [MyOperation], + identifiers: {foo: String} + operations: [MyOperation] } @conditionKeys(["aws:region"]) @@ -223,13 +223,13 @@ Each condition key structure supports the following members: @service(sdkId: "My Value", arnNamespace: "myservice") @defineConditionKeys( "otherservice:Bar": { - type: "String", - documentation: "The Bar string", + type: "String" + documentation: "The Bar string" externalDocumentation: "http://example.com" }) service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } .. code-tab:: json @@ -343,16 +343,16 @@ condition key inference disabled. @service(sdkId: "My Value", arnNamespace: "myservice") service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } @disableConditionKeyInference resource MyResource { identifiers: { - foo: String, - bar: String, - }, + foo: String + bar: String + } } .. code-tab:: json @@ -424,13 +424,13 @@ operation for it to complete successfully. @service(sdkId: "My Value", arnNamespace: "myservice") service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } resource MyResource { - identifiers: {foo: String}, - operations: [MyOperation], + identifiers: {foo: String} + operations: [MyOperation] } @requiredActions(["otherservice:OtherOperation"]) @@ -514,15 +514,15 @@ Given the following model, @service(sdkId: "My Value", arnNamespace: "myservice") @defineConditionKeys("otherservice:Bar": { type: "String" }) service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } @conditionKeys(["otherservice:Bar"]) resource MyResource { - identifiers: {foo: String}, - operations: [MyOperation], - resources: [MyInnerResource], + identifiers: {foo: String} + operations: [MyOperation] + resources: [MyInnerResource] } resource MyInnerResource { diff --git a/docs/source/1.0/spec/aws/aws-query-protocol.rst b/docs/source/1.0/spec/aws/aws-query-protocol.rst index dfd5305e704..48c32f9e269 100644 --- a/docs/source/1.0/spec/aws/aws-query-protocol.rst +++ b/docs/source/1.0/spec/aws/aws-query-protocol.rst @@ -156,16 +156,16 @@ For example, given the following: .. code-block:: smithy structure QueryStructuresInput { - foo: String, + foo: String @xmlName("Custom") - bar: String, + bar: String - baz: MyStructure, + baz: MyStructure } structure MyStructure { - temp: String, + temp: String } The ``x-www-form-urlencoded`` serialization is: @@ -189,18 +189,18 @@ For example, given the following: .. code-block:: smithy structure QueryListsInput { - ListArg: StringList, - ComplexListArg: GreetingList, + ListArg: StringList + ComplexListArg: GreetingList @xmlFlattened - FlattenedListArg: StringList, + FlattenedListArg: StringList - ListArgWithXmlNameMember: ListWithXmlName, + ListArgWithXmlNameMember: ListWithXmlName // Notice that the xmlName on the targeted list member is ignored. @xmlFlattened @xmlName("Hi") - FlattenedListArgWithXmlName: ListWithXmlName, + FlattenedListArgWithXmlName: ListWithXmlName } list ListWithXmlName { @@ -217,7 +217,7 @@ For example, given the following: } structure GreetingStruct { - hi: String, + hi: String } The ``x-www-form-urlencoded`` serialization is: @@ -249,36 +249,36 @@ For example, given the following: .. code-block:: smithy structure QueryMapsInput { - MapArg: StringMap, + MapArg: StringMap @xmlName("reNamed") - RenamedMapArg: StringMap, + RenamedMapArg: StringMap - ComplexMapArg: ComplexMap, + ComplexMapArg: ComplexMap - MapWithXmlMemberName: MapWithXmlName, + MapWithXmlMemberName: MapWithXmlName } map StringMap { - key: String, + key: String value: String } map ComplexMap { - key: String, - value: GreetingStruct, + key: String + value: GreetingStruct } map MapWithXmlName { @xmlName("K") - key: String, + key: String @xmlName("V") value: String } structure GreetingStruct { - hi: String, + hi: String } The ``x-www-form-urlencoded`` serialization is: diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index a953a61408b..3c91dd675df 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -62,7 +62,7 @@ and the hypothetical ``fooExample`` authentication scheme. @fooExample @httpBasicAuth service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } .. code-tab:: json @@ -100,7 +100,7 @@ can also support configuration settings. @authDefinition @trait(selector: "service") structure algorithmAuth { - algorithm: AlgorithmAuthAlgorithm, + algorithm: AlgorithmAuthAlgorithm } @private @@ -109,7 +109,7 @@ can also support configuration settings. @algorithmAuth(algorithm: "SHA-2") service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -131,7 +131,7 @@ Value type @httpBasicAuth service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -153,7 +153,7 @@ Value type @httpDigestAuth service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -175,7 +175,7 @@ Value type @httpBearerAuth service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -219,7 +219,7 @@ HTTP header: @httpApiKeyAuth(name: "X-Api-Key", in: "header") service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -244,7 +244,7 @@ and bound to the service is an operation that supports unauthenticated access. @httpDigestAuth service WeatherService { - version: "2017-02-11", + version: "2017-02-11" operations: [PingServer] } @@ -306,7 +306,7 @@ The following example defines two operations: @httpDigestAuth @auth([httpBasicAuth]) service AuthenticatedService { - version: "2017-02-11", + version: "2017-02-11" operations: [OperationA, OperationB] } diff --git a/docs/source/1.0/spec/core/behavior-traits.rst b/docs/source/1.0/spec/core/behavior-traits.rst index fd876c6932f..22cf21ac898 100644 --- a/docs/source/1.0/spec/core/behavior-traits.rst +++ b/docs/source/1.0/spec/core/behavior-traits.rst @@ -51,7 +51,7 @@ member if and only if the member is not explicitly provided. structure AllocateWidgetInput { @idempotencyToken - clientToken: String, + clientToken: String } @@ -78,7 +78,7 @@ Conflicts with @idempotent operation DeleteSomething { - input: DeleteSomethingInput, + input: DeleteSomethingInput output: DeleteSomethingOutput } @@ -109,7 +109,7 @@ Conflicts with @readonly operation GetSomething { - input: GetSomethingInput, + input: GetSomethingInput output: GetSomethingOutput } @@ -244,20 +244,20 @@ explicitly on the operation. @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "maxResults", items: "foos") operation GetFoos { - input: GetFoosInput, + input: GetFoosInput output: GetFoosOutput } structure GetFoosInput { - maxResults: Integer, + maxResults: Integer nextToken: String } structure GetFoosOutput { - nextToken: String, + nextToken: String @required - foos: StringList, + foos: StringList } list StringList { @@ -338,13 +338,13 @@ settings from a service. @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "maxResults") service Example { - version: "2019-06-27", - operations: [GetFoos], + version: "2019-06-27" + operations: [GetFoos] } @readonly @paginated(items: "foos") operation GetFoos { - input: GetFoosInput, + input: GetFoosInput output: GetFoosOutput } @@ -405,12 +405,12 @@ wrapper where the output token and items are referenced by paths. @paginated(inputToken: "nextToken", outputToken: "result.nextToken", pageSize: "maxResults", items: "result.foos") operation GetFoos { - input: GetFoosInput, + input: GetFoosInput output: GetFoosOutput } structure GetFoosInput { - maxResults: Integer, + maxResults: Integer nextToken: String } @@ -420,10 +420,10 @@ wrapper where the output token and items are referenced by paths. } structure ResultWrapper { - nextToken: String, + nextToken: String @required - foos: StringList, + foos: StringList } list StringList { @@ -652,6 +652,6 @@ See @httpChecksumRequired operation PutSomething { - input: PutSomethingInput, + input: PutSomethingInput output: PutSomethingOutput } diff --git a/docs/source/1.0/spec/core/constraint-traits.rst b/docs/source/1.0/spec/core/constraint-traits.rst index 1f31182fac8..fb170e48a39 100644 --- a/docs/source/1.0/spec/core/constraint-traits.rst +++ b/docs/source/1.0/spec/core/constraint-traits.rst @@ -93,28 +93,28 @@ The following example defines an enum of valid string values for ``MyString``. @enum([ { - value: "t2.nano", - name: "T2_NANO", + value: "t2.nano" + name: "T2_NANO" documentation: """ T2 instances are Burstable Performance Instances that provide a baseline level of CPU performance with the ability to burst above the - baseline.""", + baseline.""" tags: ["ebsOnly"] - }, + } { - value: "t2.micro", - name: "T2_MICRO", + value: "t2.micro" + name: "T2_MICRO" documentation: """ T2 instances are Burstable Performance Instances that provide a baseline level of CPU performance with the ability to burst above the - baseline.""", + baseline.""" tags: ["ebsOnly"] - }, + } { - value: "m256.mega", - name: "M256_MEGA", + value: "m256.mega" + name: "M256_MEGA" deprecated: true } ]) @@ -548,7 +548,7 @@ in a response. structure MyStructure { @required - foo: FooString, + foo: FooString } .. code-tab:: json @@ -596,7 +596,7 @@ Value type @uniqueItems list MyList { - member: String, + member: String } .. code-tab:: json diff --git a/docs/source/1.0/spec/core/documentation-traits.rst b/docs/source/1.0/spec/core/documentation-traits.rst index 2266b5f2a68..0a4ca0c576e 100644 --- a/docs/source/1.0/spec/core/documentation-traits.rst +++ b/docs/source/1.0/spec/core/documentation-traits.rst @@ -115,11 +115,11 @@ For example, given the following model, structure Foo { @documentation("Member documentation") - baz: Baz, + baz: Baz - bar: Baz, + bar: Baz - qux: String, + qux: String } @documentation("Shape documentation") @@ -211,29 +211,29 @@ These values use the same semantics and format as @readonly operation MyOperation { - input: MyOperationInput, + input: MyOperationInput output: MyOperationOutput } apply MyOperation @examples([ { - title: "Invoke MyOperation", + title: "Invoke MyOperation" input: { - tags: ["foo", "baz", "bar"], + tags: ["foo", "baz", "bar"] }, output: { - status: "PENDING", + status: "PENDING" } - }, + } { - title: "Another example for MyOperation", + title: "Another example for MyOperation" input: { - foo: "baz", - }, + foo: "baz" + } output: { - status: "PENDING", + status: "PENDING" } - }, + } ]) @@ -256,11 +256,11 @@ Value type .. code-tab:: smithy @externalDocumentation( - "Homepage": "https://www.example.com/", - "API Reference": "https://www.example.com/api-ref", + "Homepage": "https://www.example.com/" + "API Reference": "https://www.example.com/api-ref" ) service MyService { - version: "2006-03-01", + version: "2006-03-01" } @@ -289,10 +289,10 @@ filtered version of the model. .. code-tab:: smithy structure MyStructure { - foo: String, + foo: String @internal - bar: String, + bar: String } @@ -331,10 +331,10 @@ Conflicts with structure PutContentsInput { @required - contents: String, + contents: String @recommended(reason: "Validation will reject contents if they are invalid.") - validateContents: Boolean, + validateContents: Boolean } @@ -432,7 +432,7 @@ Value type @title("ACME Simple Image Service") service MySimpleImageService { - version: "2006-03-01", + version: "2006-03-01" } diff --git a/docs/source/1.0/spec/core/endpoint-traits.rst b/docs/source/1.0/spec/core/endpoint-traits.rst index e614b1ed2a1..0151489c9c9 100644 --- a/docs/source/1.0/spec/core/endpoint-traits.rst +++ b/docs/source/1.0/spec/core/endpoint-traits.rst @@ -55,7 +55,7 @@ The following example defines an operation that uses a custom endpoint: @readonly @endpoint(hostPrefix: "{foo}.data.") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -121,7 +121,7 @@ Given the following operation, @readonly @endpoint(hostPrefix: "{foo}.data.") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -186,7 +186,7 @@ Given the following operation, @readonly @endpoint(hostPrefix: "{foo}-{bar}.data.") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -261,7 +261,7 @@ invalid because the ``{foo}`` and ``{bar}`` labels are adjacent: @readonly @endpoint(hostPrefix: "{foo}{bar}.data.") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -322,7 +322,7 @@ Given the following operation, @endpoint(hostPrefix: "{foo}.data.") @http(method: "GET", uri: "/status") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -414,7 +414,7 @@ to an operation marked with the :ref:`endpoint-trait` will be ignored. @readonly @endpoint(hostPrefix: "{foo}.data") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } diff --git a/docs/source/1.0/spec/core/http-traits.rst b/docs/source/1.0/spec/core/http-traits.rst index 3700d3e0d74..d1347c7d0c0 100644 --- a/docs/source/1.0/spec/core/http-traits.rst +++ b/docs/source/1.0/spec/core/http-traits.rst @@ -69,26 +69,26 @@ The following example defines an operation that uses HTTP bindings: // Sent in the URI label named "key". @required @httpLabel - key: ObjectKey, + key: ObjectKey // Sent in the URI label named "bucketName". @required @httpLabel - bucketName: String, + bucketName: String // Sent in the X-Foo header @httpHeader("X-Foo") - foo: String, + foo: String // Sent in the query string as paramName @httpQuery("paramName") - someValue: String, + someValue: String // Sent in the body - data: MyBlob, + data: MyBlob // Sent in the body - additional: String, + additional: String } @@ -627,7 +627,7 @@ The following example defines an operation that send an HTTP label named @readonly @http(method: "GET", uri: "/{foo}") operation GetStatus { - input: GetStatusInput, + input: GetStatusInput output: GetStatusOutput } @@ -713,16 +713,16 @@ data in a response: @readonly @http(method: "GET", uri: "/random-binary-data") operation GetRandomBinaryData { - output: GetRandomBinaryDataOutput, + output: GetRandomBinaryDataOutput } structure GetRandomBinaryDataOutput { @required @httpHeader("Content-Type") - contentType: String, + contentType: String @httpPayload - content: Blob, + content: Blob } .. _http-protocol-document-payloads: @@ -805,7 +805,7 @@ Given the following Smithy model: } map StringMap { - key: String, + key: String value: String } @@ -875,19 +875,19 @@ request: @readonly @http(method: "GET", uri: "/things") operation ListThings { - input: ListThingsInput, + input: ListThingsInput output: ListThingsOutput, // omitted for brevity } structure ListThingsInput { @httpQuery("color") - color: String, + color: String @httpQuery("shape") - shape: String, + shape: String @httpQuery("size") - size: Integer, + size: Integer } .. rubric:: Serialization rules @@ -968,17 +968,17 @@ target input map as query string parameters in an HTTP request: @readonly @http(method: "GET", uri: "/things") operation ListThings { - input: ListThingsInput, + input: ListThingsInput output: ListThingsOutput, // omitted for brevity } structure ListThingsInput { @httpQueryParams() - myParams: MapOfStrings, + myParams: MapOfStrings } map MapOfStrings { - key: String, + key: String value: String } @@ -1167,16 +1167,16 @@ and HTTP bindings: structure PublishMessagesInput { @httpPayload - messages: MessageStream, + messages: MessageStream } @streaming union MessageStream { - message: Message, + message: Message } structure Message { - message: String, + message: String } .. code-tab:: json @@ -1245,11 +1245,11 @@ marked with the ``httpPayload`` trait: @streaming union MessageStream { - message: Message, + message: Message } structure Message { - message: String, + message: String } diff --git a/docs/source/1.0/spec/core/idl.rst b/docs/source/1.0/spec/core/idl.rst index ea4fca944b2..6009f1ecd48 100644 --- a/docs/source/1.0/spec/core/idl.rst +++ b/docs/source/1.0/spec/core/idl.rst @@ -77,8 +77,12 @@ The following example defines a model file with each section: Lexical notes ------------- -Smithy models MUST be encoded using UTF-8 and SHOULD use Unix style -line endings (``\n``). The Smithy ABNF is whitespace sensitive. +* Smithy models MUST be encoded using UTF-8 and SHOULD use Unix style + line endings (``\n``). +* The Smithy ABNF is whitespace sensitive. +* Except for within strings, commas in the Smithy IDL are considered + whitespace. Commas can be used anywhere where they make the model + easier to read (for example, in complex traits defined on a single line). .. _smithy-idl-abnf: @@ -95,7 +99,7 @@ The Smithy IDL is defined by the following ABNF: .. rubric:: Whitespace .. productionlist:: smithy - ws :*(`sp` / `newline` / `comment`) ; whitespace + ws :*(`sp` / `newline` / `comment` / ",") ; whitespace sp :*(%x20 / %x09) ; " " and \t br :`sp` (`comment` / `newline`) `sp` ; break newline :%x0A / %x0D.0A ; \n and \r\n @@ -112,13 +116,13 @@ The Smithy IDL is defined by the following ABNF: .. productionlist:: smithy control_section :*(`control_statement`) - control_statement :"$" `ws` `node_object_key` `ws` ":" `ws` `node_value` `br` + control_statement :"$" `ws` `node_object_key` `ws` ":" `ws` `node_value` `ws` .. rubric:: Metadata .. productionlist:: smithy metadata_section :*(`metadata_statement`) - metadata_statement :"metadata" `ws` `node_object_key` `ws` "=" `ws` `node_value` `br` + metadata_statement :"metadata" `ws` `node_object_key` `ws` "=" `ws` `node_value` `ws` .. rubric:: Node values @@ -128,18 +132,8 @@ The Smithy IDL is defined by the following ABNF: :/ `number` :/ `node_keywords` :/ `node_string_value` - node_array :`empty_node_array` / `populated_node_array` - empty_node_array :"[" `ws` "]" - populated_node_array:"[" `ws` `node_value` `ws` - : *(`comma` `node_value` `ws`) - : `trailing_comma` "]" - trailing_comma :[`comma`] - comma :"," `ws` - node_object :`empty_node_object` / `populated_node_object` - empty_node_object :"{" `ws` "}" - populated_node_object:"{" `ws` `node_object_kvp` `ws` - : *(`comma` `node_object_kvp` `ws`) - : `trailing_comma` "}" + node_array :"[" `ws` *(`node_value` `ws`) "]" + node_object :"{" `ws` *(`node_object_kvp` `ws`) "}" node_object_kvp :`node_object_key` `ws` ":" `ws` `node_value` node_object_key :`quoted_text` / `identifier` number :[`minus`] `int` [`frac`] [`exp`] @@ -172,11 +166,11 @@ The Smithy IDL is defined by the following ABNF: .. productionlist:: smithy shape_section :[`namespace_statement` [`use_section`] [`shape_statements`]] - namespace_statement :"namespace" `ws` `namespace` `br` + namespace_statement :"namespace" `ws` `namespace` `ws` use_section :*(`use_statement`) - use_statement :"use" `ws` `absolute_root_shape_id` `br` + use_statement :"use" `ws` `absolute_root_shape_id` `ws` shape_statements :*(`shape_statement` / `apply_statement`) - shape_statement :`trait_statements` `shape_body` `br` + shape_statement :`trait_statements` `shape_body` `ws` shape_body :`simple_shape_statement` :/ `list_statement` :/ `set_statement` @@ -191,11 +185,8 @@ The Smithy IDL is defined by the following ABNF: :/ "byte" / "short" / "integer" / "long" :/ "float" / "double" / "bigInteger" :/ "bigDecimal" / "timestamp" - shape_members :`empty_shape_members` / `populated_shape_members` - empty_shape_members :"{" `ws` "}" - populated_shape_members :"{" `ws` `shape_member_kvp` - : *(`comma` `shape_member_kvp` `ws`) `trailing_comma` "}" - shape_member_kvp :`trait_statements` `identifier` `ws` ":" `ws` `shape_id` + shape_members :"{" `ws` *(`shape_member_kvp` `ws`) "}" + shape_member_kvp :`trait_statements` `identifier` `ws` ":" `ws` `shape_id` list_statement :"list" `ws` `identifier` `ws` `shape_members` set_statement :"set" `ws` `identifier` `ws` `shape_members` map_statement :"map" `ws` `identifier` `ws` `shape_members` @@ -212,9 +203,9 @@ The Smithy IDL is defined by the following ABNF: trait :"@" `shape_id` [`trait_body`] trait_body :"(" `ws` `trait_body_value` `ws` ")" trait_body_value :`trait_structure` / `node_value` - trait_structure :`trait_structure_kvp` *(`ws` `comma` `trait_structure_kvp`) + trait_structure :`trait_structure_kvp` *(`ws` `trait_structure_kvp`) trait_structure_kvp :`node_object_key` `ws` ":" `ws` `node_value` - apply_statement :"apply" `ws` `shape_id` `ws` `trait` `br` + apply_statement :"apply" `ws` `shape_id` `ws` `trait` `ws` .. rubric:: Shape ID diff --git a/docs/source/1.0/spec/core/model-validation.rst b/docs/source/1.0/spec/core/model-validation.rst index 76cf81c6945..7f0b10a117b 100644 --- a/docs/source/1.0/spec/core/model-validation.rst +++ b/docs/source/1.0/spec/core/model-validation.rst @@ -106,16 +106,16 @@ The following Smithy document applies a custom validator named "SomeValidator": metadata validators = [ { // The name of the validator. - name: "SomeValidator", + name: "SomeValidator" // Uses a custom event ID for each validation event emitted. - id: "CustomEventId", + id: "CustomEventId" // Uses a custom message that also includes the default message. - message: "My custom message name. {super}", + message: "My custom message name. {super}" // Applies the rule only to the following namespaces. - namespaces: ["foo.baz", "bar.qux"], + namespaces: ["foo.baz", "bar.qux"] // The following properties are specific to the validator. configuration: { - "someProperty": "foo", + "someProperty": "foo" } } ] @@ -253,8 +253,8 @@ in the ``foo.baz`` namespace with an ID of ``UnreferencedShape``: metadata suppressions = [ { - id: "UnreferencedShape", - namespace: "foo.baz", + id: "UnreferencedShape" + namespace: "foo.baz" reason: "This is a test namespace." } ] @@ -268,7 +268,7 @@ ID of ``OverlyBroadValidator``: metadata suppressions = [ { - id: "OverlyBroadValidator", + id: "OverlyBroadValidator" namespace: "*" } ] @@ -335,8 +335,8 @@ following constraints: $version: "1.0" metadata validators = [{ - name: "EmitEachSelector", - id: "MissingDocumentation", + name: "EmitEachSelector" + id: "MissingDocumentation" message: "This shape is missing documentation" configuration: { selector: """ @@ -357,17 +357,17 @@ input/output that has a shape name that does not case-insensitively end with metadata validators = [ { - name: "EmitEachSelector", - id: "OperationInputName", - message: "This shape is referenced as input but the name does not end with 'Input'", + name: "EmitEachSelector" + id: "OperationInputName" + message: "This shape is referenced as input but the name does not end with 'Input'" configuration: { selector: "operation -[input]-> :not([id|name$=Input i])" } - }, + } { - name: "EmitEachSelector", - id: "OperationOutputName", - message: "This shape is referenced as output but the name does not end with 'Output'", + name: "EmitEachSelector" + id: "OperationOutputName" + message: "This shape is referenced as output but the name does not end with 'Output'" configuration: { selector: "operation -[output]-> :not([id|name$=Output i])" } @@ -384,17 +384,17 @@ as lifecycle 'read' or 'delete' that has a shape name that does not start with metadata validators = [ { - name: "EmitEachSelector", - id: "LifecycleGetName", - message: "Lifecycle 'read' operation shape names should start with 'Get'", + name: "EmitEachSelector" + id: "LifecycleGetName" + message: "Lifecycle 'read' operation shape names should start with 'Get'" configuration: { selector: "operation [read]-> :not([id|name^=Get i])" } - }, + } { - name: "EmitEachSelector", - id: "LifecycleDeleteName", - message: "Lifecycle 'delete' operation shape names should start with 'Delete'", + name: "EmitEachSelector" + id: "LifecycleDeleteName" + message: "Lifecycle 'delete' operation shape names should start with 'Delete'" configuration: { selector: "operation -[delete]-> :not([id|name^=Delete i])" } @@ -420,11 +420,11 @@ Consider the following model: metadata validators = [ { - name: "EmitEachSelector", - id: "DocumentedString", + name: "EmitEachSelector" + id: "DocumentedString" configuration: { // matches all shapes - selector: "*", + selector: "*" // Only emitted for shapes with the documentation // trait, and each event points to where the // trait is defined. @@ -471,9 +471,9 @@ Consider the following model: metadata validators = [ { - name: "EmitEachSelector", + name: "EmitEachSelector" configuration: { - selector: "[trait|documentation]", + selector: "[trait|documentation]" messageTemplate: """ This shape has a name of @{id|name} and a @@documentation \ trait of "@{trait|documentation}".""" @@ -509,12 +509,12 @@ to make message templates more descriptive. Consider the following example: metadata validators = [ { - name: "EmitEachSelector", - id: "UnstableTrait", + name: "EmitEachSelector" + id: "UnstableTrait" configuration: { selector: """ $matches(-[trait]-> [trait|unstable]) - ${matches}""", + ${matches}""" messageTemplate: "This shape applies traits(s) that are unstable: @{var|matches|id}" } } @@ -641,12 +641,12 @@ traits. $version: "1.0" metadata validators = [{ - name: "EmitNoneSelector", - id: "MissingConstraintTraits", + name: "EmitNoneSelector" + id: "MissingConstraintTraits" message: """ No instances of the enum, pattern, length, or range trait - could be found. Did you forget to apply these traits?""", + could be found. Did you forget to apply these traits?""" configuration: { - selector: ":is([trait|enum], [trait|pattern], [trait|length], [trait|range])", + selector: ":is([trait|enum], [trait|pattern], [trait|length], [trait|range])" } }] diff --git a/docs/source/1.0/spec/core/model.rst b/docs/source/1.0/spec/core/model.rst index be1bc060039..086e4480018 100644 --- a/docs/source/1.0/spec/core/model.rst +++ b/docs/source/1.0/spec/core/model.rst @@ -849,7 +849,7 @@ The following example defines a map of strings to integers: namespace smithy.example map IntegerMap { - key: String, + key: String value: Integer } @@ -890,7 +890,7 @@ dense. The following example defines a sparse map: @sparse map SparseMap { - key: String, + key: String value: String } @@ -949,10 +949,10 @@ is marked with the :ref:`required-trait`. namespace smithy.example structure MyStructure { - foo: String, + foo: String @required - baz: Integer, + baz: Integer } .. code-tab:: json @@ -1033,12 +1033,12 @@ The following example defines a union shape with several members: namespace smithy.example union MyUnion { - i32: Integer, + i32: Integer - stringA: String, + stringA: String @sensitive - stringB: String, + stringB: String } .. code-tab:: json @@ -1283,8 +1283,8 @@ that do not fit within a resource hierarchy. namespace smithy.example service MyService { - version: "2017-02-11", - operations: [GetServerTime], + version: "2017-02-11" + operations: [GetServerTime] } @readonly @@ -1331,8 +1331,8 @@ shape ID of a resource to the ``resources`` property of a service. namespace smithy.example service MyService { - version: "2017-02-11", - resources: [MyResource], + version: "2017-02-11" + resources: [MyResource] } resource MyResource {} @@ -1418,20 +1418,20 @@ the conflicting shapes. namespace smithy.example service MyService { - version: "2017-02-11", - operations: [GetSomething], + version: "2017-02-11" + operations: [GetSomething] rename: { "foo.example#Widget": "FooWidget" } } operation GetSomething { - output: GetSomethingOutput, + output: GetSomethingOutput } structure GetSomethingOutput { - widget1: Widget, - fooWidget: foo.example#Widget, + widget1: Widget + fooWidget: foo.example#Widget } structure Widget {} @@ -1533,8 +1533,8 @@ can potentially return the ``NotFound`` or ``BadRequest`` namespace smithy.example operation MyOperation { - input: Input, - output: Output, + input: Input + output: Output errors: [NotFound, BadRequest] } @@ -1655,9 +1655,7 @@ single identifier named ``forecastId`` that targets the ``ForecastId`` shape: namespace smithy.example resource Forecast { - identifiers: { - forecastId: ForecastId - } + identifiers: { forecastId: ForecastId } } string ForecastId @@ -1701,23 +1699,23 @@ For example, given the following model, resource ResourceA { identifiers: { a: String - }, - resources: [ResourceB], + } + resources: [ResourceB] } resource ResourceB { identifiers: { - a: String, - b: String, - }, - resources: [ResourceC], + a: String + b: String + } + resources: [ResourceC] } resource ResourceC { identifiers: { - a: String, - b: String, - c: String, + a: String + b: String + c: String } } @@ -1785,25 +1783,25 @@ define an ``identifiers`` property that is compatible with their parents: resource ResourceA { identifiers: { - a: String, - b: String, - }, - resources: [Invalid1, Invalid2], + a: String + b: String + } + resources: [Invalid1, Invalid2] } resource Invalid1 { // Invalid: missing "a". identifiers: { - b: String, - }, + b: String + } } resource Invalid2 { identifiers: { - a: String, + a: String // Invalid: does not target the same shape. - b: SomeOtherString, - }, + b: SomeOtherString + } } .. code-tab:: json @@ -1905,26 +1903,24 @@ For example, given the following model, .. code-tab:: smithy resource Forecast { - identifiers: { - forecastId: ForecastId, - }, - read: GetForecast, + identifiers: { forecastId: ForecastId } + read: GetForecast } @readonly operation GetForecast { - input: GetForecastInput, + input: GetForecastInput output: GetForecastOutput } structure GetForecastInput { @required - forecastId: ForecastId, + forecastId: ForecastId } structure GetForecastOutput { @required - weather: WeatherData, + weather: WeatherData } .. code-tab:: json @@ -1996,20 +1992,18 @@ Given the following model, .. code-tab:: smithy resource Forecast { - identifiers: { - forecastId: ForecastId, - }, - collectionOperations: [BatchPutForecasts], + identifiers: { forecastId: ForecastId } + collectionOperations: [BatchPutForecasts] } operation BatchPutForecasts { - input: BatchPutForecastsInput, + input: BatchPutForecastsInput output: BatchPutForecastsOutput } structure BatchPutForecastsInput { @required - forecasts: BatchPutForecastList, + forecasts: BatchPutForecastList } .. code-tab:: json @@ -2073,28 +2067,28 @@ For example, given the following, resource Forecast { // continued from above - resources: [HistoricalForecast], + resources: [HistoricalForecast] } resource HistoricalForecast { identifiers: { - forecastId: ForecastId, - historicalId: HistoricalForecastId, - }, - read: GetHistoricalForecast, - list: ListHistoricalForecasts, + forecastId: ForecastId + historicalId: HistoricalForecastId + } + read: GetHistoricalForecast + list: ListHistoricalForecasts } @readonly operation GetHistoricalForecast { - input: GetHistoricalForecastInput, + input: GetHistoricalForecastInput output: GetHistoricalForecastOutput } structure GetHistoricalForecastInput { @required @resourceIdentifier("forecastId") - customForecastIdName: ForecastId, + customForecastIdName: ForecastId @required @resourceIdentifier("historicalId") @@ -2127,15 +2121,13 @@ The following example defines a resource with each lifecycle method: namespace smithy.example resource Forecast { - identifiers: { - forecastId: ForecastId, - }, - put: PutForecast, - create: CreateForecast, - read: GetForecast, - update: UpdateForecast, - delete: DeleteForecast, - list: ListForecasts, + identifiers: { forecastId: ForecastId } + put: PutForecast + create: CreateForecast + read: GetForecast + update: UpdateForecast + delete: DeleteForecast + list: ListForecasts } @@ -2157,14 +2149,14 @@ The following example defines the ``PutForecast`` operation. @idempotent operation PutForecast { - input: PutForecastInput, + input: PutForecastInput output: PutForecastOutput } structure PutForecastInput { // The client provides the resource identifier. @required - forecastId: ForecastId, + forecastId: ForecastId chanceOfRain: Float } @@ -2199,19 +2191,19 @@ The following example defines the ``CreateForecast`` operation. .. code-block:: smithy operation CreateForecast { - input: CreateForecastInput, + input: CreateForecastInput output: CreateForecastOutput } operation CreateForecast { - input: CreateForecastInput, + input: CreateForecastInput output: CreateForecastOutput } structure CreateForecastInput { // No identifier is provided by the client, so the service is // responsible for providing the identifier of the resource. - chanceOfRain: Float, + chanceOfRain: Float } @@ -2232,14 +2224,14 @@ For example: @readonly operation GetForecast { - input: GetForecastInput, - output: GetForecastOutput, + input: GetForecastInput + output: GetForecastOutput errors: [ResourceNotFound] } structure GetForecastInput { @required - forecastId: ForecastId, + forecastId: ForecastId } @@ -2259,16 +2251,16 @@ For example: .. code-block:: smithy operation UpdateForecast { - input: UpdateForecastInput, - output: UpdateForecastOutput, + input: UpdateForecastInput + output: UpdateForecastOutput errors: [ResourceNotFound] } structure UpdateForecastInput { @required - forecastId: ForecastId, + forecastId: ForecastId - chanceOfRain: Float, + chanceOfRain: Float } @@ -2289,14 +2281,14 @@ For example: @idempotent operation DeleteForecast { - input: DeleteForecastInput, - output: DeleteForecastOutput, + input: DeleteForecastInput + output: DeleteForecastOutput errors: [ResourceNotFound] } structure DeleteForecastInput { @required - forecastId: ForecastId, + forecastId: ForecastId } @@ -2320,17 +2312,17 @@ For example: @readonly @paginated operation ListForecasts { - input: ListForecastsInput, + input: ListForecastsInput output: ListForecastsOutput } structure ListForecastsInput { - maxResults: Integer, + maxResults: Integer nextToken: String } structure ListForecastsOutput { - nextToken: String, + nextToken: String @required forecasts: ForecastList } @@ -2690,24 +2682,24 @@ The following example defines two custom traits: ``beta`` and @trait(selector: "string", conflicts: [beta]) structure structuredTrait { @required - lorem: StringShape, + lorem: StringShape @required - ipsum: StringShape, + ipsum: StringShape - dolor: StringShape, + dolor: StringShape } // Apply the "beta" trait to the "foo" member. structure MyShape { @required @beta - foo: StringShape, + foo: StringShape } // Apply the structuredTrait to the string. @structuredTrait( - lorem: "This is a custom trait!", + lorem: "This is a custom trait!" ipsum: "lorem and ipsum are both required values.") string StringShape @@ -2840,7 +2832,7 @@ after adding a member to the ``foo`` trait: @trait structure foo { - baz: String, + baz: String } @foo(baz: "bar") diff --git a/docs/source/1.0/spec/core/protocol-traits.rst b/docs/source/1.0/spec/core/protocol-traits.rst index c5069a9ae20..a851048d688 100644 --- a/docs/source/1.0/spec/core/protocol-traits.rst +++ b/docs/source/1.0/spec/core/protocol-traits.rst @@ -76,7 +76,7 @@ The following example defines a service that supports both the hypothetical @jsonExample @xmlExample service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } .. code-tab:: json @@ -129,7 +129,7 @@ support configuration settings. @configurableExample(version: "1.0") service WeatherService { - version: "2017-02-11", + version: "2017-02-11" } @@ -157,9 +157,9 @@ Given the following structure definition, structure MyStructure { @jsonName("Foo") - foo: String, + foo: String - bar: String, + bar: String } .. code-tab:: json diff --git a/docs/source/1.0/spec/core/resource-traits.rst b/docs/source/1.0/spec/core/resource-traits.rst index eb63f5119b1..25160d0ada9 100644 --- a/docs/source/1.0/spec/core/resource-traits.rst +++ b/docs/source/1.0/spec/core/resource-traits.rst @@ -157,14 +157,14 @@ The following example creates a reference to a ``HistoricalForecast`` resource resource HistoricalForecast { identifiers: { - forecastId: ForecastId, - historicalId: HistoricalForecastId, + forecastId: ForecastId + historicalId: HistoricalForecastId } } @references([{resource: HistoricalForecast}]) structure HistoricalReference { - forecastId: ForecastId, + forecastId: ForecastId historicalId: HistoricalForecastId } @@ -184,16 +184,16 @@ defined if needed. For example: @references([ { - resource: HistoricalForecast, + resource: HistoricalForecast ids: { - forecastId: "customForecastId", + forecastId: "customForecastId" historicalId: "customHistoricalId" } } ]) structure AnotherHistoricalReference { - customForecastId: String, - customHistoricalId: String, + customForecastId: String + customHistoricalId: String } .. rubric:: Additional examples @@ -205,31 +205,31 @@ The following example defines several references: .. code-tab:: smithy @references([ - {resource: Forecast}, - {resource: ShapeName}, - {resource: Meteorologist}, + {resource: Forecast} + {resource: ShapeName} + {resource: Meteorologist} { - resource: com.foo.baz#Object, - service: com.foo.baz#Service, - ids: {bucket: "bucketName", object: "objectKey"}, + resource: com.foo.baz#Object + service: com.foo.baz#Service + ids: {bucket: "bucketName", object: "objectKey"} ]) structure ForecastInformation { - someId: SomeShapeIdentifier, + someId: SomeShapeIdentifier @required - forecastId: ForecastId, + forecastId: ForecastId @required - meteorologistId: MeteorologistId, + meteorologistId: MeteorologistId @required - otherData: SomeOtherShape, + otherData: SomeOtherShape @required - bucketName: BucketName, + bucketName: BucketName @required - objectKey: ObjectKey, + objectKey: ObjectKey } .. rubric:: References on string shapes @@ -242,7 +242,7 @@ property in the reference. resource SimpleResource { identifiers: { - foo: String, + foo: String } } @@ -292,28 +292,28 @@ match for the name of the resource identifier. resource File { identifiers: { - directory: "String", - fileName: "String", - }, - read: GetFile, + directory: "String" + fileName: "String" + } + read: GetFile } @readonly operation GetFile { - input: GetFileInput, - output: GetFileOutput, + input: GetFileInput + output: GetFileOutput errors: [NoSuchResource] } structure GetFileInput { @required - directory: String, + directory: String // resourceIdentifier is used because the input member name // does not match the resource identifier name @resourceIdentifier("fileName") @required - name: String, + name: String } diff --git a/docs/source/1.0/spec/core/selectors.rst b/docs/source/1.0/spec/core/selectors.rst index 307d54f6e1f..a0ff1fbabd6 100644 --- a/docs/source/1.0/spec/core/selectors.rst +++ b/docs/source/1.0/spec/core/selectors.rst @@ -719,17 +719,17 @@ in the closure of a service. @trait(selector: "service") list allowedTags { - member: String, + member: String } @allowedTags(["internal", "external"]) service MyService { - version: "2020-04-28", + version: "2020-04-28" operations: [OperationA, OperationB, OperationC, OperationD] } operation OperationA { - input: OperationAInput, + input: OperationAInput } @tags(["internal"]) @@ -742,20 +742,20 @@ in the closure of a service. operation OperationD {} structure OperationAInput { - badValue: BadEnum, - goodValue: GoodEnum, + badValue: BadEnum + goodValue: GoodEnum } @enum([ - {value: "a", tags: ["internal"]}, - {value: "b", tags: ["invalid"]}, + {value: "a", tags: ["internal"]} + {value: "b", tags: ["invalid"]} ]) string BadEnum @enum([ - {value: "a"}, - {value: "b", tags: ["internal", "external"]}, - {value: "c", tags: ["internal"]}, + {value: "a"} + {value: "b", tags: ["internal", "external"]} + {value: "c", tags: ["internal"]} ]) string GoodEnum @@ -1421,9 +1421,9 @@ matches the disqualifier selector. @aws.api#dataPlane service Example { - version: "2020-09-08", - resources: [Foo], - operations: [OperationA], + version: "2020-09-08" + resources: [Foo] + operations: [OperationA] } operation OperationA {} @@ -1514,7 +1514,7 @@ operation: @httpBasicAuth @httpBearerAuth service MyService { - version: "2020-04-21", + version: "2020-04-21" operations: [HasDigestAuth, HasBasicAuth, NoAuth] } diff --git a/docs/source/1.0/spec/core/stream-traits.rst b/docs/source/1.0/spec/core/stream-traits.rst index 9bfc88a7d1b..8100a8cf925 100644 --- a/docs/source/1.0/spec/core/stream-traits.rst +++ b/docs/source/1.0/spec/core/stream-traits.rst @@ -46,13 +46,13 @@ Validation .. code-tab:: smithy operation StreamingOperation { - output: StreamingOperationOutput, + output: StreamingOperationOutput } structure StreamingOperationOutput { @required streamId: String - output: StreamingBlob, + output: StreamingBlob } @streaming @@ -124,18 +124,18 @@ stream in its input by referencing a member that targets a union: } structure PublishMessagesInput { - room: String, - messages: PublishEvents, + room: String + messages: PublishEvents } @streaming union PublishEvents { - message: Message, - leave: LeaveEvent, + message: Message + leave: LeaveEvent } structure Message { - message: String, + message: String } structure LeaveEvent {} @@ -203,19 +203,19 @@ stream in its output: } structure SubscribeToMovementsOutput { - movements: MovementEvents, + movements: MovementEvents } @streaming union MovementEvents { - up: Movement, - down: Movement, - left: Movement, - right: Movement, + up: Movement + down: Movement + left: Movement + right: Movement } structure Movement { - velocity: Float, + velocity: Float } .. code-tab:: json @@ -314,19 +314,19 @@ service, followed by the events sent in the payload of the HTTP message. structure PublishMessagesInput { @httpLabel @required - room: String, + room: String @httpPayload - messages: MessageStream, + messages: MessageStream } @streaming union MessageStream { - message: Message, + message: Message } structure Message { - message: String, + message: String } .. code-tab:: json @@ -414,7 +414,7 @@ message. @http(method: "GET", uri: "/messages/{room}") operation SubscribeToMessages { - input: SubscribeToMessagesInput, + input: SubscribeToMessagesInput output: SubscribeToMessagesOutput } @@ -426,10 +426,10 @@ message. structure SubscribeToMessagesOutput { @httpHeader("X-Connection-Lifetime") - connectionLifetime: Integer, + connectionLifetime: Integer @httpPayload - messages: MessageStream, + messages: MessageStream } .. code-tab:: json @@ -519,14 +519,14 @@ on the name of an event. For example, given the following event stream: } structure SubscribeToEventsOutput { - events: Events, + events: Events } @streaming union Events { - a: Event1, - b: Event2, - c: Event3, + a: Event1 + b: Event2 + c: Event3 } structure Event1 {} @@ -564,13 +564,13 @@ headers and the "c" member as the payload. structure ExampleEvent { @eventHeader - a: String, + a: String @eventHeader - b: String, + b: String @eventPayload - c: Blob, + c: Blob } .. code-tab:: json @@ -613,9 +613,9 @@ based protocol, the event payload is serialized as a JSON object: .. code-tab:: smithy structure ExampleEvent { - a: String, - b: String, - c: Blob, + a: String + b: String + c: Blob } .. code-tab:: json @@ -677,10 +677,10 @@ The following example defines multiple event headers: structure ExampleEvent { @eventHeader - a: String, + a: String @eventHeader - b: String, + b: String } .. code-tab:: json @@ -747,10 +747,10 @@ of an event: structure ExampleEvent { @eventPayload - a: String, + a: String @eventHeader - b: String, + b: String } .. code-tab:: json @@ -785,8 +785,8 @@ The following structure is **invalid** because the "a" member is bound to the structure ExampleEvent { @eventPayload - a: String, + a: String - b: String, + b: String // ^ Error: not bound to an eventHeader. } diff --git a/docs/source/1.0/spec/core/type-refinement-traits.rst b/docs/source/1.0/spec/core/type-refinement-traits.rst index 11b82476393..12cdbf0db2b 100644 --- a/docs/source/1.0/spec/core/type-refinement-traits.rst +++ b/docs/source/1.0/spec/core/type-refinement-traits.rst @@ -132,7 +132,7 @@ in Java). @httpError(429) structure ThrottlingError { @required - message: String, + message: String } @@ -188,7 +188,7 @@ The following example defines a :ref:`map ` shape that MAY contain @sparse map SparseMap { - key: String, + key: String value: String } diff --git a/docs/source/1.0/spec/core/xml-traits.rst b/docs/source/1.0/spec/core/xml-traits.rst index ca742620d2a..88cf865f78f 100644 --- a/docs/source/1.0/spec/core/xml-traits.rst +++ b/docs/source/1.0/spec/core/xml-traits.rst @@ -41,7 +41,7 @@ For example, given the following: .. code-block:: smithy structure MyStructure { - foo: String, + foo: String } The XML serialization is: @@ -80,12 +80,12 @@ members that target it. Given the following: @xmlName("AStruct") structure A { - b: B, + b: B } @xmlName("BStruct") structure B { - hello: String, + hello: String } .. code-tab:: json @@ -146,7 +146,7 @@ The following table defines how simple types are serialized in XML documents. .. code-block:: smithy structure Struct { - binary: Blob, + binary: Blob } given a value of ``value`` for ``binary``: @@ -187,7 +187,7 @@ The following table defines how simple types are serialized in XML documents. .. code-block:: smithy structure Struct { - date: Timestamp, + date: Timestamp } given a value of ``1578255206`` for ``date``: @@ -227,7 +227,7 @@ following: } list MyList { - member: String, + member: String } The XML serialization of ``Foo`` is: @@ -255,7 +255,7 @@ change the nested element name. For example, given the following: list MyList { @xmlName("Item") - member: String, + member: String } .. code-tab:: json @@ -308,7 +308,7 @@ example, given the following: structure Foo { @xmlFlattened - flat: MyList, + flat: MyList } The XML serialization of ``Foo`` is: @@ -329,7 +329,7 @@ the name of the repeated XML element. For example, given the following: union Choice { @xmlFlattened @xmlName("Hi") - flat: MySet, + flat: MySet } set MySet { @@ -354,7 +354,7 @@ following: union Choice { @xmlFlattened - flat: MySet, + flat: MySet } set MySet { @@ -396,8 +396,8 @@ serialized in a nested element named ``entry`` that contains a nested } map MyMap { - key: String, - value: String, + key: String + value: String } The XML serialization of ``Foo`` is: @@ -428,10 +428,10 @@ to change the nested element names. For example, given the following: map MyMap { @xmlName("Name") - key: String, + key: String @xmlName("Setting") - value: String, + value: String } The XML serialization of ``Foo`` is: @@ -468,8 +468,8 @@ into a containing structure/union. For example, given the following: } map MyMap { - key: String, - value: String, + key: String + value: String } .. code-tab:: json @@ -527,11 +527,11 @@ the name of the repeated XML element. For example, given the following: union Choice { @xmlFlattened @xmlName("Hi") - flat: MyMap, + flat: MyMap } map MyMap { - key: String, + key: String value: String } @@ -563,15 +563,15 @@ the following: union Choice { @xmlFlattened @xmlName("Hi") - flat: MyMap, + flat: MyMap } map MyMap { @xmlName("Name") - key: String, + key: String @xmlName("Setting") - value: String, + value: String } The XML serialization of ``Choice`` is: @@ -623,9 +623,9 @@ member name. For example, given the following: structure MyStructure { @xmlAttribute - foo: String, + foo: String - bar: String, + bar: String } .. code-tab:: json @@ -723,13 +723,13 @@ Given the following: structure Foo { @xmlFlattened - flat: MyList, + flat: MyList - nested: MyList, + nested: MyList } list MyList { - member: String, + member: String } .. code-tab:: json @@ -783,9 +783,9 @@ Maps can be flattened into structures too. Given the following: structure Foo { @xmlFlattened - flat: MyMap, + flat: MyMap - notFlat: MyMap, + notFlat: MyMap } map MyMap { @@ -879,9 +879,9 @@ elements using the same name as the structure member name. Given the following: structure MyStructure { @xmlName("Foo") - foo: String, + foo: String - bar: String, + bar: String } .. code-tab:: json @@ -922,7 +922,7 @@ following structure AnotherStructure { @xmlName("hello:foo") - foo: String, + foo: String } The XML serialization is: @@ -977,8 +977,8 @@ Given the following: @xmlNamespace(uri: "http://foo.com") structure MyStructure { - foo: String, - bar: String, + foo: String + bar: String } .. code-tab:: json @@ -1020,10 +1020,10 @@ Given the following: @xmlNamespace(uri: "http://foo.com", prefix: "baz") structure MyStructure { - foo: String, + foo: String @xmlName("baz:bar") - bar: String, + bar: String } The XML serialization is: diff --git a/docs/source/1.0/spec/http-protocol-compliance-tests.rst b/docs/source/1.0/spec/http-protocol-compliance-tests.rst index 014f336d38b..0527c843072 100644 --- a/docs/source/1.0/spec/http-protocol-compliance-tests.rst +++ b/docs/source/1.0/spec/http-protocol-compliance-tests.rst @@ -256,22 +256,22 @@ that uses :ref:`HTTP binding traits `. @http(method: "POST", uri: "/") @httpRequestTests([ { - id: "say_hello", - protocol: exampleProtocol, + id: "say_hello" + protocol: exampleProtocol params: { - "greeting": "Hi", - "name": "Teddy", + "greeting": "Hi" + "name": "Teddy" "query": "Hello there" - }, - method: "POST", - uri: "/", + } + method: "POST" + uri: "/" queryParams: [ "Hi=Hello%20there" - ], + ] headers: { - "X-Greeting": "Hi", - }, - body: "{\"name\": \"Teddy\"}", + "X-Greeting": "Hi" + } + body: "{\"name\": \"Teddy\"}" bodyMediaType: "application/json" } ]) @@ -281,10 +281,10 @@ that uses :ref:`HTTP binding traits `. structure SayHelloInput { @httpHeader("X-Greeting") - greeting: String, + greeting: String @httpQuery("Hi") - query: String, + query: String name: String } @@ -488,12 +488,12 @@ that uses :ref:`HTTP binding traits `. @http(method: "POST", uri: "/") @httpResponseTests([ { - id: "say_goodbye", - protocol: exampleProtocol, - params: {farewell: "Bye"}, - code: 200, + id: "say_goodbye" + protocol: exampleProtocol + params: {farewell: "Bye"} + code: 200 headers: { - "X-Farewell": "Bye", + "X-Farewell": "Bye" "Content-Length": "0" } } @@ -504,7 +504,7 @@ that uses :ref:`HTTP binding traits `. structure SayGoodbyeOutput { @httpHeader("X-Farewell") - farewell: String, + farewell: String } .. code-tab:: json @@ -577,20 +577,20 @@ that uses :ref:`HTTP binding traits `. @httpError(400) @httpResponseTests([ { - id: "invalid_greeting", - protocol: exampleProtocol, - params: {foo: "baz", message: "Hi"}, - code: 400, - headers: {"X-Foo": "baz"}, - body: "{\"message\": \"Hi\"}", - bodyMediaType: "application/json", + id: "invalid_greeting" + protocol: exampleProtocol + params: {foo: "baz", message: "Hi"} + code: 400 + headers: {"X-Foo": "baz"} + body: "{\"message\": \"Hi\"}" + bodyMediaType: "application/json" } ]) structure InvalidGreeting { @httpHeader("X-Foo") - foo: String, + foo: String - message: String, + message: String } .. code-tab:: json diff --git a/docs/source/1.0/spec/mqtt.rst b/docs/source/1.0/spec/mqtt.rst index ac2cf10a945..63a4f710114 100644 --- a/docs/source/1.0/spec/mqtt.rst +++ b/docs/source/1.0/spec/mqtt.rst @@ -102,13 +102,13 @@ and ``{second}``, in the MQTT topic template: structure ExampleOperationInput { @required @topicLabel - first: String, + first: String @required @topicLabel - second: String, + second: String - message: String, + message: String } .. code-tab:: json @@ -216,10 +216,10 @@ The following example defines an operation that publishes messages to the structure PostFooInput { @required @topicLabel - bar: String, + bar: String someValue: String, - anotherValue: Boolean, + anotherValue: Boolean } .. code-tab:: json @@ -326,27 +326,27 @@ topic using an :ref:`event stream `: @subscribe("events/{id}") operation SubscribeForEvents { - input: SubscribeForEventsInput, + input: SubscribeForEventsInput output: SubscribeForEventsOutput } structure SubscribeForEventsInput { @required @topicLabel - id: String, + id: String } structure SubscribeForEventsOutput { - events: EventStream, + events: EventStream } @streaming union EventStream { - message: Event, + message: Event } structure Event { - message: String, + message: String } .. code-tab:: json @@ -531,15 +531,19 @@ MQTT protocol bindings. @protocolDefinition structure mqttJson {} - @trait(selector: "operation:not(-[output]->)", - conflicts: ["smithy.mqtt#subscribe"]) + @trait( + selector: "operation:not(-[output]->)" + conflicts: ["smithy.mqtt#subscribe"] + ) @tags(["diff.error.const"]) // Matches one or more characters that are not "#" or "+". @pattern("^[^#+]+$") string publish - @trait(selector: "operation:test(-[output]-> structure > member > union[trait|streaming])", - conflicts: ["smithy.mqtt#publish"]) + @trait( + selector: "operation:test(-[output]-> structure > member > union[trait|streaming])" + conflicts: [publish] + ) @tags(["diff.error.const"]) // Matches one or more characters that are not "#" or "+". @pattern("^[^#+]+$") diff --git a/docs/source/1.0/spec/waiters.rst b/docs/source/1.0/spec/waiters.rst index 7fa42a01c16..84e3dc6eefc 100644 --- a/docs/source/1.0/spec/waiters.rst +++ b/docs/source/1.0/spec/waiters.rst @@ -54,16 +54,16 @@ exists: @waitable( BucketExists: { - documentation: "Wait until a bucket exists", + documentation: "Wait until a bucket exists" acceptors: [ { - state: "success", + state: "success" matcher: { success: true } - }, + } { - state: "retry", + state: "retry" matcher: { errorType: "NotFound" } @@ -72,8 +72,8 @@ exists: } ) operation HeadBucket { - input: HeadBucketInput, - output: HeadBucketOutput, + input: HeadBucketInput + output: HeadBucketOutput errors: [NotFound] } @@ -602,26 +602,26 @@ triggered if the ``status`` property equals ``failed``. @waitable( ThingExists: { - description: "Waits until a thing has been created", + description: "Waits until a thing has been created" acceptors: [ // Fail-fast if the thing transitions to a "failed" state. { - state: "failure", + state: "failure" matcher: { output: { - path: "status", - comparator: "stringEquals", + path: "status" + comparator: "stringEquals" expected: "failed" } } - }, + } // Succeed when the thing enters into a "success" state. { - state: "success", + state: "success" matcher: { output: { - path: "status", - comparator: "stringEquals", + path: "status" + comparator: "stringEquals" expected: "success" } } @@ -630,13 +630,13 @@ triggered if the ``status`` property equals ``failed``. } ) operation GetThing { - input: GetThingInput, - output: GetThingOutput, + input: GetThingInput + output: GetThingOutput } structure GetThingInput { @required - name: String, + name: String } structure GetThingOutput { @@ -658,8 +658,8 @@ provided groups on input matches the number of provided groups on output: acceptors: [ { inputOutput: { - path: "length(input.groups) == length(output.groups)", - expected: "true", + path: "length(input.groups) == length(output.groups)" + expected: "true" comparator: "booleanEquals" } } @@ -667,8 +667,8 @@ provided groups on input matches the number of provided groups on output: } ) operation ListGroups { - input: ListGroupsInput, - output: ListGroupsOutput, + input: ListGroupsInput + output: ListGroupsOutput } @@ -745,11 +745,11 @@ is unnecessary: { acceptors: [ { - state: "failure", + state: "failure" matcher: { errorType: "ValidationError" } - }, + } // other acceptors... ] } @@ -764,11 +764,11 @@ specific errors. For example, the following matcher is unnecessary: { acceptors: [ { - state: "retry", + state: "retry" matcher: { success: true } - }, + } // other acceptors... ] } @@ -824,24 +824,24 @@ the ``StartResource`` API operation. @waitable( ResourceRunning: { - description: "Waits for the resource to be running", + description: "Waits for the resource to be running" acceptors: [ { - state: "failure", + state: "failure" matcher: { output: { - path: "State", - expected: "Stopped", + path: "State" + expected: "Stopped" comparator: "stringEquals" } } }, { - state: "success", + state: "success" matcher: { output: { - path: "State", - expected: "Running", + path: "State" + expected: "Running" comparator: "stringEquals" } } @@ -851,8 +851,8 @@ the ``StartResource`` API operation. } ) operation GetResource { - input: GetResourceInput, - output: GetResourceOutput, + input: GetResourceInput + output: GetResourceOutput } diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index d2e93d0e4be..cb9f396cc17 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -105,29 +105,15 @@ weather service. ``Weather`` is a :ref:`service` shape that is defined inside of a :ref:`namespace `. -.. tabs:: - - .. code-tab:: smithy +.. code-block:: smithy - namespace example.weather + namespace example.weather - /// Provides weather forecasts. - /// Triple slash comments attach documentation to shapes. - service Weather { - version: "2006-03-01" - } - - .. code-tab:: json - - { - "smithy": "1.0", - "shapes": { - "example.weather#Weather": { - "type": "service", - "version": "2006-03-01" - } - } - } + /// Provides weather forecasts. + /// Triple slash comments attach documentation to shapes. + service Weather { + version: "2006-03-01" + } .. admonition:: What's that syntax? :class: note @@ -150,64 +136,25 @@ Defining resources A resource is contained within a service or another resource. Resources have identifiers, operations, and any number of child resources. -.. tabs:: - - .. code-tab:: smithy - - namespace example.weather - - /// Provides weather forecasts. - service Weather { - version: "2006-03-01", - resources: [City] - } +.. code-block:: smithy - resource City { - identifiers: { cityId: CityId }, - read: GetCity, - list: ListCities, - } + namespace example.weather - // "pattern" is a trait. - @pattern("^[A-Za-z0-9 ]+$") - string CityId + /// Provides weather forecasts. + service Weather { + version: "2006-03-01" + resources: [City] + } - .. code-tab:: json + resource City { + identifiers: { cityId: CityId } + read: GetCity + list: ListCities + } - { - "smithy": "1.0", - "shapes": { - "example.weather#Weather": { - "type": "service", - "version": "2006-03-01", - "resources": [ - { - "target": "example.weather#City" - } - ] - }, - "example.weather#City": { - "type": "resource", - "identifiers": { - "cityId": { - "target": "example.weather#CityId" - } - }, - "read": { - "target": "example.weather#GetCity" - }, - "list": { - "target": "example.weather#ListCities" - } - }, - "example.weather#CityId": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Za-z0-9 ]+$" - } - } - } - } + // "pattern" is a trait. + @pattern("^[A-Za-z0-9 ]+$") + string CityId Because the ``Weather`` service contains many cities, the ``City`` resource defines an :ref:`identifier `. *Identifiers* are used @@ -222,59 +169,19 @@ identity of the resource. Each ``City`` has a single ``Forecast``. This can be defined by adding the ``Forecast`` to the ``resources`` property of the ``City``. -.. tabs:: - - .. code-tab:: smithy - - resource City { - identifiers: { cityId: CityId }, - read: GetCity, - list: ListCities, - resources: [Forecast], - } - - resource Forecast { - identifiers: { cityId: CityId }, - read: GetForecast, - } +.. code-block:: smithy - .. code-tab:: json + resource City { + identifiers: { cityId: CityId } + read: GetCity + list: ListCities + resources: [Forecast] + } - { - "smithy": "1.0", - "shapes": { - "example.weather#City": { - "type": "resource", - "identifiers": { - "cityId": { - "target": "example.weather#CityId" - } - }, - "read": { - "target": "example.weather#GetCity" - }, - "list": { - "target": "example.weather#ListCities" - }, - "resources": [ - { - "target": "example.weather#Forecast" - } - ] - }, - "example.weather#Forecast": { - "type": "resource", - "identifiers": { - "cityId": { - "target": "example.weather#CityId" - } - }, - "read": { - "target": "example.weather#GetForecast" - } - } - } - } + resource Forecast { + identifiers: { cityId: CityId } + read: GetForecast + } Child resources must define the exact same identifiers property of their parent, but they are allowed to add any number of additional identifiers if @@ -303,192 +210,68 @@ lifecycle operations helps automated tooling reason about your API. Let's define the operation used to "read" a ``City``. -.. tabs:: - - .. code-tab:: smithy - - @readonly - operation GetCity { - input: GetCityInput, - output: GetCityOutput, - errors: [NoSuchResource] - } +.. code-block:: smithy - structure GetCityInput { - // "cityId" provides the identifier for the resource and - // has to be marked as required. - @required - cityId: CityId - } - - structure GetCityOutput { - // "required" is used on output to indicate if the service - // will always provide a value for the member. - @required - name: String, + @readonly + operation GetCity { + input: GetCityInput + output: GetCityOutput + errors: [NoSuchResource] + } - @required - coordinates: CityCoordinates, - } + structure GetCityInput { + // "cityId" provides the identifier for the resource and + // has to be marked as required. + @required + cityId: CityId + } - structure CityCoordinates { - @required - latitude: Float, + structure GetCityOutput { + // "required" is used on output to indicate if the service + // will always provide a value for the member. + @required + name: String - @required - longitude: Float, - } + @required + coordinates: CityCoordinates + } - // "error" is a trait that is used to specialize - // a structure as an error. - @error("client") - structure NoSuchResource { - @required - resourceType: String - } + structure CityCoordinates { + @required + latitude: Float - .. code-tab:: json + @required + longitude: Float + } - { - "smithy": "1.0", - "shapes": { - "example.weather#GetCity": { - "type": "operation", - "input": { - "target": "example.weather#GetCityInput" - }, - "output": { - "target": "example.weather#GetCityOutput" - }, - "errors": [ - { - "target": "example.weather#NoSuchResource" - } - ] - }, - "example.weather#GetCityInput": { - "type": "structure", - "members": { - "cityId": { - "target": "example.weather#CityId", - "traits": { - "smithy.api#required": true - } - } - } - }, - "example.weather#GetCityOutput": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#required": true - } - }, - "coordinates": { - "target": "example.weather#CityCoordinates", - "traits": { - "smithy.api#required": true - } - } - } - }, - "example.weather#CityCoordinates": { - "type": "structure", - "members": { - "latitude": { - "target": "smithy.api#Float", - "traits": { - "smithy.api#required": true - } - }, - "longitude": { - "target": "smithy.api#Float", - "traits": { - "smithy.api#required": true - } - } - } - }, - "example.weather#NoSuchResource": { - "type": "structure", - "members": { - "resourceType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#required": true - } - } - }, - "traits": { - "smithy.api#error": "client" - } - } - } - } + // "error" is a trait that is used to specialize + // a structure as an error. + @error("client") + structure NoSuchResource { + @required + resourceType: String + } And define the operation used to "read" a ``Forecast``. -.. tabs:: - - .. code-tab:: smithy +.. code-block:: smithy - @readonly - operation GetForecast { - input: GetForecastInput, - output: GetForecastOutput - } - - // "cityId" provides the only identifier for the resource since - // a Forecast doesn't have its own. - structure GetForecastInput { - @required - cityId: CityId, - } - - structure GetForecastOutput { - chanceOfRain: Float - } + @readonly + operation GetForecast { + input: GetForecastInput + output: GetForecastOutput + } - .. code-tab:: json + // "cityId" provides the only identifier for the resource since + // a Forecast doesn't have its own. + structure GetForecastInput { + @required + cityId: CityId + } - { - "smithy": "1.0", - "shapes": { - "example.weather#GetForecast": { - "type": "operation", - "input": { - "target": "example.weather#GetForecastInput" - }, - "output": { - "target": "example.weather#GetForecastOutput" - }, - "traits": { - "smithy.api#readonly": true - } - }, - "example.weather#GetForecastInput": { - "type": "structure", - "members": { - "cityId": { - "target": "example.weather#CityId", - "traits": { - "smithy.api#required": true - } - } - } - }, - "example.weather#GetForecastOutput": { - "type": "structure", - "members": { - "chanceOfRain": { - "target": "smithy.api#Float" - } - } - } - } - } + structure GetForecastOutput { + chanceOfRain: Float + } .. admonition:: Review :class: tip @@ -510,141 +293,55 @@ is a :ref:`collection operation `, and as such, MUST NOT bind the identifier of a ``City`` to its input structure; we are listing cities, so there's no way we could provide a ``City`` identifier. -.. tabs:: - - .. code-tab:: smithy - - /// Provides weather forecasts. - @paginated(inputToken: "nextToken", outputToken: "nextToken", - pageSize: "pageSize") - service Weather { - version: "2006-03-01", - resources: [City] - } - - // The paginated trait indicates that the operation may - // return truncated results. Applying this trait to the service - // sets default pagination configuration settings on each operation. - @paginated(items: "items") - @readonly - operation ListCities { - input: ListCitiesInput, - output: ListCitiesOutput - } - - structure ListCitiesInput { - nextToken: String, - pageSize: Integer - } +.. code-block:: smithy + + /// Provides weather forecasts. + @paginated( + inputToken: "nextToken" + outputToken: "nextToken" + pageSize: "pageSize" + ) + service Weather { + version: "2006-03-01" + resources: [City] + } - structure ListCitiesOutput { - nextToken: String, + // The paginated trait indicates that the operation may + // return truncated results. Applying this trait to the service + // sets default pagination configuration settings on each operation. + @paginated(items: "items") + @readonly + operation ListCities { + input: ListCitiesInput + output: ListCitiesOutput + } - @required - items: CitySummaries, - } + structure ListCitiesInput { + nextToken: String + pageSize: Integer + } - // CitySummaries is a list of CitySummary structures. - list CitySummaries { - member: CitySummary - } + structure ListCitiesOutput { + nextToken: String - // CitySummary contains a reference to a City. - @references([{resource: City}]) - structure CitySummary { - @required - cityId: CityId, + @required + items: CitySummaries + } - @required - name: String, - } + // CitySummaries is a list of CitySummary structures. + list CitySummaries { + member: CitySummary + } - .. code-tab:: json + // CitySummary contains a reference to a City. + @references([{resource: City}]) + structure CitySummary { + @required + cityId: CityId - { - "smithy": "1.0", - "shapes": { - "example.weather#Weather": { - "type": "service", - "version": "2006-03-01", - "resources": [ - { - "target": "example.weather#City" - } - ], - "traits": { - "smithy.api#paginated": { - "inputToken": "nextToken", - "outputToken": "nextToken", - "pageSize": "pageSize" - } - } - }, - "example.weather#ListCities": { - "type": "operation", - "input": { - "target": "example.weather#ListCitiesInput" - }, - "output": { - "target": "example.weather#ListCitiesOutput" - }, - "traits": { - "smithy.api#readonly": true, - "smithy.api#paginated": { - "items": "items" - } - } - }, - "example.weather#ListCitiesInput": { - "type": "structure", - "members": { - "nextToken": { - "target": "smithy.api#String" - }, - "pageSize": { - "target": "smithy.api#Integer" - } - } - }, - "example.weather#ListCitiesOutput": { - "type": "structure", - "members": { - "nextToken": { - "target": "smithy.api#String" - }, - "items": { - "target": "example.weather#CitySummaries", - "traits": { - "smithy.api#required": true - } - } - } - }, - "example.weather#CitySummaries": { - "type": "list", - "member": { - "target": "example.weather#CitySummary" - } - }, - "example.weather#CitySummary": { - "type": "structure", - "members": { - "cityId": { - "target": "example.weather#CityId", - "traits": { - "smithy.api#required": true - } - }, - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#required": true - } - } - } - } - } - } + @required + name: String + } The ``ListCities`` operation is :ref:`paginated `, meaning the results of invoking the operation can be truncated, requiring subsequent @@ -677,71 +374,27 @@ service shape with no special lifecycle designation using the ``operations`` property. The following operation gets the current time from the ``Weather`` service. +.. code-block:: smithy -.. tabs:: - - .. code-tab:: smithy - - /// Provides weather forecasts. - @paginated(inputToken: "nextToken", outputToken: "nextToken", - pageSize: "pageSize") - service Weather { - version: "2006-03-01", - resources: [City], - operations: [GetCurrentTime] - } - - @readonly - operation GetCurrentTime { - output: GetCurrentTimeOutput - } + /// Provides weather forecasts. + @paginated(inputToken: "nextToken", outputToken: "nextToken", + pageSize: "pageSize") + service Weather { + version: "2006-03-01" + resources: [City] + operations: [GetCurrentTime] + } - structure GetCurrentTimeOutput { - @required - time: Timestamp - } + @readonly + operation GetCurrentTime { + output: GetCurrentTimeOutput + } - .. code-tab:: json + structure GetCurrentTimeOutput { + @required + time: Timestamp + } - { - "smithy": "1.0", - "shapes": { - "example.weather#Weather": { - "type": "service", - "version": "2006-03-01", - "resources": [ - { - "target": "example.weather#City" - } - ], - "operations": [ - { - "target": "example.weather#GetCurrentTime" - } - ] - }, - "example.weather#GetCurrentTime": { - "type": "operation", - "output": { - "target": "example.weather#GetCurrentTimeOutput" - }, - "traits": { - "smithy.api#readonly": true - } - }, - "example.weather#GetCurrentTimeOutput": { - "type": "structure", - "members": { - "time": { - "target": "smithy.api#Timestamp", - "traits": { - "smithy.api#required": true - } - } - } - } - } - } Building the Model ================== @@ -859,24 +512,27 @@ Finally, the complete ``weather.smithy`` model should look like: namespace example.weather /// Provides weather forecasts. - @paginated(inputToken: "nextToken", outputToken: "nextToken", - pageSize: "pageSize") + @paginated( + inputToken: "nextToken" + outputToken: "nextToken" + pageSize: "pageSize" + ) service Weather { - version: "2006-03-01", - resources: [City], + version: "2006-03-01" + resources: [City] operations: [GetCurrentTime] } resource City { - identifiers: { cityId: CityId }, - read: GetCity, - list: ListCities, - resources: [Forecast], + identifiers: { cityId: CityId } + read: GetCity + list: ListCities + resources: [Forecast] } resource Forecast { - identifiers: { cityId: CityId }, - read: GetForecast, + identifiers: { cityId: CityId } + read: GetForecast } // "pattern" is a trait. @@ -885,8 +541,8 @@ Finally, the complete ``weather.smithy`` model should look like: @readonly operation GetCity { - input: GetCityInput, - output: GetCityOutput, + input: GetCityInput + output: GetCityOutput errors: [NoSuchResource] } @@ -901,19 +557,19 @@ Finally, the complete ``weather.smithy`` model should look like: // "required" is used on output to indicate if the service // will always provide a value for the member. @required - name: String, + name: String @required - coordinates: CityCoordinates, + coordinates: CityCoordinates } // This structure is nested within GetCityOutput. structure CityCoordinates { @required - latitude: Float, + latitude: Float @required - longitude: Float, + longitude: Float } // "error" is a trait that is used to specialize @@ -929,20 +585,20 @@ Finally, the complete ``weather.smithy`` model should look like: @readonly @paginated(items: "items") operation ListCities { - input: ListCitiesInput, + input: ListCitiesInput output: ListCitiesOutput } structure ListCitiesInput { - nextToken: String, + nextToken: String pageSize: Integer } structure ListCitiesOutput { - nextToken: String, + nextToken: String @required - items: CitySummaries, + items: CitySummaries } // CitySummaries is a list of CitySummary structures. @@ -954,10 +610,10 @@ Finally, the complete ``weather.smithy`` model should look like: @references([{resource: City}]) structure CitySummary { @required - cityId: CityId, + cityId: CityId @required - name: String, + name: String } @readonly @@ -972,7 +628,7 @@ Finally, the complete ``weather.smithy`` model should look like: @readonly operation GetForecast { - input: GetForecastInput, + input: GetForecastInput output: GetForecastOutput } @@ -980,7 +636,7 @@ Finally, the complete ``weather.smithy`` model should look like: // a Forecast doesn't have its own. structure GetForecastInput { @required - cityId: CityId, + cityId: CityId } structure GetForecastOutput { @@ -1006,6 +662,7 @@ Finally, the complete ``weather.smithy`` model should look like: } ], "traits": { + "smithy.api#documentation": "Provides weather forecasts.", "smithy.api#paginated": { "inputToken": "nextToken", "outputToken": "nextToken", @@ -1038,13 +695,13 @@ Finally, the complete ``weather.smithy`` model should look like: "latitude": { "target": "smithy.api#Float", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } }, "longitude": { "target": "smithy.api#Float", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } } @@ -1067,20 +724,20 @@ Finally, the complete ``weather.smithy`` model should look like: "cityId": { "target": "example.weather#CityId", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } }, "name": { "target": "smithy.api#String", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } }, "traits": { "smithy.api#references": [ { - "resource": "City" + "resource": "example.weather#City" } ] } @@ -1110,7 +767,7 @@ Finally, the complete ``weather.smithy`` model should look like: } ], "traits": { - "smithy.api#readonly": true + "smithy.api#readonly": {} } }, "example.weather#GetCityInput": { @@ -1119,7 +776,7 @@ Finally, the complete ``weather.smithy`` model should look like: "cityId": { "target": "example.weather#CityId", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } } @@ -1127,16 +784,16 @@ Finally, the complete ``weather.smithy`` model should look like: "example.weather#GetCityOutput": { "type": "structure", "members": { - "coordinates": { - "target": "example.weather#CityCoordinates", + "name": { + "target": "smithy.api#String", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } }, - "name": { - "target": "smithy.api#String", + "coordinates": { + "target": "example.weather#CityCoordinates", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } } @@ -1147,7 +804,7 @@ Finally, the complete ``weather.smithy`` model should look like: "target": "example.weather#GetCurrentTimeOutput" }, "traits": { - "smithy.api#readonly": true + "smithy.api#readonly": {} } }, "example.weather#GetCurrentTimeOutput": { @@ -1156,7 +813,7 @@ Finally, the complete ``weather.smithy`` model should look like: "time": { "target": "smithy.api#Timestamp", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } } @@ -1170,7 +827,7 @@ Finally, the complete ``weather.smithy`` model should look like: "target": "example.weather#GetForecastOutput" }, "traits": { - "smithy.api#readonly": true + "smithy.api#readonly": {} } }, "example.weather#GetForecastInput": { @@ -1179,7 +836,7 @@ Finally, the complete ``weather.smithy`` model should look like: "cityId": { "target": "example.weather#CityId", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } } @@ -1204,7 +861,7 @@ Finally, the complete ``weather.smithy`` model should look like: "smithy.api#paginated": { "items": "items" }, - "smithy.api#readonly": true + "smithy.api#readonly": {} } }, "example.weather#ListCitiesInput": { @@ -1221,14 +878,14 @@ Finally, the complete ``weather.smithy`` model should look like: "example.weather#ListCitiesOutput": { "type": "structure", "members": { + "nextToken": { + "target": "smithy.api#String" + }, "items": { "target": "example.weather#CitySummaries", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } - }, - "nextToken": { - "target": "smithy.api#String" } } }, @@ -1238,7 +895,7 @@ Finally, the complete ``weather.smithy`` model should look like: "resourceType": { "target": "smithy.api#String", "traits": { - "smithy.api#required": true + "smithy.api#required": {} } } }, diff --git a/docs/themes/smithy/landing.html b/docs/themes/smithy/landing.html index aa3f15b8dc4..fc06430f9ac 100644 --- a/docs/themes/smithy/landing.html +++ b/docs/themes/smithy/landing.html @@ -17,16 +17,16 @@

Smithy

[full example]namespace example.weather
 
 service Weather {
-    version: "2006-03-01",
-    resources: [City],
+    version: "2006-03-01"
+    resources: [City]
     operations: [GetCurrentTime]
 }
 
 resource City {
-    identifiers: { cityId: CityId },
-    read: GetCity,
-    list: ListCities,
-    resources: [Forecast],
+    identifiers: { cityId: CityId }
+    read: GetCity
+    list: ListCities
+    resources: [Forecast]
 }
 
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlModelParser.java b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlModelParser.java index 9ddfd8a4676..42c827e787a 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlModelParser.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlModelParser.java @@ -142,17 +142,23 @@ ModelFile parse() { @Override public void ws() { while (!eof()) { - char c = peek(); - if (c == '/') { - if (peekDocComment()) { - parseDocComment(); - } else { - parseComment(); - } - } else if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) { - break; - } else { - skip(); + switch (peek()) { + case '/': + if (peekDocComment()) { + parseDocComment(); + } else { + parseComment(); + } + break; + case ' ': + case '\t': + case '\r': + case '\n': + case ',': + skip(); + break; + default: + return; } } } @@ -192,7 +198,6 @@ private void parseControlSection() { .build()); } - br(); ws(); } } @@ -227,7 +232,6 @@ private void parseMetadataSection() { expect('='); ws(); modelFile.putMetadata(key, IdlNodeParser.parseNode(this)); - br(); ws(); } } @@ -249,11 +253,10 @@ private void parseShapeSection() { int start = position(); ParserUtils.consumeNamespace(this); modelFile.setNamespace(sliceFrom(start)); - - br(); // Clear out any erroneous documentation comments. clearPendingDocs(); ws(); + parseUseSection(); parseShapeStatements(); } else if (!eof()) { @@ -278,7 +281,6 @@ private void parseUseSection() { expect('#'); ParserUtils.consumeIdentifier(this); String lexeme = sliceFrom(start); - br(); // Clear out any erroneous documentation comments. clearPendingDocs(); ws(); @@ -422,7 +424,7 @@ private void parseShape(List traits) { addTraits(id, traits); clearPendingDocs(); - br(); + ws(); } private ShapeId parseShapeName() { @@ -451,31 +453,24 @@ private void parseMembers(ShapeId id, Set requiredMembers) { ws(); expect('{'); - // Don't keep any previous state of captured doc comments when - // parsing members. - clearPendingDocs(); ws(); - if (peek() != '}') { - parseMember(id, requiredMembers, definedMembers, remaining); - while (!eof()) { - ws(); - if (peek() == ',') { - expect(','); - // A comma clears out any previously captured documentation - // comments that may have been found when parsing the member. - clearPendingDocs(); - ws(); - if (peek() == '}') { - // Trailing comma: "," "}" - break; - } - parseMember(id, requiredMembers, definedMembers, remaining); - } else { - // Assume '}'; break to enforce. - break; - } + while (!eof()) { + if (peek() == '}') { + break; } + + parseMember(id, requiredMembers, definedMembers, remaining); + + // Clears out any previously captured documentation + // comments that may have been found when parsing the member. + clearPendingDocs(); + + ws(); + } + + if (eof()) { + expect('}'); } if (!remaining.isEmpty()) { @@ -486,7 +481,7 @@ private void parseMembers(ShapeId id, Set requiredMembers) { expect('}'); } - private String parseMember(ShapeId parent, Set required, Set defined, Set remaining) { + private void parseMember(ShapeId parent, Set required, Set defined, Set remaining) { // Parse optional member traits. List memberTraits = parseDocsAndTraits(); SourceLocation memberLocation = currentLocation(); @@ -514,8 +509,6 @@ private String parseMember(ShapeId parent, Set required, Set def modelFile.onShape(memberBuilder); modelFile.addForwardReference(target, memberBuilder::target); addTraits(memberId, memberTraits); - - return memberName; } private void parseMapStatement(ShapeId id, SourceLocation location) { @@ -662,7 +655,6 @@ private void parseApplyStatement() { // Clear out any errantly captured pending docs. clearPendingDocs(); - br(); ws(); } @@ -746,19 +738,16 @@ private String peekDebugMessage() { break; } } - return result.toString(); - } - - // Take two characters for context. - for (int i = 0; i < 2; i++) { - char peek = peek(i); - if (peek == Character.MIN_VALUE) { - result.append("[EOF]"); - break; + } else { + // Take two characters for context. + for (int i = 0; i < 2; i++) { + char peek = peek(i); + if (peek != Character.MIN_VALUE) { + result.append(peek); + } } - result.append(peek); } - return result.toString(); + return result.length() == 0 ? "[EOF]" : result.toString(); } } diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlNodeParser.java b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlNodeParser.java index f8acef0c9bc..3794161955e 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlNodeParser.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlNodeParser.java @@ -143,12 +143,6 @@ static ObjectNode parseObjectNode(IdlModelParser parser, String parent) { throw parser.syntax("Duplicate member of " + parent + ": '" + keyNode.getValue() + '\''); } parser.ws(); - if (parser.peek() == ',') { - parser.skip(); - parser.ws(); - } else { - break; - } } } @@ -179,12 +173,6 @@ private static ArrayNode parseArrayNode(IdlModelParser parser) { } else { items.add(parseNode(parser)); parser.ws(); - if (parser.peek() == ',') { - parser.skip(); - parser.ws(); - } else { - break; - } } } diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlTraitParser.java b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlTraitParser.java index a7dda2041e5..f911cac3738 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlTraitParser.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/loader/IdlTraitParser.java @@ -127,11 +127,6 @@ private static ObjectNode parseStructuredTrait(IdlModelParser parser, StringNode parser.ws(); while (!parser.eof() && parser.peek() != ')') { - parser.expect(','); - parser.ws(); - if (parser.peek() == ')') { - break; - } char c = parser.peek(); if (ParserUtils.isIdentifierStart(c) || c == '"') { parseTraitStructureKvp(parser, entries); diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/loader/ValidSmithyModelLoaderRunnerTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/loader/ValidSmithyModelLoaderRunnerTest.java index c6743ac3583..d825731396f 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/loader/ValidSmithyModelLoaderRunnerTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/loader/ValidSmithyModelLoaderRunnerTest.java @@ -75,11 +75,13 @@ public void parserRunnerTest(String file) { } if (!result.equals(expected)) { + ModelSerializer serializer = ModelSerializer.builder().build(); throw new IllegalStateException(String.format( - "Result did not match the expected model for %s.\nResult:\n\n%s\n\nExpected:\n\n%s", + "Result did not match the expected model for %s.\nResult:\n\n%s\n\nExpected:\n\n%s\r\nDiff: %s", file, formatModel(result), - formatModel(expected))); + formatModel(expected), + Node.diff(serializer.serialize(result), serializer.serialize(expected)))); } } diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/loader/dupe-trait-member-names.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/loader/dupe-trait-member-names.errors index fac09bb1f72..dcf7880ff3f 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/loader/dupe-trait-member-names.errors +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/loader/dupe-trait-member-names.errors @@ -1 +1 @@ -[ERROR] -: Parse error at line 5, column 19 near `, | Model +[ERROR] -: Parse error at line 6, column 1 | Model diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list1.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list1.smithy index fa8ca767a1d..2232a3c7b1d 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list1.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list1.smithy @@ -1,4 +1,4 @@ -// Parse error at line 4, column 1 near `string`: Expected: ']', but found 's' +// Parse error at line 5, column 1 near `[EOF]`: Expected: ']', but found '[EOF]' | Model namespace com.foo @tags(["foo", "bar" string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list2.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list2.smithy index d96babdd243..75d5edb8dd7 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list2.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list2.smithy @@ -1,4 +1,4 @@ -// Parse error at line 4, column 8 near `MyString`: Expected: ']', but found 'M' +// Parse error at line 5, column 1 near `[EOF]`: Expected: ']', but found '[EOF]' namespace com.foo @tags(["foo", "bar", string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list3.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list3.smithy index 95bb574aff9..e28933d9803 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list3.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-list3.smithy @@ -1,4 +1,4 @@ -// Parse error at line 4, column 8 near `MyString`: Expected: ']', but found 'M' +// Parse error at line 5, column 1 near `[EOF]`: Expected: ']', but found '[EOF]' namespace com.foo @tags([ string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object3.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object3.smithy index c74985ddc1f..0e93fd78bee 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object3.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object3.smithy @@ -1,4 +1,4 @@ -// Parse error at line 4, column 8 near `MyString`: Expected: ',', but found 'M' +// Parse error at line 5, column 1 near `[EOF]`: Expected: ':', but found '[EOF]' namespace com.foo @foo(bar: string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object4.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object4.smithy index b880f1a62a4..c1cbbe0a501 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object4.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/annotation-unclosed-object4.smithy @@ -1,4 +1,4 @@ -// Parse error at line 4, column 1 near `string`: Expected: ',', but found 's' +// Parse error at line 4, column 8 near `MyString`: Expected: ':', but found 'M' | Model namespace com.foo @foo(bar: "baz" string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/apply-requires-newline.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/apply-requires-newline.smithy deleted file mode 100644 index 0e936945728..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/apply-requires-newline.smithy +++ /dev/null @@ -1,4 +0,0 @@ -// Parse error at line 4, column 29 near `string`: Expected a line break, but found 's' | Model -namespace com.foo -string SomeShape -apply SomeShape @deprecated string AnotherString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-requires-newline.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-requires-newline.smithy deleted file mode 100644 index 542520f351b..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-requires-newline.smithy +++ /dev/null @@ -1,6 +0,0 @@ -// Parse error at line 6, column 3 near `string`: Expected a line break -namespace com.foo -map MyMap { - key: smithy.api#String, - value: smithy.api#String -} string MyString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters1.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters1.smithy index 5227467efc4..d68680f76fb 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters1.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters1.smithy @@ -1,3 +1,3 @@ -// Parse error at line 4, column 1 near `[EOF]`: Expected a valid identifier character, but found '[EOF]' +// Parse error at line 4, column 1 near `[EOF]`: Expected: '}', but found '[EOF]' namespace com.foo map MyMap { diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters2.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters2.smithy index e041b9fb38b..078e67514bc 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters2.smithy +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/map-unclosed-parameters2.smithy @@ -1,3 +1,3 @@ -// Parse error at line 4, column 1 near `[EOF]`: Expected a valid identifier character, but found '[EOF]' +// Parse error at line 4, column 1 near ``: Expected: '}', but found '' namespace com.foo map MyMap { key: SomeShape, diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/newline-after-shape.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/newline-after-shape.smithy deleted file mode 100644 index bc72d43ba4d..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/newline-after-shape.smithy +++ /dev/null @@ -1,4 +0,0 @@ -// Parse error at line 4, column 17 near `string`: Expected a line break, but found 's' | Model -namespace com.test - -string MyString string OtherString diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/use/use-requires-newline.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/use/use-requires-newline.smithy deleted file mode 100644 index 79d4f763055..00000000000 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/invalid/use/use-requires-newline.smithy +++ /dev/null @@ -1,6 +0,0 @@ -// Parse error at line 6, column 24 near `use`: Expected a line break -$version: "1.0" - -namespace foo.baz - -use smithy.example#Foo use smithy.example#Baz diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.json b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.json new file mode 100644 index 00000000000..8c531be6e71 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.json @@ -0,0 +1,14 @@ +{ + "smithy": "1.0", + "shapes": { + "smithy.example#MyString": { + "type": "string" + }, + "smithy.example#Foo": { + "type": "structure", + "traits": { + "smithy.api#deprecated": {} + } + } + } +} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.smithy new file mode 100644 index 00000000000..cb333abcc07 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/newlines-are-not-required.smithy @@ -0,0 +1 @@ +namespace smithy.example string MyString @deprecated structure Foo {} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.json b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.json new file mode 100644 index 00000000000..61d7bb38930 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.json @@ -0,0 +1,260 @@ +{ + "smithy": "1.0", + "shapes": { + "example.weather#Weather": { + "type": "service", + "version": "2006-03-01", + "operations": [ + { + "target": "example.weather#GetCurrentTime" + } + ], + "resources": [ + { + "target": "example.weather#City" + } + ], + "traits": { + "smithy.api#documentation": "Provides weather forecasts.", + "smithy.api#paginated": { + "inputToken": "nextToken", + "outputToken": "nextToken", + "pageSize": "pageSize" + } + } + }, + "example.weather#City": { + "type": "resource", + "identifiers": { + "cityId": { + "target": "example.weather#CityId" + } + }, + "read": { + "target": "example.weather#GetCity" + }, + "list": { + "target": "example.weather#ListCities" + }, + "resources": [ + { + "target": "example.weather#Forecast" + } + ] + }, + "example.weather#CityCoordinates": { + "type": "structure", + "members": { + "latitude": { + "target": "smithy.api#Float", + "traits": { + "smithy.api#required": {} + } + }, + "longitude": { + "target": "smithy.api#Float", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#CityId": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Za-z0-9 ]+$" + } + }, + "example.weather#CitySummaries": { + "type": "list", + "member": { + "target": "example.weather#CitySummary" + } + }, + "example.weather#CitySummary": { + "type": "structure", + "members": { + "cityId": { + "target": "example.weather#CityId", + "traits": { + "smithy.api#required": {} + } + }, + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#references": [ + { + "resource": "example.weather#City" + } + ] + } + }, + "example.weather#Forecast": { + "type": "resource", + "identifiers": { + "cityId": { + "target": "example.weather#CityId" + } + }, + "read": { + "target": "example.weather#GetForecast" + } + }, + "example.weather#GetCity": { + "type": "operation", + "input": { + "target": "example.weather#GetCityInput" + }, + "output": { + "target": "example.weather#GetCityOutput" + }, + "errors": [ + { + "target": "example.weather#NoSuchResource" + } + ], + "traits": { + "smithy.api#readonly": {} + } + }, + "example.weather#GetCityInput": { + "type": "structure", + "members": { + "cityId": { + "target": "example.weather#CityId", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#GetCityOutput": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#required": {} + } + }, + "coordinates": { + "target": "example.weather#CityCoordinates", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#GetCurrentTime": { + "type": "operation", + "output": { + "target": "example.weather#GetCurrentTimeOutput" + }, + "traits": { + "smithy.api#readonly": {} + } + }, + "example.weather#GetCurrentTimeOutput": { + "type": "structure", + "members": { + "time": { + "target": "smithy.api#Timestamp", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#GetForecast": { + "type": "operation", + "input": { + "target": "example.weather#GetForecastInput" + }, + "output": { + "target": "example.weather#GetForecastOutput" + }, + "traits": { + "smithy.api#readonly": {} + } + }, + "example.weather#GetForecastInput": { + "type": "structure", + "members": { + "cityId": { + "target": "example.weather#CityId", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#GetForecastOutput": { + "type": "structure", + "members": { + "chanceOfRain": { + "target": "smithy.api#Float" + } + } + }, + "example.weather#ListCities": { + "type": "operation", + "input": { + "target": "example.weather#ListCitiesInput" + }, + "output": { + "target": "example.weather#ListCitiesOutput" + }, + "traits": { + "smithy.api#paginated": { + "items": "items" + }, + "smithy.api#readonly": {} + } + }, + "example.weather#ListCitiesInput": { + "type": "structure", + "members": { + "nextToken": { + "target": "smithy.api#String" + }, + "pageSize": { + "target": "smithy.api#Integer" + } + } + }, + "example.weather#ListCitiesOutput": { + "type": "structure", + "members": { + "nextToken": { + "target": "smithy.api#String" + }, + "items": { + "target": "example.weather#CitySummaries", + "traits": { + "smithy.api#required": {} + } + } + } + }, + "example.weather#NoSuchResource": { + "type": "structure", + "members": { + "resourceType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#error": "client" + } + } + } +} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.smithy new file mode 100644 index 00000000000..af770a08455 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/loader/valid/optional-commas.smithy @@ -0,0 +1,136 @@ +namespace example.weather + +// Commas are whitespace. +,,,,,, + +/// Provides weather forecasts. +@paginated( + inputToken: "nextToken" + outputToken: "nextToken" + pageSize: "pageSize" +) +service Weather { + version: "2006-03-01" + resources: [City] + operations: [GetCurrentTime] +} + +resource City { + identifiers: { cityId: CityId } + read: GetCity + list: ListCities + resources: [Forecast] +} + +resource Forecast { + identifiers: { cityId: CityId } + read: GetForecast +} + +// "pattern" is a trait. +@pattern("^[A-Za-z0-9 ]+$") +string CityId + +@readonly +operation GetCity { + input: GetCityInput + output: GetCityOutput + errors: [NoSuchResource] +} + +structure GetCityInput { + // "cityId" provides the identifier for the resource and + // has to be marked as required. + @required + cityId: CityId +} + +structure GetCityOutput { + // "required" is used on output to indicate if the service + // will always provide a value for the member. + @required + name: String + + @required + coordinates: CityCoordinates +} + +// This structure is nested within GetCityOutput. +structure CityCoordinates { + @required + latitude: Float + + @required + longitude: Float +} + +// "error" is a trait that is used to specialize +// a structure as an error. +@error("client") +structure NoSuchResource { + @required + resourceType: String +} + +// The paginated trait indicates that the operation may +// return truncated results. +@readonly +@paginated(items: "items") +operation ListCities { + input: ListCitiesInput + output: ListCitiesOutput +} + +structure ListCitiesInput { + nextToken: String + pageSize: Integer +} + +structure ListCitiesOutput { + nextToken: String + + @required + items: CitySummaries +} + +// CitySummaries is a list of CitySummary structures. +list CitySummaries { + member: CitySummary +} + +// CitySummary contains a reference to a City. +@references([{resource: City}]) +structure CitySummary { + @required + cityId: CityId + + @required + name: String +} + +@readonly +operation GetCurrentTime { + output: GetCurrentTimeOutput +} + +structure GetCurrentTimeOutput { + @required + time: Timestamp +} + +@readonly +operation GetForecast { + input: GetForecastInput + output: GetForecastOutput +} + +// "cityId" provides the only identifier for the resource since +// a Forecast doesn't have its own. +structure GetForecastInput { + @required + cityId: CityId +} + +structure GetForecastOutput { + chanceOfRain: Float +} diff --git a/smithy-utils/src/main/java/software/amazon/smithy/utils/SimpleParser.java b/smithy-utils/src/main/java/software/amazon/smithy/utils/SimpleParser.java index a7049346d38..789efca1072 100644 --- a/smithy-utils/src/main/java/software/amazon/smithy/utils/SimpleParser.java +++ b/smithy-utils/src/main/java/software/amazon/smithy/utils/SimpleParser.java @@ -206,29 +206,28 @@ public RuntimeException syntax(String message) { * Skip 0 or more whitespace characters (that is, ' ', '\t', '\r', and '\n'). */ public void ws() { - while (!eof()) { - char c = peek(); - if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) { - break; - } else { - skip(); - } + while (!eof() && isWhitespace(peek())) { + skip(); } } + private boolean isWhitespace(char c) { + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; + } + /** * Skip 0 or more spaces (that is, ' ' and '\t'). */ public void sp() { - while (!eof()) { - char c = peek(); - if (!(c == ' ' || c == '\t')) { - break; - } + while (!eof() && isSpace(peek())) { skip(); } } + private boolean isSpace(char c) { + return c == ' ' || c == '\t'; + } + /** * Skips spaces then expects that the next character is either the end of * the expression or a line break (\n, \r\n, or \r).