Skip to content

Commit 26df2fc

Browse files
authored
Merge pull request #49 from PHPCSStandards/php-8.2/account-for-true-type
PHP 8.2 | Tokenizer, File, sniffs: account for new `true` type
2 parents 2ff6414 + ef96fc6 commit 26df2fc

19 files changed

+228
-8
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ The file documents changes to the PHP_CodeSniffer project.
2929
- Squiz.Commenting.FileComment
3030
- Squiz.Commenting.InlineComment
3131
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
32+
- Added support for `true` as a stand-alone type declaration
33+
- The `File::getMethodProperties()`, `File::getMethodParameters()` and `File::getMemberProperties()` methods now all support the `true` type.
34+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
35+
- Added support for `true` as a stand-alone type to a number of sniffs
36+
- Generic.PHP.LowerCaseType
37+
- PSr12.Functions.NullableTypeDeclaration
38+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
3239
- Squiz.Commenting.FunctionComment: new ParamNameUnexpectedAmpersandPrefix error for parameters annotated as passed by reference while the parameter is not passed by reference
3340
- Thanks to Dan Wallis (@fredden) for the patch
3441
- Documentation has been added for the following sniffs:
@@ -39,6 +46,7 @@ The file documents changes to the PHP_CodeSniffer project.
3946
- Support for PHPUnit 8 and 9 to the test suite.
4047
- Test suites for external standards which run via the PHPCS native test suite can now run on PHPUnit 4-9 (was 4-7).
4148
- If any of these tests use the PHPUnit `setUp()`/`tearDown()` methods or overload the `setUp()` in the `AbstractSniffUnitTest` test case, they will need to be adjusted. See the [PR details for further information](https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/59/commits/26384ebfcc0b1c1651b0e1e40c9b6c8c22881832).
49+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
4250

4351
### Changed
4452
- Changes have been made to the way PHPCS handles invalid sniff properties being set in a custom ruleset
@@ -69,6 +77,7 @@ The file documents changes to the PHP_CodeSniffer project.
6977
- Squiz.PHP.InnerFunctions sniff no longer reports on OO methods for OO structures declared within a function or closure
7078
- Thanks to @Daimona for the patch
7179
- Runtime performance improvement for PHPCS CLI users. The improvement should be most noticeable for users on Windows.
80+
- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
7281

7382
### Removed
7483
- Removed support for installing via PEAR

src/Files/File.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,7 @@ public function getMethodParameters($stackPtr)
14791479
case T_TYPE_UNION:
14801480
case T_TYPE_INTERSECTION:
14811481
case T_FALSE:
1482+
case T_TRUE:
14821483
case T_NULL:
14831484
// Part of a type hint or default value.
14841485
if ($defaultStart === null) {
@@ -1705,6 +1706,7 @@ public function getMethodProperties($stackPtr)
17051706
T_PARENT => T_PARENT,
17061707
T_STATIC => T_STATIC,
17071708
T_FALSE => T_FALSE,
1709+
T_TRUE => T_TRUE,
17081710
T_NULL => T_NULL,
17091711
T_NAMESPACE => T_NAMESPACE,
17101712
T_NS_SEPARATOR => T_NS_SEPARATOR,
@@ -1906,6 +1908,7 @@ public function getMemberProperties($stackPtr)
19061908
T_SELF => T_SELF,
19071909
T_PARENT => T_PARENT,
19081910
T_FALSE => T_FALSE,
1911+
T_TRUE => T_TRUE,
19091912
T_NULL => T_NULL,
19101913
T_NAMESPACE => T_NAMESPACE,
19111914
T_NS_SEPARATOR => T_NS_SEPARATOR,

src/Standards/Generic/Sniffs/PHP/LowerCaseTypeSniff.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class LowerCaseTypeSniff implements Sniff
3737
'mixed' => true,
3838
'static' => true,
3939
'false' => true,
40+
'true' => true,
4041
'null' => true,
4142
'never' => true,
4243
];

