44
55namespace AsyncAws \CodeGenerator \Generator ;
66
7+ use AsyncAws \CodeGenerator \Definition \ListShape ;
8+ use AsyncAws \CodeGenerator \Definition \MapShape ;
79use AsyncAws \CodeGenerator \Definition \Shape ;
10+ use AsyncAws \CodeGenerator \Definition \StructureShape ;
811use AsyncAws \CodeGenerator \Generator \Naming \ClassName ;
912use AsyncAws \CodeGenerator \Generator \Naming \NamespaceRegistry ;
1013use AsyncAws \CodeGenerator \Generator \PhpGenerator \ClassRegistry ;
1922 */
2023class EnumGenerator
2124{
25+ public const UNKNOWN_VALUE = 'UNKNOWN_TO_SDK ' ;
26+
2227 /**
2328 * @var ClassRegistry
2429 */
@@ -34,10 +39,21 @@ class EnumGenerator
3439 */
3540 private $ generated = [];
3641
37- public function __construct (ClassRegistry $ classRegistry , NamespaceRegistry $ namespaceRegistry )
42+ /**
43+ * @var list<string>
44+ */
45+ private $ managedMethods ;
46+
47+ /**
48+ * @var array<string, bool>|null
49+ */
50+ private $ usedShapedOutput ;
51+
52+ public function __construct (ClassRegistry $ classRegistry , NamespaceRegistry $ namespaceRegistry , array $ managedMethods )
3853 {
3954 $ this ->classRegistry = $ classRegistry ;
4055 $ this ->namespaceRegistry = $ namespaceRegistry ;
56+ $ this ->managedMethods = $ managedMethods ;
4157 }
4258
4359 /**
@@ -63,13 +79,19 @@ public function generate(Shape $shape): ClassName
6379 }
6480 ksort ($ consts );
6581 $ availableConsts = [];
82+
6683 foreach ($ consts as $ constName => $ constValue ) {
6784 $ classBuilder ->addConstant ($ constName , $ constValue )->setVisibility (Visibility::Public);
6885 $ availableConsts [] = 'self:: ' . $ constName . ' => true ' ;
6986 }
87+
88+ if ($ this ->isShapeUsedOutput ($ shape )) {
89+ $ classBuilder ->addConstant (self ::UNKNOWN_VALUE , self ::UNKNOWN_VALUE )->setVisibility (Visibility::Public);
90+ }
7091 $ classBuilder ->addMethod ('exists ' )
7192 ->setStatic (true )
7293 ->setReturnType ('bool ' )
94+ ->setComment ('@psalm-assert-if-true self::* $value ' )
7395 ->setBody ('
7496 return isset([
7597 ' . implode (", \n" , $ availableConsts ) . '
@@ -103,4 +125,49 @@ public static function canonicalizeName(string $name): string
103125
104126 return $ name ;
105127 }
128+
129+ private function isShapeUsedOutput (Shape $ shape ): bool
130+ {
131+ if (null === $ this ->usedShapedOutput ) {
132+ $ service = $ shape ->getService ();
133+ $ walk = function (?Shape $ shape ) use (&$ walk ) {
134+ if (null === $ shape ) {
135+ return ;
136+ }
137+ if (isset ($ this ->usedShapedOutput [$ shape ->getName ()])) {
138+ // Node already visited
139+ return ;
140+ }
141+
142+ $ this ->usedShapedOutput [$ shape ->getName ()] = true ;
143+ if ($ shape instanceof StructureShape) {
144+ foreach ($ shape ->getMembers () as $ member ) {
145+ $ walk ($ member ->getShape ());
146+ }
147+ } elseif ($ shape instanceof ListShape) {
148+ $ walk ($ shape ->getMember ()->getShape ());
149+ } elseif ($ shape instanceof MapShape) {
150+ $ walk ($ shape ->getKey ()->getShape ());
151+ $ walk ($ shape ->getValue ()->getShape ());
152+ }
153+ };
154+
155+ foreach ($ this ->managedMethods as $ method ) {
156+ if (null !== $ operation = $ service ->getOperation ($ method )) {
157+ $ walk ($ operation ->getOutput ());
158+ foreach ($ operation ->getErrors () as $ error ) {
159+ $ walk ($ error );
160+ }
161+ }
162+ if (null !== $ waiter = $ service ->getWaiter ($ method )) {
163+ $ walk ($ waiter ->getOperation ()->getOutput ());
164+ foreach ($ waiter ->getOperation ()->getErrors () as $ error ) {
165+ $ walk ($ error );
166+ }
167+ }
168+ }
169+ }
170+
171+ return $ this ->usedShapedOutput [$ shape ->getName ()] ?? false ;
172+ }
106173}
0 commit comments