2
2
3
3
namespace SlevomatCodingStandard \Helpers ;
4
4
5
+ use InvalidArgumentException ;
5
6
use PHP_CodeSniffer \Files \File ;
6
7
use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprFloatNode ;
7
8
use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprIntegerNode ;
21
22
use PHPStan \PhpDocParser \Ast \Type \TypeNode ;
22
23
use PHPStan \PhpDocParser \Ast \Type \UnionTypeNode ;
23
24
use function count ;
25
+ use function get_class ;
24
26
use function in_array ;
27
+ use function preg_match ;
28
+ use function sprintf ;
25
29
use function strtolower ;
26
30
27
31
/**
@@ -291,7 +295,16 @@ public static function getTypeHintFromOneType(
291
295
return 'array ' ;
292
296
}
293
297
294
- return $ genericName ;
298
+ if ((bool ) preg_match (
299
+ '/^ \\\\?[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(?: \\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/ ' ,
300
+ $ genericName ,
301
+ )) {
302
+ return $ genericName ;
303
+ }
304
+
305
+ throw new InvalidArgumentException (
306
+ sprintf ('Invalid type "%1$s" of class %2$s given ' , $ genericName , get_class ($ typeNode )),
307
+ );
295
308
}
296
309
297
310
if ($ typeNode instanceof IdentifierTypeNode) {
@@ -303,19 +316,61 @@ public static function getTypeHintFromOneType(
303
316
return $ enableUnionTypeHint || $ enableStandaloneNullTrueFalseTypeHints ? 'false ' : 'bool ' ;
304
317
}
305
318
306
- if (in_array (strtolower ($ typeNode ->name ), ['positive-int ' , 'negative-int ' ], true )) {
319
+ if (in_array (
320
+ strtolower ($ typeNode ->name ),
321
+ ['positive-int ' , 'non-positive-int ' , 'negative-int ' , 'non-negative-int ' , 'literal-int ' , 'int-mask ' ],
322
+ true ,
323
+ )) {
307
324
return 'int ' ;
308
325
}
309
326
310
327
if (in_array (
311
328
strtolower ($ typeNode ->name ),
312
- ['class-string ' , ' trait-string ' , ' callable-string ' , 'numeric-string ' , ' non-empty-string ' , ' non-falsy-string ' , ' literal -string ' ],
329
+ ['callable-array ' , 'callable -string ' ],
313
330
true ,
314
331
)) {
332
+ return 'callable ' ;
333
+ }
334
+
335
+ // see https://psalm.dev/docs/annotating_code/type_syntax/scalar_types/#class-string-interface-string
336
+ if ((bool ) preg_match ('/-string$/i ' , $ typeNode ->name )) {
315
337
return 'string ' ;
316
338
}
317
339
318
- return $ typeNode ->name ;
340
+ // here when used literally e.g. as type non-empty-array|null
341
+ if (in_array (
342
+ strtolower ($ typeNode ->name ),
343
+ ['non-empty-array ' , 'list ' , 'non-empty-list ' ],
344
+ true ,
345
+ )) {
346
+ return 'array ' ;
347
+ }
348
+
349
+ if (strtolower ($ typeNode ->name ) === 'array-key ' ) {
350
+ return $ enableUnionTypeHint ? 'int|string ' : 'mixed ' ;
351
+ }
352
+
353
+ if (TypeHintHelper::isNeverTypeHint (strtolower ($ typeNode ->name ))) {
354
+ // don't set a type hint at all if it's not supported by the PHP version yet
355
+ return $ enableStandaloneNullTrueFalseTypeHints ? 'never ' : 'never-returns ' ;
356
+ }
357
+
358
+ if (strtolower ($ typeNode ->name ) === 'static ' ) {
359
+ // don't set a type hint at all (instead of "self") if it's not supported by the PHP version yet
360
+ // use $this to fake it
361
+ return $ enableUnionTypeHint ? 'static ' : '$this ' ;
362
+ }
363
+
364
+ if ((bool ) preg_match (
365
+ '/^ \\\\?[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(?: \\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/ ' ,
366
+ $ typeNode ->name ,
367
+ )) {
368
+ return $ typeNode ->name ;
369
+ }
370
+
371
+ throw new InvalidArgumentException (
372
+ sprintf ('Invalid type "%1$s" of class %2$s given ' , $ typeNode ->name , get_class ($ typeNode )),
373
+ );
319
374
}
320
375
321
376
if ($ typeNode instanceof CallableTypeNode) {
@@ -334,6 +389,11 @@ public static function getTypeHintFromOneType(
334
389
return 'object ' ;
335
390
}
336
391
392
+ // $this and self are not strictly equal
393
+ if ($ typeNode instanceof ThisTypeNode) {
394
+ return (string ) $ typeNode ;
395
+ }
396
+
337
397
if ($ typeNode instanceof ConstTypeNode) {
338
398
if ($ typeNode ->constExpr instanceof ConstExprIntegerNode) {
339
399
return 'int ' ;
@@ -348,7 +408,16 @@ public static function getTypeHintFromOneType(
348
408
}
349
409
}
350
410
351
- return (string ) $ typeNode ;
411
+ if ((bool ) preg_match (
412
+ '/^ \\\\?[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(?: \\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/ ' ,
413
+ (string ) $ typeNode ,
414
+ )) {
415
+ return (string ) $ typeNode ;
416
+ }
417
+
418
+ throw new InvalidArgumentException (
419
+ sprintf ('Invalid type "%1$s" of class %2$s given ' , (string ) $ typeNode , get_class ($ typeNode )),
420
+ );
352
421
}
353
422
354
423
/**
0 commit comments