Skip to content

Commit a342627

Browse files
authored
Merge pull request #702 from PHPCSStandards/feature/typestring-improve-handling-fqn-true-false-null
TypeString: improve handling of FQN `true`/`false`/`null`
2 parents 0c75908 + 1ed1033 commit a342627

File tree

6 files changed

+119
-3
lines changed

6 files changed

+119
-3
lines changed

PHPCSUtils/Utils/TypeString.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,16 @@ public static function isKeyword($type)
129129
return false;
130130
}
131131

132-
$typeLC = \strtolower(\trim($type));
132+
$typeLC = \strtolower(\ltrim(\trim($type), '\\'));
133133
return isset(self::$keywordTypes[$typeLC]);
134134
}
135135

136136
/**
137137
* Normalize the case for a single type.
138138
*
139139
* - Types which are recognized PHP "keyword" types will be returned in lowercase.
140+
* - Types which are recognized PHP "keyword" types and can be fully qualified (true/false/null)
141+
* will be returned as unqualified.
140142
* - Class/Interface/Enum names will be returned in their original case.
141143
*
142144
* @since 1.1.0
@@ -152,7 +154,7 @@ public static function normalizeCase($type)
152154
}
153155

154156
if (self::isKeyword($type)) {
155-
return \strtolower($type);
157+
return \strtolower(\ltrim($type, '\\'));
156158
}
157159

158160
return $type;
@@ -218,7 +220,7 @@ public static function isNullable($typeString)
218220

219221
// Check for nullable union type.
220222
$matched = \preg_match(
221-
'`(?<before>^|[^|&(?\s]+\s*\|)\s*null\s*(?<after>\|\s*[^|&)?\s]+|$)`i',
223+
'`(?<before>^|[^|&(?\s]+\s*\|)\s*[\\\\]?null\s*(?<after>\|\s*[^|&)?\s]+|$)`i',
222224
$typeString,
223225
$matches
224226
);

Tests/Utils/TypeString/FilterTypesTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,14 @@ public static function dataFilterTypes()
290290
'\Fully\Qualified' => '\Fully\Qualified',
291291
],
292292
],
293+
'keyed array containing FQN and uppercase true/false/null keywords' => [
294+
'keywords' => [
295+
'\FALSE' => '\FALSE',
296+
'\NULL' => '\NULL',
297+
'\TRUE' => '\TRUE',
298+
],
299+
'oonames' => [],
300+
],
293301
'keyed array containing both keywords and oo names, keys not the same as values' => [
294302
'keywords' => [
295303
'float' => 'callable',

Tests/Utils/TypeString/IsKeywordTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ public static function dataIsKeywordValid()
117117
];
118118
}
119119

120+
$data['true: fully qualified'] = ['type' => '\true'];
121+
$data['false: fully qualified'] = ['type' => '\false'];
122+
$data['null: fully qualified'] = ['type' => '\null'];
123+
$data['true: fully qualified, uppercase'] = ['type' => '\TRUE'];
124+
$data['false: fully qualified, uppercase'] = ['type' => '\FALSE'];
125+
$data['null: fully qualified, uppercase'] = ['type' => '\NULL'];
126+
120127
return $data;
121128
}
122129

Tests/Utils/TypeString/IsTypeTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,16 @@ public static function dataTypeStrings()
319319
'dnf' => false,
320320
],
321321
],
322+
'nullable union type: \true|\null (FQN)' => [
323+
'type' => '\true|\null',
324+
'expected' => [
325+
'singular' => false,
326+
'nullable' => true,
327+
'union' => true,
328+
'intersection' => false,
329+
'dnf' => false,
330+
],
331+
],
322332

323333
'intersection type: UnqualifiedName&Package\Partially&\Vendor\FullyQualified&namespace\Relative\Name' => [
324334
'type' => 'UnqualifiedName&Package\Partially&\Vendor\FullyQualified&namespace\Relative\Name',
@@ -391,6 +401,36 @@ public static function dataTypeStrings()
391401
'dnf' => true,
392402
],
393403
],
404+
'DNF type: FQN null at end' => [
405+
'type' => '(Foo&Bar)|\null',
406+
'expected' => [
407+
'singular' => false,
408+
'nullable' => true,
409+
'union' => false,
410+
'intersection' => false,
411+
'dnf' => true,
412+
],
413+
],
414+
'DNF type: FQN null in the middle' => [
415+
'type' => '(Foo&Bar)|\null|(Baz&Countable)',
416+
'expected' => [
417+
'singular' => false,
418+
'nullable' => true,
419+
'union' => false,
420+
'intersection' => false,
421+
'dnf' => true,
422+
],
423+
],
424+
'DNF type: FQN null at start and whitespace rich' => [
425+
'type' => ' \null | ( Foo & Bar & \Baz )',
426+
'expected' => [
427+
'singular' => false,
428+
'nullable' => true,
429+
'union' => false,
430+
'intersection' => false,
431+
'dnf' => true,
432+
],
433+
],
394434
];
395435
}
396436

Tests/Utils/TypeString/NormalizeCaseTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,31 @@ public static function dataNormalizeCase()
135135
];
136136
}
137137

138+
$data['true: fully qualified'] = [
139+
'type' => '\true',
140+
'expected' => 'true',
141+
];
142+
$data['false: fully qualified'] = [
143+
'type' => '\false',
144+
'expected' => 'false',
145+
];
146+
$data['null: fully qualified'] = [
147+
'type' => '\null',
148+
'expected' => 'null',
149+
];
150+
$data['true: fully qualified, uppercase'] = [
151+
'type' => '\TRUE',
152+
'expected' => 'true',
153+
];
154+
$data['false: fully qualified, uppercase'] = [
155+
'type' => '\FALSE',
156+
'expected' => 'false',
157+
];
158+
$data['null: fully qualified, uppercase'] = [
159+
'type' => '\NULL',
160+
'expected' => 'null',
161+
];
162+
138163
$data['Classname: UnqualifiedName'] = [
139164
'type' => 'UnqualifiedName',
140165
'expected' => 'UnqualifiedName',

Tests/Utils/TypeString/ToArrayTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,23 @@ public static function dataToArrayNormalized()
372372
'void' => 'void',
373373
],
374374
],
375+
'union type: \true|\false|\null (FQN)' => [
376+
'type' => '\true|\false|\null',
377+
'expected' => [
378+
'true' => 'true',
379+
'false' => 'false',
380+
'null' => 'null',
381+
],
382+
],
383+
'union type: \TRUE|\FALSE|\NULL (FQN + uppercase)' => [
384+
'type' => '\TRUE|\FALSE|\NULL',
385+
'expected' => [
386+
'true' => 'true',
387+
'false' => 'false',
388+
'null' => 'null',
389+
],
390+
],
391+
375392
'DNF type: keywords in mixed case' => [
376393
'type' => 'FALSE|(B&A)|Null',
377394
'expected' => [
@@ -423,6 +440,23 @@ public static function dataToArrayNotNormalized()
423440
'void' => 'void',
424441
],
425442
],
443+
'union type: \true|\false|\null (FQN)' => [
444+
'type' => '\true|\false|\null',
445+
'expected' => [
446+
'\true' => '\true',
447+
'\false' => '\false',
448+
'\null' => '\null',
449+
],
450+
],
451+
'union type: \TRUE|\FALSE|\NULL (FQN + uppercase)' => [
452+
'type' => '\TRUE|\FALSE|\NULL',
453+
'expected' => [
454+
'\TRUE' => '\TRUE',
455+
'\FALSE' => '\FALSE',
456+
'\NULL' => '\NULL',
457+
],
458+
],
459+
426460
'DNF type: keywords in mixed case' => [
427461
'type' => 'FALSE|(B&A)|Null',
428462
'expected' => [

0 commit comments

Comments
 (0)