Skip to content

Handle \true/\false/\null in the new namespaced names tokenization #1042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ public function process(File $phpcsFile, $stackPtr)

if (isset(Tokens::EMPTY_TOKENS[$code]) === true) {
continue;
}

if ($code === T_NAME_FULLY_QUALIFIED) {
$compareReadyKeyword = strtolower($tokens[$next]['content']);
if ($compareReadyKeyword !== '\true' && $compareReadyKeyword !== '\false') {
$goodCondition = true;
}
} else if ($code !== T_TRUE && $code !== T_FALSE) {
$goodCondition = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,24 @@ public function process(File $phpcsFile, $stackPtr)
T_LNUMBER,
T_DNUMBER,
T_CONSTANT_ENCAPSED_STRING,
T_NAME_FULLY_QUALIFIED,
];

if (in_array($tokens[$previousIndex]['code'], $relevantTokens, true) === false) {
return;
}

// Special case: T_NAME_FULLY_QUALIFIED is only a "relevant" token when it is for a FQN true/false/null.
if ($tokens[$previousIndex]['code'] === T_NAME_FULLY_QUALIFIED) {
$compareReadyKeyword = strtolower($tokens[$previousIndex]['content']);
if ($compareReadyKeyword !== '\true'
&& $compareReadyKeyword !== '\false'
&& $compareReadyKeyword !== '\null'
) {
return;
}
}

if ($tokens[$previousIndex]['code'] === T_CLOSE_SHORT_ARRAY) {
$previousIndex = $tokens[$previousIndex]['bracket_opener'];
if ($this->isArrayStatic($phpcsFile, $previousIndex) === false) {
Expand Down Expand Up @@ -164,6 +176,7 @@ public function isArrayStatic(File $phpcsFile, $arrayToken)
T_COMMA => T_COMMA,
T_TRUE => T_TRUE,
T_FALSE => T_FALSE,
T_NULL => T_NULL,
];

for ($i = ($start + 1); $i < $end; $i++) {
Expand All @@ -172,10 +185,21 @@ public function isArrayStatic(File $phpcsFile, $arrayToken)
continue;
}

// Special case: T_NAME_FULLY_QUALIFIED is only a "static" token when it is for a FQN true/false/null.
if ($tokens[$i]['code'] === T_NAME_FULLY_QUALIFIED) {
$compareReadyKeyword = strtolower($tokens[$i]['content']);
if ($compareReadyKeyword === '\true'
|| $compareReadyKeyword === '\false'
|| $compareReadyKeyword === '\null'
) {
continue;
}
}

if (isset($staticTokens[$tokens[$i]['code']]) === false) {
return false;
}
}
}//end for

return true;

