Browse Source

feature: [PHP8.2] Support for new standalone types (`null`, `true`, `false`) (#6623)

Grzegorz Korba 2 years ago
parent
commit
932d60f429

+ 15 - 4
src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php

@@ -42,7 +42,12 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
      * object   PHP 7.2
      * static   PHP 8.0 (return type only)
      * mixed    PHP 8.0
-     * never    PHP 8.1
+     * false    PHP 8.0 (union return type only)
+     * null     PHP 8.0 (union return type only)
+     * never    PHP 8.1 (return type only)
+     * true     PHP 8.2 (standalone type: https://wiki.php.net/rfc/true-type)
+     * false    PHP 8.2 (standalone type: https://wiki.php.net/rfc/null-false-standalone-types)
+     * null     PHP 8.2 (standalone type: https://wiki.php.net/rfc/null-false-standalone-types)
      *
      * @var array<string, true>
      */
@@ -68,12 +73,18 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
         ];
 
         if (\PHP_VERSION_ID >= 80000) {
-            $this->hints = array_merge($this->hints, ['static' => true]);
-            $this->hints = array_merge($this->hints, ['mixed' => true]);
+            $this->hints['false'] = true;
+            $this->hints['mixed'] = true;
+            $this->hints['null'] = true;
+            $this->hints['static'] = true;
         }
 
         if (\PHP_VERSION_ID >= 80100) {
-            $this->hints = array_merge($this->hints, ['never' => true]);
+            $this->hints['never'] = true;
+        }
+
+        if (\PHP_VERSION_ID >= 80200) {
+            $this->hints['true'] = true;
         }
 
         $this->functionsAnalyzer = new FunctionsAnalyzer();

+ 40 - 0
tests/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixerTest.php

@@ -172,6 +172,16 @@ function Foo(INTEGER $a) {}
             '<?php function foo(): int|bool {}',
             '<?php function foo(): INT|BOOL {}',
         ];
+
+        yield 'return type string|false' => [
+            '<?php function foo(): string|false {}',
+            '<?php function foo(): string|FALSE {}',
+        ];
+
+        yield 'return type string|null' => [
+            '<?php function foo(): string|null {}',
+            '<?php function foo(): string|NULL {}',
+        ];
     }
 
     /**
@@ -191,4 +201,34 @@ function Foo(INTEGER $a) {}
             '<?php class T { public function Foo(object $A): NEVER {die;}}',
         ];
     }
+
+    /**
+     * @dataProvider provideFix82Cases
+     *
+     * @requires PHP 8.2
+     */
+    public function testFix82(string $expected, string $input): void
+    {
+        $this->doTest($expected, $input);
+    }
+
+    public function provideFix82Cases(): iterable
+    {
+        foreach (['true', 'false', 'null'] as $type) {
+            yield sprintf('standalone type `%s` in class method', $type) => [
+                sprintf('<?php class T { public function Foo(%s $A): %1$s {return $A;}}', $type),
+                sprintf('<?php class T { public function Foo(%s $A): %1$s {return $A;}}', strtoupper($type)),
+            ];
+
+            yield sprintf('standalone type `%s` in function', $type) => [
+                sprintf('<?php function Foo(%s $A): %1$s {return $A;}', $type),
+                sprintf('<?php function Foo(%s $A): %1$s {return $A;}', strtoupper($type)),
+            ];
+
+            yield sprintf('standalone type `%s` in closure', $type) => [
+                sprintf('<?php array_filter([], function (%s $A): %1$s {return $A;});', $type),
+                sprintf('<?php array_filter([], function (%s $A): %1$s {return $A;});', strtoupper($type)),
+            ];
+        }
+    }
 }

+ 48 - 0
tests/Fixtures/Integration/misc/PHP8_2.test

@@ -28,6 +28,16 @@ class FalseNull
     ) {
     }
 
+    public function falsy(): false
+    {
+        return $this->falsy;
+    }
+
+    public function nully(): null
+    {
+        return $this->nully;
+    }
+
     public function setAB(false $a, null $b): void
     {
         $this->a = $a;
@@ -35,6 +45,10 @@ class FalseNull
     }
 }
 
+function falsyNull(null $n, false $f): null|false
+{
+}
+
 array_filter([], fn (null $n) => null === $n);
 array_filter([], fn (false $n) => false === $n);
 
@@ -48,12 +62,22 @@ class TrueType
     ) {
     }
 
+    public function havingABud(): true
+    {
+        return $this->havingABud;
+    }
+
     public function setA(true $a): void
     {
         $this->a = $a;
     }
 }
 
+function truish(true $true): true
+{
+    return $true;
+}
+
 array_filter([], fn (true $n) => true === $n);
 
 // https://wiki.php.net/rfc/constants_in_traits
@@ -84,6 +108,16 @@ class FalseNull {
     ) {
     }
 
+    public   function   falsy()   :   FALSE
+    {
+        return $this -> falsy;
+    }
+
+    public   function   nully()   :   NULL
+    {
+        return $this -> nully;
+    }
+
     public function setAB(FALSE $a, NULL $b): void
     {
         $this->a = $a;
@@ -91,6 +125,10 @@ class FalseNull {
     }
 }
 
+function   falsyNull   (NULL   $n,   FALSE   $f):   NULL|FALSE
+{
+}
+
 array_filter([], fn     (NULL     $n)     =>     NULL     ===     $n);
 array_filter([], fn     (FALSE     $n)     =>     FALSE     ===     $n);
 
@@ -103,12 +141,22 @@ class TrueType {
     ) {
     }
 
+    public   function   havingABud()   :   TRUE
+    {
+        return $this -> havingABud;
+    }
+
     public function setA(TRUE $a): void
     {
         $this->a = $a;
     }
 }
 
+function truish   (TRUE   $true)   :   TRUE
+{
+    return   $true;
+}
+
 array_filter([], fn     (TRUE     $n)     =>     TRUE     ===     $n);
 
 // https://wiki.php.net/rfc/constants_in_traits