@@ -106,7 +106,7 @@ public function generate(StructureShape $shape, bool $forEndpoint = false): Clas
106106
107107 $ serializer = $ this ->serializer ->get ($ shape ->getService ());
108108 if ($ this ->isShapeUsedInput ($ shape )) {
109- [$ returnType , $ requestBody , $ args ] = $ serializer ->generateRequestBuilder ($ shape ) + [null , null , []];
109+ [$ returnType , $ requestBody , $ args ] = $ serializer ->generateRequestBuilder ($ shape, false ) + [null , null , []];
110110 $ method = $ classBuilder ->addMethod ('requestBody ' )->setReturnType ($ returnType )->setBody ($ requestBody )->setPublic ()->setComment ('@internal ' );
111111 foreach ($ args as $ arg => $ type ) {
112112 $ method ->addParameter ($ arg )->setType ($ type );
@@ -191,36 +191,60 @@ private function namedConstructor(StructureShape $shape, ClassBuilder $classBuil
191191
192192 $ constructor ->addParameter ('input ' )->setType ('array ' );
193193
194+ // To throw an exception in an expression, we need to use a method to support PHP 7.x
195+ $ needsThrowMethod = false ;
196+
194197 $ constructorBody = '' ;
195198 foreach ($ shape ->getMembers () as $ member ) {
196199 $ memberShape = $ member ->getShape ();
197200 if ($ memberShape instanceof StructureShape) {
198201 $ objectClass = $ this ->generate ($ memberShape );
199- $ constructorBody . = strtr ('$this->PROPERTY = isset($input["NAME"]) ? CLASS::create($input["NAME"]) : null; ' . "\n" , [' PROPERTY ' => GeneratorHelper:: normalizeName ( $ member -> getName ()), 'NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
202+ $ memberCode = strtr ('CLASS::create($input["NAME"]) ' , ['NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
200203 } elseif ($ memberShape instanceof ListShape) {
201204 $ listMemberShape = $ memberShape ->getMember ()->getShape ();
202205
203206 // Check if this is a list of objects
204207 if ($ listMemberShape instanceof StructureShape) {
205208 $ objectClass = $ this ->generate ($ listMemberShape );
206- $ constructorBody . = strtr ('$this->PROPERTY = isset($input["NAME"]) ? array_map([CLASS::class, "create"], $input["NAME"]) : null; ' . "\n" , [' PROPERTY ' => GeneratorHelper:: normalizeName ( $ member -> getName ()), 'NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
209+ $ memberCode = strtr ('array_map([CLASS::class, "create"], $input["NAME"]) ' , ['NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
207210 } else {
208- $ constructorBody . = strtr ('$this->PROPERTY = $ input["NAME"] ?? null; ' . "\n" , [' PROPERTY ' => GeneratorHelper:: normalizeName ( $ member -> getName ()), 'NAME ' => $ member ->getName ()]);
211+ $ memberCode = strtr ('$input["NAME"] ' , ['NAME ' => $ member ->getName ()]);
209212 }
210213 } elseif ($ memberShape instanceof MapShape) {
211214 $ mapValueShape = $ memberShape ->getValue ()->getShape ();
212215
213216 if ($ mapValueShape instanceof StructureShape) {
214217 $ objectClass = $ this ->generate ($ mapValueShape );
215- $ constructorBody . = strtr ('$this->PROPERTY = isset($input["NAME"]) ? array_map([CLASS::class, "create"], $input["NAME"]) : null; ' . "\n" , [' PROPERTY ' => GeneratorHelper:: normalizeName ( $ member -> getName ()), 'NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
218+ $ memberCode = strtr ('array_map([CLASS::class, "create"], $input["NAME"]) ' , ['NAME ' => $ member ->getName (), 'CLASS ' => $ objectClass ->getName ()]);
216219 } else {
217- $ constructorBody . = strtr ('$this->PROPERTY = $ input["NAME"] ?? null; ' . "\n" , [' PROPERTY ' => GeneratorHelper:: normalizeName ( $ member -> getName ()), 'NAME ' => $ member ->getName ()]);
220+ $ memberCode = strtr ('$input["NAME"] ' , ['NAME ' => $ member ->getName ()]);
218221 }
219222 } else {
220- $ constructorBody .= strtr ('$this->PROPERTY = $input["NAME"] ?? null; ' . "\n" , ['PROPERTY ' => GeneratorHelper::normalizeName ($ member ->getName ()), 'NAME ' => $ member ->getName ()]);
223+ $ memberCode = strtr ('$input["NAME"] ' , ['NAME ' => $ member ->getName ()]);
224+ }
225+ if ($ member ->isRequired ()) {
226+ $ fallback = strtr ('$this->throwException(new InvalidArgument( \'Missing required field "NAME". \')) ' , ['NAME ' => $ member ->getName ()]);
227+ $ classBuilder ->addUse (InvalidArgument::class);
228+ $ needsThrowMethod = true ;
229+ } else {
230+ $ fallback = 'null ' ;
221231 }
232+ $ constructorBody .= strtr ('$this->PROPERTY = isset($input["NAME"]) ? MEMBER_CODE : FALLBACK; ' . "\n" , [
233+ 'PROPERTY ' => GeneratorHelper::normalizeName ($ member ->getName ()),
234+ 'NAME ' => $ member ->getName (),
235+ 'MEMBER_CODE ' => $ memberCode ,
236+ 'FALLBACK ' => $ fallback ,
237+ ]);
222238 }
223239 $ constructor ->setBody ($ constructorBody );
240+
241+ if ($ needsThrowMethod ) {
242+ $ throwMethod = $ classBuilder ->addMethod ('throwException ' );
243+ $ throwMethod ->setPrivate ();
244+ $ throwMethod ->addComment ('@return never ' );
245+ $ throwMethod ->addParameter ('exception ' )->setType (\Throwable::class);
246+ $ throwMethod ->setBody ('throw $exception; ' );
247+ }
224248 }
225249
226250 /**
@@ -249,12 +273,12 @@ private function addProperties(StructureShape $shape, ClassBuilder $classBuilder
249273 $ enumClassName = $ this ->enumGenerator ->generate ($ memberShape );
250274 $ classBuilder ->addUse ($ enumClassName ->getFqdn ());
251275 }
252- $ getterSetterNullable = true ;
276+ $ getterSetterNullable = null ;
253277
254278 if ($ memberShape instanceof StructureShape) {
255279 $ this ->generate ($ memberShape );
256280 } elseif ($ memberShape instanceof MapShape) {
257- $ nullable = $ getterSetterNullable = false ;
281+ $ getterSetterNullable = false ;
258282 $ mapKeyShape = $ memberShape ->getKey ()->getShape ();
259283 if ('string ' !== $ mapKeyShape ->getType ()) {
260284 throw new \RuntimeException ('Complex maps are not supported ' );
@@ -271,7 +295,7 @@ private function addProperties(StructureShape $shape, ClassBuilder $classBuilder
271295 $ classBuilder ->addUse ($ enumClassName ->getFqdn ());
272296 }
273297 } elseif ($ memberShape instanceof ListShape) {
274- $ nullable = $ getterSetterNullable = false ;
298+ $ getterSetterNullable = false ;
275299 $ memberShape ->getMember ()->getShape ();
276300
277301 if (($ memberShape = $ memberShape ->getMember ()->getShape ()) instanceof StructureShape) {
@@ -297,7 +321,10 @@ private function addProperties(StructureShape $shape, ClassBuilder $classBuilder
297321 $ deprecation = strtr ('@trigger_error(\sprintf( \'The property "NAME" of "%s" is deprecated by AWS. \', __CLASS__), E_USER_DEPRECATED); ' , ['NAME ' => $ member ->getName ()]);
298322 }
299323
300- if ($ getterSetterNullable ) {
324+ $ nullable = $ nullable ?? !$ member ->isRequired ();
325+ $ getterSetterNullable = $ getterSetterNullable ?? $ nullable ;
326+
327+ if ($ getterSetterNullable || !$ nullable ) {
301328 $ method ->setBody ($ deprecation . strtr ('
302329 return $this->PROPERTY;
303330 ' , [
@@ -311,11 +338,10 @@ private function addProperties(StructureShape $shape, ClassBuilder $classBuilder
311338 ]));
312339 }
313340
314- $ nullable = $ nullable ?? !$ member ->isRequired ();
315341 if ($ parameterType && $ parameterType !== $ returnType && (empty ($ memberClassNames ) || $ memberClassNames [0 ]->getName () !== $ parameterType )) {
316- $ method ->addComment ('@return ' . $ parameterType . ($ nullable ? '|null ' : '' ));
342+ $ method ->addComment ('@return ' . $ parameterType . ($ getterSetterNullable ? '|null ' : '' ));
317343 }
318- $ method ->setReturnNullable ($ nullable );
344+ $ method ->setReturnNullable ($ getterSetterNullable );
319345 }
320346
321347 foreach ($ forEndpointProps as $ key => $ ok ) {
0 commit comments