in codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/OperationGenerator.java [72:170]
public void run() {
OperationIndex operationIndex = OperationIndex.of(model);
Symbol serviceSymbol = symbolProvider.toSymbol(service);
if (!operationIndex.getInput(operation).isPresent()) {
// Theoretically this shouldn't ever get hit since we automatically insert synthetic inputs / outputs.
throw new CodegenException(
"Operations are required to have input shapes in order to allow for future evolution.");
}
StructureShape inputShape = operationIndex.getInput(operation).get();
Symbol inputSymbol = symbolProvider.toSymbol(inputShape);
if (!operationIndex.getOutput(operation).isPresent()) {
throw new CodegenException(
"Operations are required to have output shapes in order to allow for future evolution.");
}
StructureShape outputShape = operationIndex.getOutput(operation).get();
Symbol outputSymbol = symbolProvider.toSymbol(outputShape);
// Generate operation method
final boolean hasDocs = writer.writeShapeDocs(operation);
operation.getTrait(DeprecatedTrait.class)
.ifPresent(trait -> {
if (hasDocs) {
writer.writeDocs("");
}
final String defaultMessage = "This operation has been deprecated.";
writer.writeDocs("Deprecated: " + trait.getMessage().map(s -> {
if (s.length() == 0) {
return defaultMessage;
}
return s;
}).orElse(defaultMessage));
});
Symbol contextSymbol = SymbolUtils.createValueSymbolBuilder("Context", SmithyGoDependency.CONTEXT).build();
writer.openBlock("func (c $P) $T(ctx $T, params $P, optFns ...func(*Options)) ($P, error) {", "}",
serviceSymbol, operationSymbol, contextSymbol, inputSymbol, outputSymbol, () -> {
writer.write("if params == nil { params = &$T{} }", inputSymbol);
writer.write("");
writer.write("result, metadata, err := c.invokeOperation(ctx, $S, params, optFns, c.$L)",
operationSymbol.getName(), getAddOperationMiddlewareFuncName(operationSymbol));
writer.write("if err != nil { return nil, err }");
writer.write("");
writer.write("out := result.($P)", outputSymbol);
writer.write("out.ResultMetadata = metadata");
writer.write("return out, nil");
}).write("");
// Write out the input and output structures. These are written out here to prevent naming conflicts with other
// shapes in the model.
new StructureGenerator(model, symbolProvider, writer, service, inputShape, inputSymbol, protocolGenerator)
.renderStructure(() -> {
}, true);
var rulesTrait = service.getTrait(EndpointRuleSetTrait.class);
if (rulesTrait.isPresent()) {
writer.write(new EndpointParameterOperationBindingsGenerator(ctx, operation, inputShape)
.generate());
}
// The output structure gets a metadata member added.
Symbol metadataSymbol = SymbolUtils.createValueSymbolBuilder("Metadata", SmithyGoDependency.SMITHY_MIDDLEWARE)
.build();
boolean hasEventStream = Stream.concat(inputShape.members().stream(),
outputShape.members().stream())
.anyMatch(memberShape -> StreamingTrait.isEventStream(model, memberShape));
new StructureGenerator(model, symbolProvider, writer, service, outputShape, outputSymbol, protocolGenerator)
.renderStructure(() -> {
if (outputShape.getMemberNames().size() != 0) {
writer.write("");
}
if (hasEventStream) {
writer.write("eventStream $P",
EventStreamGenerator.getEventStreamOperationStructureSymbol(service, operation))
.write("");
}
writer.writeDocs("Metadata pertaining to the operation's result.");
writer.write("ResultMetadata $T", metadataSymbol);
});
if (hasEventStream) {
writer.write("""
// GetStream returns the type to interact with the event stream.
func (o $P) GetStream() $P {
return o.eventStream
}
""", outputSymbol, EventStreamGenerator.getEventStreamOperationStructureSymbol(
service, operation));
}
// Generate operation protocol middleware helper function
generateAddOperationMiddleware();
}