77use AsyncAws \CodeGenerator \Definition \DocumentShape ;
88use AsyncAws \CodeGenerator \Definition \ListShape ;
99use AsyncAws \CodeGenerator \Definition \MapShape ;
10+ use AsyncAws \CodeGenerator \Definition \ObjectShape ;
1011use AsyncAws \CodeGenerator \Definition \Shape ;
1112use AsyncAws \CodeGenerator \Definition \StructureShape ;
13+ use AsyncAws \CodeGenerator \Definition \UnionShape ;
1214use AsyncAws \CodeGenerator \Generator \Naming \ClassName ;
1315use AsyncAws \CodeGenerator \Generator \Naming \NamespaceRegistry ;
1416
@@ -39,30 +41,116 @@ public function __construct(NamespaceRegistry $namespaceRegistry)
3941 *
4042 * @return array{string, ClassName[]} [docblock representation, ClassName related]
4143 */
42- public function generateDocblock (StructureShape $ shape , ClassName $ shapeClassName , bool $ alternateClass = true , bool $ allNullable = false , bool $ isObject = false , array $ extra = []): array
44+ public function generateDocblock (ObjectShape $ shape , ClassName $ shapeClassName , bool $ alternateClass = true , bool $ allNullable = false , bool $ isObject = false , array $ extra = []): array
4345 {
44- $ classNames = [];
46+ if ($ shape instanceof StructureShape) {
47+ [$ definitions , $ classNames ] = $ this ->getDefinitionForStructure ($ shape , $ allNullable , $ isObject , $ extra );
48+ } elseif ($ shape instanceof UnionShape) {
49+ [$ definitions , $ classNames ] = $ this ->getDefinitionForUnion ($ shape , $ allNullable , $ isObject , $ extra );
50+ } else {
51+ throw new \RuntimeException ('Unsupported shape type: ' . \get_class ($ shape ));
52+ }
53+
4554 if ($ alternateClass ) {
4655 $ classNames [] = $ shapeClassName ;
56+ $ definitions [] = $ shapeClassName ->getName ();
57+ }
58+
59+ $ body = '@param ' . implode ('| ' , $ definitions ) . ' $input ' ;
60+
61+ return [$ body , array_unique ($ classNames , \SORT_REGULAR )];
62+ }
63+
64+ /**
65+ * Return php type information for the given shape.
66+ *
67+ * @return array{string, string, ClassName[]} [typeHint value, docblock representation, ClassName related]
68+ */
69+ public function getPhpType (Shape $ shape ): array
70+ {
71+ $ memberClassNames = [];
72+ if ($ shape instanceof ObjectShape) {
73+ $ memberClassNames [] = $ className = $ this ->namespaceRegistry ->getObject ($ shape );
74+
75+ return [$ className ->getFqdn (), $ className ->getName (), $ memberClassNames ];
76+ }
77+
78+ if ($ shape instanceof ListShape) {
79+ $ listMemberShape = $ shape ->getMember ()->getShape ();
80+ [$ type , $ doc , $ memberClassNames ] = $ this ->getPhpType ($ listMemberShape );
81+ if (str_ends_with ($ doc , '::* ' )) {
82+ $ doc = "list< $ doc> " ;
83+ } else {
84+ $ doc .= '[] ' ;
85+ }
86+
87+ return ['array ' , $ doc , $ memberClassNames ];
4788 }
89+
90+ if ($ shape instanceof MapShape) {
91+ $ mapKeyShape = $ shape ->getKey ()->getShape ();
92+ $ mapValueShape = $ shape ->getValue ()->getShape ();
93+ [$ type , $ doc , $ memberClassNames ] = $ this ->getPhpType ($ mapValueShape );
94+ if (!empty ($ mapKeyShape ->getEnum ())) {
95+ $ memberClassNames [] = $ memberClassName = $ this ->namespaceRegistry ->getEnum ($ mapKeyShape );
96+ $ doc = "array< {$ memberClassName ->getName ()}::*, $ doc> " ;
97+ } else {
98+ $ doc = "array<string, $ doc> " ;
99+ }
100+
101+ return ['array ' , $ doc , $ memberClassNames ];
102+ }
103+
104+ if ($ shape instanceof DocumentShape) {
105+ return ['bool|string|int|float|array|null ' , 'bool|string|int|float|list<mixed>|array<string, mixed>|null ' , []];
106+ }
107+
108+ $ type = $ doc = $ this ->getNativePhpType ($ shape ->getType ());
109+ if (!empty ($ shape ->getEnum ())) {
110+ $ memberClassNames [] = $ memberClassName = $ this ->namespaceRegistry ->getEnum ($ shape );
111+
112+ $ doc = $ memberClassName ->getName () . '::* ' ;
113+ }
114+
115+ return [$ type , $ doc , $ memberClassNames ];
116+ }
117+
118+ private function getDefinitionForUnion (UnionShape $ shape , bool $ allNullable , bool $ isObject , array $ extra ): array
119+ {
120+ $ definitions = [];
121+ $ classNames = [];
122+ foreach ($ shape ->getChildren () as $ child ) {
123+ [$ childDefinitions , $ childClassNames ] = $ this ->getDefinitionForStructure ($ child , $ allNullable , $ isObject , $ extra );
124+ $ definitions = array_merge ($ definitions , $ childDefinitions );
125+ $ classNames = array_merge ($ classNames , $ childClassNames );
126+ }
127+
128+ $ definitions = array_unique ($ definitions );
129+
130+ return [$ definitions , $ classNames ];
131+ }
132+
133+ private function getDefinitionForStructure (StructureShape $ shape , bool $ allNullable , bool $ isObject , array $ extra ): array
134+ {
135+ $ classNames = [];
48136 if (empty ($ shape ->getMembers ()) && empty ($ extra )) {
49137 // No input array
50- return [' @param array ' . ( $ alternateClass ? ' | ' . $ shapeClassName -> getName () : '' ) . ' $input ' , $ classNames ];
138+ return [[ ' array '] , $ classNames ];
51139 }
52140
53- $ body = ['@param array{ ' ];
141+ $ body = ['array{ ' ];
54142 foreach ($ shape ->getMembers () as $ member ) {
55143 $ nullable = !$ member ->isRequired ();
56144 $ memberShape = $ member ->getShape ();
57145
58- if ($ memberShape instanceof StructureShape ) {
146+ if ($ memberShape instanceof ObjectShape ) {
59147 $ classNames [] = $ className = $ this ->namespaceRegistry ->getObject ($ memberShape );
60148 $ param = $ className ->getName () . '|array ' ;
61149 } elseif ($ memberShape instanceof ListShape) {
62150 $ listMemberShape = $ memberShape ->getMember ()->getShape ();
63151
64152 // is the list item an object?
65- if ($ listMemberShape instanceof StructureShape ) {
153+ if ($ listMemberShape instanceof ObjectShape ) {
66154 $ classNames [] = $ className = $ this ->namespaceRegistry ->getObject ($ listMemberShape );
67155 $ param = 'array< ' . $ className ->getName () . '|array> ' ;
68156 } elseif (!empty ($ listMemberShape ->getEnum ())) {
@@ -75,7 +163,7 @@ public function generateDocblock(StructureShape $shape, ClassName $shapeClassNam
75163 $ mapValueShape = $ memberShape ->getValue ()->getShape ();
76164
77165 // is the map item an object?
78- if ($ mapValueShape instanceof StructureShape ) {
166+ if ($ mapValueShape instanceof ObjectShape ) {
79167 $ classNames [] = $ className = $ this ->namespaceRegistry ->getObject ($ mapValueShape );
80168 $ param = $ className ->getName () . '|array ' ;
81169 } elseif (!empty ($ mapValueShape ->getEnum ())) {
@@ -125,64 +213,11 @@ public function generateDocblock(StructureShape $shape, ClassName $shapeClassNam
125213 $ body [] = \sprintf (' %s: %s, ' , $ phpdocMemberName , $ param );
126214 }
127215 }
128- $ body = array_merge ($ body , $ extra );
129- $ body [] = '} ' . ($ alternateClass ? '| ' . $ shapeClassName ->getName () : '' ) . ' $input ' ;
130216
131- return [implode ("\n" , $ body ), $ classNames ];
132- }
133-
134- /**
135- * Return php type information for the given shape.
136- *
137- * @return array{string, string, ClassName[]} [typeHint value, docblock representation, ClassName related]
138- */
139- public function getPhpType (Shape $ shape ): array
140- {
141- $ memberClassNames = [];
142- if ($ shape instanceof StructureShape) {
143- $ memberClassNames [] = $ className = $ this ->namespaceRegistry ->getObject ($ shape );
144-
145- return [$ className ->getFqdn (), $ className ->getName (), $ memberClassNames ];
146- }
147-
148- if ($ shape instanceof ListShape) {
149- $ listMemberShape = $ shape ->getMember ()->getShape ();
150- [$ type , $ doc , $ memberClassNames ] = $ this ->getPhpType ($ listMemberShape );
151- if ('::* ' === substr ($ doc , -3 )) {
152- $ doc = "list< $ doc> " ;
153- } else {
154- $ doc .= '[] ' ;
155- }
156-
157- return ['array ' , $ doc , $ memberClassNames ];
158- }
159-
160- if ($ shape instanceof MapShape) {
161- $ mapKeyShape = $ shape ->getKey ()->getShape ();
162- $ mapValueShape = $ shape ->getValue ()->getShape ();
163- [$ type , $ doc , $ memberClassNames ] = $ this ->getPhpType ($ mapValueShape );
164- if (!empty ($ mapKeyShape ->getEnum ())) {
165- $ memberClassNames [] = $ memberClassName = $ this ->namespaceRegistry ->getEnum ($ mapKeyShape );
166- $ doc = "array< {$ memberClassName ->getName ()}::*, $ doc> " ;
167- } else {
168- $ doc = "array<string, $ doc> " ;
169- }
170-
171- return ['array ' , $ doc , $ memberClassNames ];
172- }
173-
174- if ($ shape instanceof DocumentShape) {
175- return ['bool|string|int|float|array|null ' , 'bool|string|int|float|list<mixed>|array<string, mixed>|null ' , []];
176- }
177-
178- $ type = $ doc = $ this ->getNativePhpType ($ shape ->getType ());
179- if (!empty ($ shape ->getEnum ())) {
180- $ memberClassNames [] = $ memberClassName = $ this ->namespaceRegistry ->getEnum ($ shape );
181-
182- $ doc = $ memberClassName ->getName () . '::* ' ;
183- }
217+ $ body = array_merge ($ body , $ extra );
218+ $ body [] = '} ' ;
184219
185- return [$ type , $ doc , $ memberClassNames ];
220+ return [[ implode ( "\n" , $ body )] , $ classNames ];
186221 }
187222
188223 private function getNativePhpType (string $ parameterType ): string
0 commit comments