Expand Down
39 changes: 36 additions & 3 deletions src/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class LowerCaseConstantSniff implements Sniff
T_NAME_QUALIFIED => T_NAME_QUALIFIED,
T_NAME_FULLY_QUALIFIED => T_NAME_FULLY_QUALIFIED,
T_NAME_RELATIVE => T_NAME_RELATIVE,
T_NS_SEPARATOR => T_NS_SEPARATOR,
T_NAMESPACE => T_NAMESPACE,
T_TYPE_UNION => T_TYPE_UNION,
T_TYPE_INTERSECTION => T_TYPE_INTERSECTION,
T_TYPE_OPEN_PARENTHESIS => T_TYPE_OPEN_PARENTHESIS,
Expand All @@ -62,6 +60,9 @@ public function register()
{
$targets = $this->targets;

// Allow for "fully qualified" true/false/null.
$targets[] = T_NAME_FULLY_QUALIFIED;

// Register scope modifiers to filter out property type declarations.
$targets += Tokens::SCOPE_MODIFIERS;
$targets[] = T_VAR;
Expand Down Expand Up @@ -97,6 +98,13 @@ public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();

// If this is a fully qualified name, check if it is FQN true/false/null.
if ($tokens[$stackPtr]['code'] === T_NAME_FULLY_QUALIFIED
&& $this->isFQNTrueFalseNull($phpcsFile, $stackPtr) === false
) {
return;
}

// Skip over potential type declarations for constants.
if ($tokens[$stackPtr]['code'] === T_CONST) {
// Constant must always have a value assigned to it, so we can just look for the assignment
Expand Down Expand Up @@ -180,7 +188,10 @@ public function process(File $phpcsFile, $stackPtr)
}

for ($i = $param['default_token']; $i < $paramEnd; $i++) {
if (isset($this->targets[$tokens[$i]['code']]) === true) {
if (isset($this->targets[$tokens[$i]['code']]) === true
|| ($tokens[$i]['code'] === T_NAME_FULLY_QUALIFIED
&& $this->isFQNTrueFalseNull($phpcsFile, $i) === true)
) {
$this->processConstant($phpcsFile, $i);
}
}
Expand All @@ -196,6 +207,28 @@ public function process(File $phpcsFile, $stackPtr)
}//end process()


/**
* Check if a fully qualified name is a fully qualified true/false/null.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the T_NAME_FULLY_QUALIFIED token in the
* stack passed in $tokens.
*
* @return bool
*/
protected function isFQNTrueFalseNull(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();

// Check for fully qualified true/false/null only.
$compareReadyKeyword = strtolower($tokens[$stackPtr]['content']);
return ($compareReadyKeyword === '\true'
|| $compareReadyKeyword === '\false'
|| $compareReadyKeyword === '\null');

}//end isFQNTrueFalseNull()


/**
* Processes a non-type declaration constant.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ if (true) {
if (file_exists(__FILE__) === true) {

}

// Check handling of case and FQN state.
if (\true) {
} else if (\FALSE) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ public function getWarningList($testFile='')
switch ($testFile) {
case 'UnconditionalIfStatementUnitTest.1.inc':
return [
3 => 1,
5 => 1,
7 => 1,
3 => 1,
5 => 1,
7 => 1,
16 => 1,
17 => 1,
];

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ if ($value == true) {}
if (true === $value) {}
if (true == $value) {}

if($value === true){}
if($value == true){}
if($value === false){}
if($value == false){}
if(false === $value){}
if(!false == $value || true !== $value){}

Expand Down Expand Up @@ -139,8 +139,8 @@ if (is_array($val)
&& array('foo', 'bar') === array($foo, $bar)
&& ['foo', 'bar'] === [$foo, $bar]
&& array('foo' => true, 'bar' => false) === array(getContents())
&& ['foo' => true, 'bar' => false] === array(getContents())
&& array(getContents()) === ['foo' => true, 'bar' => false]
&& ['foo' => true, 'bar' => \false, 'baz' => null] === array(getContents())
&& array(getContents()) === ['foo' => \true, 'bar' => false, 'baz' => \null]
) {
}

Expand Down Expand Up @@ -192,3 +192,14 @@ if(Partially\qualified('foo') === 10){}
if(1.5 === Partially\qualified(true)){}
if(namespace\relative(false) === null){}
if('string' === namespace\relative(null)){}

// Handle FQN true/false/null the same as plain true/false/null.
if ($value === \true) {}
if (\true === $value) {}

if($value == \FALSE){}
if(\FALSE === $value){}
if(!\false == $value || true !== $value){}

if($value === \Null){}
if(\Null == $value){}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public function getErrorList()
190 => 1,
192 => 1,
194 => 1,
198 => 1,
201 => 1,
202 => 2,
205 => 1,
];

}//end getErrorList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,7 @@ class SkipOverPHP84FinalProperties {
final MyType|FALSE $propA;
private static final NULL|MyClass $propB;
}

$a = \NULL;
$a = \falSe;
$a = \True;
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,7 @@ class SkipOverPHP84FinalProperties {
final MyType|FALSE $propA;
private static final NULL|MyClass $propB;
}

$a = \null;
$a = \false;
$a = \true;
3 changes: 3 additions & 0 deletions src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ public function getErrorList($testFile='')
129 => 1,
149 => 1,
153 => 1,
164 => 1,
165 => 1,
166 => 1,
];

default:
Expand Down
4 changes: 4 additions & 0 deletions src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ class SkipOverPHP84FinalProperties {
final MyType|false $propA;
private static final null|MyClass $propB;
}

$a = \null;
$a = \falSe;
$a = \True;
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ class SkipOverPHP84FinalProperties {
final MyType|false $propA;
private static final null|MyClass $propB;
}

$a = \NULL;
$a = \FALSE;
$a = \TRUE;
45 changes: 24 additions & 21 deletions src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,30 @@ final class UpperCaseConstantUnitTest extends AbstractSniffTestCase
public function getErrorList()
{
return [
7 => 1,
10 => 1,
15 => 1,
16 => 1,
23 => 1,
26 => 1,
31 => 1,
32 => 1,
39 => 1,
42 => 1,
47 => 1,
48 => 1,
70 => 1,
71 => 1,
85 => 1,
87 => 1,
88 => 1,
90 => 2,
92 => 2,
93 => 1,
98 => 2,
7 => 1,
10 => 1,
15 => 1,
16 => 1,
23 => 1,
26 => 1,
31 => 1,
32 => 1,
39 => 1,
42 => 1,
47 => 1,
48 => 1,
70 => 1,
71 => 1,
85 => 1,
87 => 1,
88 => 1,
90 => 2,
92 => 2,
93 => 1,
98 => 2,
109 => 1,
110 => 1,
111 => 1,
];

}//end getErrorList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,6 @@ function fooH(): ?

// Fatal error: null cannot be marked as nullable, but that's not the concern of this sniff.
function fooI(): ? null {}

// Ensure nullable FQN true/false are handled correctly.
function fqnTrueFalseNull(? \FALSE $paramA, ? \Null $paramB) : ? \true {}
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ function fooH(): ?false {}

// Fatal error: null cannot be marked as nullable, but that's not the concern of this sniff.
function fooI(): ?null {}

// Ensure nullable FQN true/false are handled correctly.
function fqnTrueFalseNull(?\FALSE $paramA, ?\Null $paramB) : ?\true {}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ protected function getErrorList()
90 => 1,
91 => 1,
95 => 1,
98 => 3,
];

}//end getErrorList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ public function process(File $phpcsFile, $stackPtr)
$foundBooleans++;
}

if ($tokens[$i]['code'] === T_NAME_FULLY_QUALIFIED) {
$compareReadyKeyword = strtolower($tokens[$i]['content']);
if ($compareReadyKeyword === '\true' || $compareReadyKeyword === '\false') {
$foundBooleans++;
}
}

if ($tokens[$i]['code'] === T_BOOLEAN_AND
|| $tokens[$i]['code'] === T_BOOLEAN_OR
) {
Expand Down
18 changes: 18 additions & 0 deletions src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,21 @@ class AllowMoreForSelectivelyIgnoringDisallowedTags {
}

// phpcs:enable Squiz.Commenting.VariableComment

class StandaloneFQNNullTrueFalseTypes
{
/**
* @var null
*/
public \Null $variableName = null;

/**
* @var true
*/
protected \true $variableName = true;

/**
* @var false
*/
private \FALSE $variableName = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,21 @@ class AllowMoreForSelectivelyIgnoringDisallowedTags {
}

// phpcs:enable Squiz.Commenting.VariableComment

class StandaloneFQNNullTrueFalseTypes
{
/**
* @var null
*/
public \Null $variableName = null;

/**
* @var true
*/
protected \true $variableName = true;

/**
* @var false
*/
private \FALSE $variableName = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,9 @@ if (unqualified($argTags > 0)) {}
if (Partially\qualified($argTags > 0)) {}
if (\Fully\qualified($argTags > 0)) {}
if (namespace\relative($argTags > 0)) {}

// Verify that FQN true/false are handled the same as unqualified.
if (true) {}
if (\true) {}
for ($var1 = 10; FALSE; $var1--) {}
for ($var1 = 10; \FALSE; $var1--) {}
Loading