src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,5 @@ function intersectionReturnTypes ($var): \Package\ClassName&\Package\Other_Class
9292

9393
$arrow = fn (int $a, string $b, bool $c, array $d, Foo\Bar $e) : int => $a * $b;
9494
$arrow = fn (Int $a, String $b, BOOL $c, Array $d, Foo\Bar $e) : Float => $a * $b;
95+
96+
$cl = function (False $a, TRUE $b, Null $c): ?True {}

src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,5 @@ function intersectionReturnTypes ($var): \Package\ClassName&\Package\Other_Class
9292

9393
$arrow = fn (int $a, string $b, bool $c, array $d, Foo\Bar $e) : int => $a * $b;
9494
$arrow = fn (int $a, string $b, bool $c, array $d, Foo\Bar $e) : float => $a * $b;
95+
96+
$cl = function (false $a, true $b, null $c): ?true {}

src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function getErrorList()
6767
82 => 2,
6868
85 => 1,
6969
94 => 5,
70+
96 => 4,
7071
];
7172

7273
}//end getErrorList()

src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ class NullableTypeDeclarationSniff implements Sniff
2727
T_SELF => true,
2828
T_PARENT => true,
2929
T_STATIC => true,
30+
T_NULL => true,
31+
T_FALSE => true,
32+
T_TRUE => true,
3033
];
3134

3235

src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,11 @@ class testInstanceOf() {
8585

8686
// PHP 8.0: static return type.
8787
function testStatic() : ? static {}
88+
89+
// PHP 8.2: nullable true/false.
90+
function fooG(): ? true {}
91+
function fooH(): ?
92+
false {}
93+
94+
// Fatal error: null cannot be marked as nullable, but that's not the concern of this sniff.
95+
function fooI(): ? null {}

src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc.fixed

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,10 @@ class testInstanceOf() {
8383

8484
// PHP 8.0: static return type.
8585
function testStatic() : ?static {}
86+
87+
// PHP 8.2: nullable true/false.
88+
function fooG(): ?true {}
89+
function fooH(): ?false {}
90+
91+
// Fatal error: null cannot be marked as nullable, but that's not the concern of this sniff.
92+
function fooI(): ?null {}

src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ protected function getErrorList()
4141
58 => 2,
4242
59 => 2,
4343
87 => 1,
44+
90 => 1,
45+
91 => 1,
46+
95 => 1,
4447
];
4548

4649
}//end getErrorList()

src/Tokenizers/PHP.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,7 @@ protected function processAdditional()
29382938
T_PARENT => T_PARENT,
29392939
T_STATIC => T_STATIC,
29402940
T_FALSE => T_FALSE,
2941+
T_TRUE => T_TRUE,
29412942
T_NULL => T_NULL,
29422943
T_NAMESPACE => T_NAMESPACE,
29432944
T_NS_SEPARATOR => T_NS_SEPARATOR,

