2020import java .nio .file .Paths ;
2121import java .util .ArrayList ;
2222import java .util .Collections ;
23+ import java .util .HashMap ;
2324import java .util .HashSet ;
2425import java .util .List ;
2526import java .util .Map ;
3132import software .amazon .smithy .diff .ModelDiff ;
3233import software .amazon .smithy .go .codegen .AddOperationShapes ;
3334import software .amazon .smithy .go .codegen .GoSettings ;
35+ import software .amazon .smithy .go .codegen .Synthetic ;
3436import software .amazon .smithy .go .codegen .integration .GoIntegration ;
3537import software .amazon .smithy .model .Model ;
3638import software .amazon .smithy .model .loader .ModelAssembler ;
@@ -142,7 +144,7 @@ public Model preprocessModel(Model model, GoSettings settings) {
142144 Model previousModel = handleApiGateWayExportsNullabilityExceptions (
143145 getPreviousModel (service , model ), service , nullabilityExceptions , true );
144146 model = handleApiGateWayExportsNullabilityExceptions (
145- model , service , nullabilityExceptions , false );
147+ model , service , nullabilityExceptions , true );
146148 List <ValidationEvent > awsSdkGoV2ChangedNullabilityEvents = getAwsSdkGoV2ChangedNullabilityEvents (
147149 previousModel ,
148150 model );
@@ -153,7 +155,7 @@ public Model preprocessModel(Model model, GoSettings settings) {
153155 }
154156 throw new CodegenException (sb .toString ());
155157 }
156- validateNullabilityExceptions (nullabilityExceptions , model );
158+ validateNullabilityExceptions (nullabilityExceptions , model , service );
157159 return model ;
158160 }
159161
@@ -266,6 +268,7 @@ private static Model handleApiGateWayExportsNullabilityExceptions(
266268 // Patch default traits to nullability exceptions
267269 for (ShapeId shapeId : nullabilityExceptions ) {
268270 if (relaxed && !model .getShape (shapeId ).isPresent ()) {
271+ LOGGER .warning ("Shape `" + shapeId + "` nullability exception is not present in the model" );
269272 continue ;
270273 }
271274 Shape shape = model .expectShape (shapeId );
@@ -316,9 +319,40 @@ private static Model handleApiGateWayExportsNullabilityExceptions(
316319 return ModelTransformer .create ().replaceShapes (model , shapesToReplace );
317320 }
318321
319- private static void validateNullabilityExceptions (Set <ShapeId > nullabilityExceptions , Model model ) {
320- Map <ShapeId , Shape > nullabilityExceptionMap = nullabilityExceptions .stream ()
321- .collect (Collectors .toMap (s -> s , s -> model .expectShape (s )));
322+ private static void validateNullabilityExceptions (Set <ShapeId > nullabilityExceptions , Model model , ShapeId service ) {
323+ Map <ShapeId , Shape > nullabilityExceptionMap = new HashMap <>();
324+ for (ShapeId shapeId : nullabilityExceptions ) {
325+ if (model .getShape (shapeId ).isPresent ()) {
326+ nullabilityExceptionMap .put (shapeId , model .expectShape (shapeId ));
327+ } else {
328+ LOGGER .warning ("Shape `" + shapeId + "` nullability exception is not present in the model" );
329+ }
330+ }
331+
332+ for (BooleanShape shape : model .getBooleanShapesWithTrait (DefaultTrait .class )) {
333+ ShapeId shapeId = shape .toShapeId ();
334+ String namespace = shapeId .getNamespace ();
335+ if (!namespace .equals (service .getNamespace ()) && !namespace .equals (Synthetic .ID .getNamespace ())) {
336+ continue ;
337+ }
338+ if (!nullabilityExceptions .contains (shapeId )) {
339+ throw new CodegenException ("Shape `" + shapeId + "` should be in nullability exceptions" );
340+ }
341+ }
342+
343+ for (NumberShape shape : model .toSet (NumberShape .class ).stream ()
344+ .filter (s -> s .hasTrait (DefaultTrait .class ))
345+ .collect (Collectors .toList ())) {
346+ ShapeId shapeId = shape .toShapeId ();
347+ String namespace = shapeId .getNamespace ();
348+ if (!namespace .equals (service .getNamespace ()) && !namespace .equals (Synthetic .ID .getNamespace ())) {
349+ continue ;
350+ }
351+ if (!nullabilityExceptions .contains (shapeId )) {
352+ throw new CodegenException ("Shape `" + shapeId + "` should be in nullability exceptions" );
353+ }
354+ }
355+
322356 // Existing “defaulted” root boolean or number shapes MUST be backfilled with a
323357 // default trait.
324358 for (Map .Entry <ShapeId , Shape > entry : nullabilityExceptionMap .entrySet ()) {
0 commit comments