// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import 'package:aws_common/aws_common.dart' hide HttpPayload; import 'package:code_builder/code_builder.dart'; import 'package:smithy/ast.dart'; import 'package:smithy_codegen/src/generator/generator.dart'; import 'package:smithy_codegen/src/generator/serialization/protocol_traits.dart'; import 'package:smithy_codegen/src/generator/types.dart'; import 'package:smithy_codegen/src/util/shape_ext.dart'; import 'package:smithy_codegen/src/util/symbol_ext.dart'; const sdkUnknown = 'sdkUnknown'; /// Useful properties when generating named member shapes (unions + structs). mixin NamedMembersGenerationContext on ShapeGenerator { /// All members on [shape] which are generated. /// /// Can be overriden to limit the members to be code generated. late final List members = shape.members.values.toList(); /// Member shapes and their [Reference] types. late final Map memberSymbols = { for (final member in members) member: context .symbolFor(member.target, shape) .withBoxed(member.isNullable(context, shape)), }; } /// Useful properties when generating union shapes. mixin UnionGenerationContext on ShapeGenerator implements NamedMembersGenerationContext { late final MemberShape unknownMember = MemberShape( (s) => s ..memberName = sdkUnknown ..shapeId = shape.shapeId.replace(member: sdkUnknown) ..target = const ShapeId.core('Document'), ); late final Reference unknownMemberSymbol = DartTypes.core.object.unboxed; late final List allMembers = [...members, unknownMember]; /// Whether this represents the unknown value type. bool isUnknownMember(MemberShape member) => member.memberName == sdkUnknown; /// The name of this member as a union variant. String variantName(MemberShape member) => member.memberName.camelCase.nameEscaped(ShapeType.union); /// The name of the union variant's private class name. String variantClassName(MemberShape member) => '${'_${className}_${member.memberName}'.pascalCase}\$'; } /// Useful properties when generating structure shapes. mixin StructureGenerationContext on ShapeGenerator implements NamedMembersGenerationContext { /// The symbol for the HTTP payload. late final Reference payloadSymbol = () { if (hasPayload) { return shape.httpPayload(context).symbol; } else if (payloadMember != null) { return context.symbolFor(payloadMember!.target, shape); } return symbol; }(); /// The shape for the HTTP payload. late final Shape payloadShape = () { final member = payloadMember; if (member != null) { return context.shapeFor(member.target); } return shape; }(); /// The symbol for the built class, to be generated by `built_value`. late final Reference builtSymbol = symbol.typeRef.rebuild((t) => t.symbol = '_\$$className'); /// The symbol for the builder class, to be generated by `built_value`. late final Reference builderSymbol = symbol.typeRef.rebuild((t) => t.symbol = '${className}Builder'); /// The symbol for the built payload class, to be generated by `built_value`. late final Reference? builtPayloadSymbol = hasBuiltPayload ? symbol.typeRef.rebuild((t) => t.symbol = '_\$$payloadClassName') : null; /// The symbol for the payload's builder class, to be generated by /// `built_value`. late final Reference payloadBuilderSymbol = hasBuiltPayload ? symbol.typeRef.rebuild((t) => t.symbol = '${payloadClassName}Builder') : builderSymbol; /// The name of the payload's class. late final String? payloadClassName = hasBuiltPayload ? '${className}Payload' : null; /// The resolved HTTP input traits. late final HttpInputTraits? httpInputTraits = shape.httpInputTraits(context); /// The resolved HTTP output traits. late final HttpOutputTraits? httpOutputTraits = shape.httpOutputTraits(context); /// The resolved HTTP error traits. late final HttpErrorTraits? httpErrorTraits = shape.httpErrorTraits( context, shape.httpPayload(context).symbol, ); /// The member shape to serialize when [HttpPayloadTrait] is used. late final MemberShape? payloadMember = shape.httpPayload(context).member; /// The list of all members which convey some information about the request, /// and for most protocols are not included in the body of the request. late final List metadataMembers = shape.metadataMembers(context); /// The list of all members which should always be included in the body of /// the request. late final List payloadMembers = shape.payloadMembers(context); /// Whether the structure has an HTTP payload. late final bool hasPayload = shape.hasPayload(context); /// Whether the structure needs a payload struct. late final bool hasBuiltPayload = shape.hasBuiltPayload(context); /// Whether the structure has a streaming payload. late final bool hasStreamingPayload = shape.hasStreamingPayload(context); /// The operation this shape belongs to, if any. late final OperationShape? operationShape = shape.operationShape(context); } /// Useful properties when generating operation shapes. mixin OperationGenerationContext on ShapeGenerator { late final StructureShape inputShape = shape.inputShape(context); late final Reference inputSymbol = shape.inputSymbol(context); late final HttpPayload inputPayload = inputShape.httpPayload(context); late final StructureShape outputShape = shape.outputShape(context); late final Reference outputSymbol = shape.outputSymbol(context); late final HttpPayload outputPayload = outputShape.httpPayload(context); late final List errorSymbols = [ ...?context.service?.errors, ...shape.errors, ].whereType().map((error) { final shape = context.shapeFor(error.target) as StructureShape; return shape.httpErrorTraits(context, shape.httpPayload(context).symbol)!; }).toList(); late final HttpTrait? httpTrait = shape.httpTrait(context); late final HttpInputTraits httpInputTraits = inputShape.httpInputTraits( context, overrideTrait: true, )!; late final HttpOutputTraits httpOutputTraits = outputShape.httpOutputTraits( context, overrideTrait: true, )!; late final PaginatedTraits? paginatedTraits = shape.paginatedTraits(context); }