tests/Core/File/GetMemberPropertiesTest.inc

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,11 @@ $anon = class() {
217217
public ?int|float $unionTypesNullable;
218218

219219
/* testPHP8PseudoTypeNull */
220-
// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
220+
// PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
221221
public null $pseudoTypeNull;
222222

223223
/* testPHP8PseudoTypeFalse */
224-
// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
224+
// PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
225225
public false $pseudoTypeFalse;
226226

227227
/* testPHP8PseudoTypeFalseAndBool */
@@ -298,7 +298,22 @@ $anon = class() {
298298
// Intentional fatal error - types which are not allowed for intersection type, but that's not the concern of the method.
299299
public int&string $illegalIntersectionType;
300300

301-
/* testPHP81NulltableIntersectionType */
301+
/* testPHP81NullableIntersectionType */
302302
// Intentional fatal error - nullability is not allowed with intersection type, but that's not the concern of the method.
303303
public ?Foo&Bar $nullableIntersectionType;
304304
};
305+
306+
$anon = class() {
307+
/* testPHP82PseudoTypeTrue */
308+
public true $pseudoTypeTrue;
309+
310+
/* testPHP82NullablePseudoTypeTrue */
311+
static protected ?true $pseudoTypeNullableTrue;
312+
313+
/* testPHP82PseudoTypeTrueInUnion */
314+
private int|string|true $pseudoTypeTrueInUnion;
315+
316+
/* testPHP82PseudoTypeFalseAndTrue */
317+
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
318+
readonly true|FALSE $pseudoTypeFalseAndTrue;
319+
};

tests/Core/File/GetMemberPropertiesTest.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ public function dataGetMemberProperties()
795795
],
796796
],
797797
[
798-
'/* testPHP81NulltableIntersectionType */',
798+
'/* testPHP81NullableIntersectionType */',
799799
[
800800
'scope' => 'public',
801801
'scope_specified' => true,
@@ -805,6 +805,51 @@ public function dataGetMemberProperties()
805805
'nullable_type' => true,
806806
],
807807
],
808+
[
809+
'/* testPHP82PseudoTypeTrue */',
810+
[
811+
'scope' => 'public',
812+
'scope_specified' => true,
813+
'is_static' => false,
814+
'is_readonly' => false,
815+
'type' => 'true',
816+
'nullable_type' => false,
817+
],
818+
],
819+
[
820+
'/* testPHP82NullablePseudoTypeTrue */',
821+
[
822+
'scope' => 'protected',
823+
'scope_specified' => true,
824+
'is_static' => true,
825+
'is_readonly' => false,
826+
'type' => '?true',
827+
'nullable_type' => true,
828+
],
829+
],
830+
[
831+
'/* testPHP82PseudoTypeTrueInUnion */',
832+
[
833+
'scope' => 'private',
834+
'scope_specified' => true,
835+
'is_static' => false,
836+
'is_readonly' => false,
837+
'type' => 'int|string|true',
838+
'nullable_type' => false,
839+
],
840+
],
841+
[
842+
'/* testPHP82PseudoTypeFalseAndTrue */',
843+
[
844+
'scope' => 'public',
845+
'scope_specified' => false,
846+
'is_static' => false,
847+
'is_readonly' => true,
848+
'type' => 'true|FALSE',
849+
'nullable_type' => false,
850+
],
851+
],
852+
808853
];
809854

810855
}//end dataGetMemberProperties()

tests/Core/File/GetMethodParametersTest.inc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ function unionTypesAllPseudoTypes(false|mixed|self|parent|iterable|Resource $var
6666
$closure = function (?int|float $number) {};
6767

6868
/* testPHP8PseudoTypeNull */
69-
// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
69+
// PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
7070
function pseudoTypeNull(null $var = null) {}
7171

7272
/* testPHP8PseudoTypeFalse */
73-
// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
73+
// PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
7474
function pseudoTypeFalse(false $var = false) {}
7575

7676
/* testPHP8PseudoTypeFalseAndBool */
@@ -167,3 +167,10 @@ $closure = function (string&int $numeric_string) {};
167167
/* testPHP81NullableIntersectionTypes */
168168
// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method.
169169
$closure = function (?Foo&Bar $object) {};
170+
171+
/* testPHP82PseudoTypeTrue */
172+
function pseudoTypeTrue(?true $var = true) {}
173+
174+
/* testPHP82PseudoTypeFalseAndTrue */
175+
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
176+
function pseudoTypeFalseAndTrue(true|false $var = true) {}

tests/Core/File/GetMethodParametersTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,54 @@ public function testPHP81NullableIntersectionTypes()
11661166
}//end testPHP81NullableIntersectionTypes()
11671167

11681168

