in codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/server/ServerValidationgenerator.java [81:248]
private void generateShapeValidationFunctions(
GoWriter writer,
Model model, SymbolProvider symbolProvider,
Set<Shape> operationInputShapes,
Set<ShapeId> shapesWithHelpers
) {
GoPointableIndex pointableIndex = GoPointableIndex.of(model);
for (ShapeId shapeId : shapesWithHelpers) {
Shape shape = model.expectShape(shapeId);
boolean topLevelShape = operationInputShapes.contains(shape);
String functionName = getShapeValidatorName(shape, topLevelShape);
Symbol shapeSymbol = symbolProvider.toSymbol(shape);
writer.openBlock("func $L(v $P) error {", "}", functionName, shapeSymbol, () -> {
writer.addUseImports(SmithyGoDependency.SMITHY);
if (pointableIndex.isNillable(shape)) {
writer.openBlock("if v == nil {", "}", () -> writer.write("return nil"));
}
writer.write("invalidParams := smithy.InvalidParamsError{Context: $S}", shapeSymbol.getName());
switch (shape.getType()) {
case STRUCTURE:
shape.members().forEach(memberShape -> {
if (StreamingTrait.isEventStream(model, memberShape)) {
return;
}
String memberName = symbolProvider.toMemberName(memberShape);
Shape targetShape = model.expectShape(memberShape.getTarget());
boolean required = GoValidationIndex.isRequiredParameter(model, memberShape, topLevelShape);
boolean hasHelper = shapesWithHelpers.contains(targetShape.getId());
boolean isEnum = targetShape.getTrait(EnumTrait.class).isPresent();
if (required) {
Runnable runnable = () -> {
writer.write("invalidParams.Add(smithy.NewErrParamRequired($S))", memberName);
if (hasHelper) {
writer.writeInline("} else ");
} else {
writer.write("}");
}
};
if (isEnum) {
writer.write("if len(v.$L) == 0 {", memberName);
runnable.run();
} else if (pointableIndex.isNillable(memberShape)) {
writer.write("if v.$L == nil {", memberName);
runnable.run();
}
}
if (hasHelper) {
Runnable runnable = () -> {
String helperName = getShapeValidatorName(targetShape, false);
writer.openBlock("if err := $L(v.$L); err != nil {", "}", helperName, memberName,
() -> {
writer.addUseImports(SmithyGoDependency.SMITHY);
writer.write(
"invalidParams.AddNested($S, err.(smithy.InvalidParamsError))",
memberName);
});
};
if (isEnum) {
writer.openBlock("if len(v.$L) > 0 {", "}", memberName, runnable);
} else if (pointableIndex.isNillable(memberShape)) {
writer.openBlock("if v.$L != nil {", "}", memberName, runnable);
}
}
});
break;
case LIST:
case SET:
CollectionShape collectionShape = CodegenUtils.expectCollectionShape(shape);
MemberShape member = collectionShape.getMember();
Shape memberTarget = model.expectShape(member.getTarget());
String helperName = getShapeValidatorName(memberTarget, false);
writer.openBlock("for i := range v {", "}", () -> {
String addr = "";
if (!pointableIndex.isPointable(member) && pointableIndex.isPointable(memberTarget)) {
addr = "&";
}
writer.openBlock("if err := $L($Lv[i]); err != nil {", "}", helperName, addr, () -> {
writer.addUseImports(SmithyGoDependency.SMITHY);
writer.addUseImports(SmithyGoDependency.FMT);
writer.write("invalidParams.AddNested(fmt.Sprintf(\"[%d]\", i), "
+ "err.(smithy.InvalidParamsError))");
});
});
break;
case MAP:
MapShape mapShape = shape.asMapShape().get();
MemberShape mapValue = mapShape.getValue();
Shape valueTarget = model.expectShape(mapValue.getTarget());
helperName = getShapeValidatorName(valueTarget, false);
writer.openBlock("for key := range v {", "}", () -> {
String valueVar = "v[key]";
if (!pointableIndex.isPointable(mapValue) && pointableIndex.isPointable(valueTarget)) {
writer.write("value := $L", valueVar);
valueVar = "&value";
}
writer.openBlock("if err := $L($L); err != nil {", "}", helperName, valueVar, () -> {
writer.addUseImports(SmithyGoDependency.SMITHY);
writer.addUseImports(SmithyGoDependency.FMT);
writer.write("invalidParams.AddNested(fmt.Sprintf(\"[%q]\", key), "
+ "err.(smithy.InvalidParamsError))");
});
});
break;
case UNION:
UnionShape unionShape = shape.asUnionShape().get();
Symbol unionSymbol = symbolProvider.toSymbol(unionShape);
Set<MemberShape> memberShapes = unionShape.getAllMembers().values().stream()
.filter(memberShape ->
shapesWithHelpers.contains(model.expectShape(memberShape.getTarget()).getId()))
.collect(Collectors.toCollection(TreeSet::new));
if (memberShapes.size() > 0) {
writer.openBlock("switch uv := v.(type) {", "}", () -> {
// Use a TreeSet to sort the members.
for (MemberShape unionMember : memberShapes) {
Shape target = model.expectShape(unionMember.getTarget());
Symbol memberSymbol = SymbolUtils.createValueSymbolBuilder(
symbolProvider.toMemberName(unionMember),
unionSymbol.getNamespace()
).build();
String memberHelper = getShapeValidatorName(target, false);
writer.openBlock("case *$T:", "", memberSymbol, () -> {
String addr = "";
if (!pointableIndex.isPointable(unionMember)
&& pointableIndex.isPointable(target)) {
addr = "&";
}
writer.openBlock("if err := $L($Luv.Value); err != nil {", "}", memberHelper,
addr, () -> {
writer.addUseImports(SmithyGoDependency.SMITHY);
writer.write("invalidParams.AddNested(\"[$L]\", "
+ "err.(smithy.InvalidParamsError))",
unionMember.getMemberName());
});
});
}
});
}
break;
default:
throw new CodegenException("Unexpected validation helper shape type " + shape.getType());
}
writer.write("if invalidParams.Len() > 0 {");
writer.write("return invalidParams");
writer.write("} else {");
writer.write("return nil");
writer.write("}");
});
writer.write("");
}
}