@@ -113,7 +113,7 @@ enum: [0, 1],
113113 if ($ this ->description !== null && $ this ->description !== '' && !$ isParameter ) {
114114 $ values ['description ' ] = Helpers::cleanDocComment ($ this ->description );
115115 }
116- if ($ this ->items instanceof \ OpenAPIExtractor \ OpenApiType) {
116+ if ($ this ->items instanceof OpenApiType) {
117117 $ values ['items ' ] = $ this ->items ->toArray ();
118118 }
119119 if ($ this ->minLength !== null ) {
@@ -139,7 +139,7 @@ enum: [0, 1],
139139 }
140140 if ($ this ->properties !== null && $ this ->properties !== []) {
141141 $ values ['properties ' ] = array_combine (array_keys ($ this ->properties ),
142- array_map (static fn (OpenApiType $ property ): array |\ stdClass => $ property ->toArray (), array_values ($ this ->properties )),
142+ array_map (static fn (OpenApiType $ property ): array |stdClass => $ property ->toArray (), array_values ($ this ->properties )),
143143 );
144144 }
145145 if ($ this ->additionalProperties !== null ) {
@@ -150,13 +150,13 @@ enum: [0, 1],
150150 }
151151 }
152152 if ($ this ->oneOf !== null ) {
153- $ values ['oneOf ' ] = array_map (fn (OpenApiType $ type ): array |\ stdClass => $ type ->toArray (), $ this ->oneOf );
153+ $ values ['oneOf ' ] = array_map (fn (OpenApiType $ type ): array |stdClass => $ type ->toArray (), $ this ->oneOf );
154154 }
155155 if ($ this ->anyOf !== null ) {
156- $ values ['anyOf ' ] = array_map (fn (OpenApiType $ type ): array |\ stdClass => $ type ->toArray (), $ this ->anyOf );
156+ $ values ['anyOf ' ] = array_map (fn (OpenApiType $ type ): array |stdClass => $ type ->toArray (), $ this ->anyOf );
157157 }
158158 if ($ this ->allOf !== null ) {
159- $ values ['allOf ' ] = array_map (fn (OpenApiType $ type ): array |\ stdClass => $ type ->toArray (), $ this ->allOf );
159+ $ values ['allOf ' ] = array_map (fn (OpenApiType $ type ): array |stdClass => $ type ->toArray (), $ this ->allOf );
160160 }
161161
162162 return $ values !== [] ? $ values : new stdClass ();
@@ -184,9 +184,9 @@ public static function resolve(string $context, array $definitions, ParamTagValu
184184 items: self ::resolve ($ context . ': items ' , $ definitions , $ node ->type ),
185185 );
186186 }
187- if ($ node instanceof GenericTypeNode && ($ node ->type ->name === 'array ' || $ node ->type ->name === 'list ' || $ node ->type ->name === 'non-empty-list ' ) && count ($ node ->genericTypes ) === 1 ) {
188- if ($ node ->type ->name === 'array ' ) {
189- Logger::error ($ context , "The 'array<TYPE>' syntax for arrays is forbidden due to ambiguities. Use 'list<TYPE>' for JSON arrays or 'array<string, TYPE>' for JSON objects instead. " );
187+ if ($ node instanceof GenericTypeNode && ($ node ->type ->name === 'array ' || $ node ->type ->name === 'non-empty-array ' || $ node -> type -> name === ' list ' || $ node ->type ->name === 'non-empty-list ' ) && count ($ node ->genericTypes ) === 1 ) {
188+ if ($ node ->type ->name === 'array ' || $ node -> type -> name === ' non-empty-array ' ) {
189+ Logger::error ($ context , "The 'array<TYPE>' and 'non-empty-array<TYPE>' syntax for arrays is forbidden due to ambiguities. Use 'list<TYPE>' for JSON arrays or 'non-empty- array<string, TYPE>' for JSON objects instead. " );
190190 }
191191
192192 if ($ node ->genericTypes [0 ] instanceof IdentifierTypeNode && $ node ->genericTypes [0 ]->name === 'empty ' ) {
@@ -213,7 +213,7 @@ public static function resolve(string $context, array $definitions, ParamTagValu
213213 foreach ($ node ->items as $ item ) {
214214 $ name = $ item ->keyName instanceof ConstExprStringNode ? $ item ->keyName ->value : $ item ->keyName ->name ;
215215 $ type = self ::resolve ($ context . ': ' . $ name , $ definitions , $ item ->valueType );
216- $ comments = array_map (static fn (Comment $ comment ): ?string => preg_replace ('/^\/\/\s*/ ' , '' , $ comment ->text ), $ item ->keyName ->getAttribute (Attribute::COMMENTS ) ?? []);
216+ $ comments = array_map (static fn (Comment $ comment ): ?string => preg_replace ('/^\/\/\s*/ ' , '' , $ comment ->text ), $ item ->keyName ->getAttribute (Attribute::COMMENTS ) ?? []);
217217 if ($ comments !== []) {
218218 $ type ->description = implode ("\n" , $ comments );
219219 }
@@ -232,7 +232,11 @@ public static function resolve(string $context, array $definitions, ParamTagValu
232232 );
233233 }
234234
235- if ($ node instanceof GenericTypeNode && $ node ->type ->name === 'array ' && count ($ node ->genericTypes ) === 2 && $ node ->genericTypes [0 ] instanceof IdentifierTypeNode) {
235+ if ($ node instanceof GenericTypeNode && in_array ($ node ->type ->name , ['array ' , 'non-empty-array ' ]) && count ($ node ->genericTypes ) === 2 && $ node ->genericTypes [0 ] instanceof IdentifierTypeNode) {
236+ if ($ node ->type ->name !== 'non-empty-array ' ) {
237+ Logger::error ($ context , 'You must ensure JSON objects are not empty using the "non-empty-array" type. To allow return empty JSON objects your code must manually check if the array is empty in order to return "new \\stdClass()" and use "non-empty-array| \\stdClass" as the type. ' );
238+ }
239+
236240 $ allowedTypes = ['string ' , 'lowercase-string ' , 'non-empty-string ' , 'non-empty-lowercase-string ' ];
237241 if (in_array ($ node ->genericTypes [0 ]->name , $ allowedTypes , true )) {
238242 return new OpenApiType (
@@ -271,14 +275,14 @@ public static function resolve(string $context, array $definitions, ParamTagValu
271275
272276 $ isUnion = $ node instanceof UnionTypeNode || $ node instanceof UnionType;
273277 $ isIntersection = $ node instanceof IntersectionTypeNode || $ node instanceof IntersectionType;
274- if ($ isUnion && count ($ node ->types ) === count (array_filter ($ node ->types , fn ($ type ): bool => $ type instanceof ConstTypeNode && $ type ->constExpr instanceof ConstExprStringNode))) {
278+ if ($ isUnion && count ($ node ->types ) === count (array_filter ($ node ->types , fn ($ type ): bool => $ type instanceof ConstTypeNode && $ type ->constExpr instanceof ConstExprStringNode))) {
275279 $ values = [];
276280 /** @var ConstTypeNode $type */
277281 foreach ($ node ->types as $ type ) {
278282 $ values [] = $ type ->constExpr ->value ;
279283 }
280284
281- if (array_filter ($ values , fn (string $ value ): bool => $ value === '' ) !== []) {
285+ if (array_filter ($ values , fn (string $ value ): bool => $ value === '' ) !== []) {
282286 // Not a valid enum
283287 return new OpenApiType (
284288 context: $ context ,
@@ -292,14 +296,14 @@ public static function resolve(string $context, array $definitions, ParamTagValu
292296 enum: $ values ,
293297 );
294298 }
295- if ($ isUnion && count ($ node ->types ) === count (array_filter ($ node ->types , fn ($ type ): bool => $ type instanceof ConstTypeNode && $ type ->constExpr instanceof ConstExprIntegerNode))) {
299+ if ($ isUnion && count ($ node ->types ) === count (array_filter ($ node ->types , fn ($ type ): bool => $ type instanceof ConstTypeNode && $ type ->constExpr instanceof ConstExprIntegerNode))) {
296300 $ values = [];
297301 /** @var ConstTypeNode $type */
298302 foreach ($ node ->types as $ type ) {
299303 $ values [] = (int )$ type ->constExpr ->value ;
300304 }
301305
302- if (array_filter ($ values , fn (string $ value ): bool => $ value === '' ) !== []) {
306+ if (array_filter ($ values , fn (string $ value ): bool => $ value === '' ) !== []) {
303307 // Not a valid enum
304308 return new OpenApiType (
305309 context: $ context ,
@@ -355,7 +359,7 @@ enum: $values,
355359 return $ item ->type ;
356360 }, $ items );
357361
358- if (array_filter ($ itemTypes , static fn (?string $ type ): bool => $ type === null ) !== [] || count ($ itemTypes ) !== count (array_unique ($ itemTypes ))) {
362+ if (array_filter ($ itemTypes , static fn (?string $ type ): bool => $ type === null ) !== [] || count ($ itemTypes ) !== count (array_unique ($ itemTypes ))) {
359363 return new OpenApiType (
360364 context: $ context ,
361365 nullable: $ nullable ,
@@ -422,21 +426,21 @@ private static function mergeEnums(string $context, array $types): array {
422426 }
423427 }
424428
425- foreach (array_map (static fn (OpenApiType $ type ): ?string => $ type ->type , $ nonEnums ) as $ type ) {
429+ foreach (array_map (static fn (OpenApiType $ type ): ?string => $ type ->type , $ nonEnums ) as $ type ) {
426430 if (array_key_exists ($ type , $ enums )) {
427431 unset($ enums [$ type ]);
428432 }
429433 }
430434
431- return array_merge ($ nonEnums , array_map (static fn (string $ type ): \ OpenAPIExtractor \ OpenApiType => new OpenApiType (
435+ return array_merge ($ nonEnums , array_map (static fn (string $ type ): OpenApiType => new OpenApiType (
432436 context: $ context ,
433437 type: $ type , enum: $ enums [$ type ],
434438 ), array_keys ($ enums )));
435439 }
436440
437441 private static function resolveIdentifier (string $ context , array $ definitions , string $ name ): OpenApiType {
438442 if ($ name === 'array ' ) {
439- Logger::error ($ context , "Instead of 'array' use: \n'new stdClass()' for empty objects \n'array<string, mixed>' for non-empty objects \n'array <emtpy>' for empty lists \n'array <YourTypeHere>' for lists " );
443+ Logger::error ($ context , "Instead of 'array' use: \n'new stdClass()' for empty objects \n'non-empty- array<string, mixed>' for non-empty objects \n'list <emtpy>' for empty lists \n'list <YourTypeHere>' for lists " );
440444 }
441445 if (str_starts_with ($ name , '\\' )) {
442446 $ name = substr ($ name , 1 );
@@ -455,7 +459,7 @@ private static function resolveIdentifier(string $context, array $definitions, s
455459 'numeric ' => new OpenApiType (context: $ context , type: 'number ' ),
456460 // https://www.php.net/manual/en/language.types.float.php: Both float and double are always stored with double precision
457461 'float ' , 'double ' => new OpenApiType (context: $ context , type: 'number ' , format: 'double ' ),
458- 'mixed ' , 'empty ' , ' array ' => new OpenApiType (context: $ context , type: 'object ' ),
462+ 'mixed ' , 'empty ' => new OpenApiType (context: $ context , type: 'object ' ),
459463 'object ' , 'stdClass ' => new OpenApiType (context: $ context , type: 'object ' , additionalProperties: true ),
460464 'null ' => new OpenApiType (context: $ context , nullable: true ),
461465 default => (function () use ($ context , $ definitions , $ name ) {
0 commit comments