1169+
/**
1170+
* Verify recognition of PHP 8.2 stand-alone `true` type.
1171+
*
1172+
* @return void
1173+
*/
1174+
public function testPHP82PseudoTypeTrue()
1175+
{
1176+
$expected = [];
1177+
$expected[0] = [
1178+
'name' => '$var',
1179+
'content' => '?true $var = true',
1180+
'default' => 'true',
1181+
'has_attributes' => false,
1182+
'pass_by_reference' => false,
1183+
'variable_length' => false,
1184+
'type_hint' => '?true',
1185+
'nullable_type' => true,
1186+
];
1187+
1188+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
1189+
1190+
}//end testPHP82PseudoTypeTrue()
1191+
1192+
1193+
/**
1194+
* Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true.
1195+
*
1196+
* @return void
1197+
*/
1198+
public function testPHP82PseudoTypeFalseAndTrue()
1199+
{
1200+
$expected = [];
1201+
$expected[0] = [
1202+
'name' => '$var',
1203+
'content' => 'true|false $var = true',
1204+
'default' => 'true',
1205+
'has_attributes' => false,
1206+
'pass_by_reference' => false,
1207+
'variable_length' => false,
1208+
'type_hint' => 'true|false',
1209+
'nullable_type' => false,
1210+
];
1211+
1212+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
1213+
1214+
}//end testPHP82PseudoTypeFalseAndTrue()
1215+
1216+
11691217
/**
11701218
* Test helper.
11711219
*

tests/Core/File/GetMethodPropertiesTest.inc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ function unionTypesAllPseudoTypes($var) : false|MIXED|self|parent|static|iterabl
102102
$closure = function () use($a) :?int|float {};
103103

104104
/* testPHP8PseudoTypeNull */
105-
// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
105+
// PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method.
106106
function pseudoTypeNull(): null {}
107107

108108
/* testPHP8PseudoTypeFalse */
109-
// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
109+
// PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method.
110110
function pseudoTypeFalse(): false {}
111111

112112
/* testPHP8PseudoTypeFalseAndBool */
@@ -150,3 +150,10 @@ $closure = function (): string&int {};
150150
/* testPHP81NullableIntersectionTypes */
151151
// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method.
152152
$closure = function (): ?Foo&Bar {};
153+
154+
/* testPHP82PseudoTypeTrue */
155+
function pseudoTypeTrue(): ?true {}
156+
157+
/* testPHP82PseudoTypeFalseAndTrue */
158+
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
159+
function pseudoTypeFalseAndTrue(): true|false {}

tests/Core/File/GetMethodPropertiesTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,52 @@ public function testPHP81NullableIntersectionTypes()
889889
}//end testPHP81NullableIntersectionTypes()
890890

891891

892+
/**
893+
* Verify recognition of PHP 8.2 stand-alone `true` type.
894+
*
895+
* @return void
896+
*/
897+
public function testPHP82PseudoTypeTrue()
898+
{
899+
$expected = [
900+
'scope' => 'public',
901+
'scope_specified' => false,
902+
'return_type' => '?true',
903+
'nullable_return_type' => true,
904+
'is_abstract' => false,
905+
'is_final' => false,
906+
'is_static' => false,
907+
'has_body' => true,
908+
];
909+
910+
$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);
911+
912+
}//end testPHP82PseudoTypeTrue()
913+
914+
915+
/**
916+
* Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true.
917+
*
918+
* @return void
919+
*/
920+
public function testPHP82PseudoTypeFalseAndTrue()
921+
{
922+
$expected = [
923+
'scope' => 'public',
924+
'scope_specified' => false,
925+
'return_type' => 'true|false',
926+
'nullable_return_type' => false,
927+
'is_abstract' => false,
928+
'is_final' => false,
929+
'is_static' => false,
930+
'has_body' => true,
931+
];
932+
933+
$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);
934+
935+
}//end testPHP82PseudoTypeFalseAndTrue()
936+
937+
892938
/**
893939
* Test helper.
894940
*

0 commit comments

Comments
 (0)