Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions PhpCollective/Sniffs/AbstractSniffs/AbstractSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ protected function getClassName(File $phpcsFile): string
$fileName = $phpcsFile->getFilename();
$fileNameParts = explode(DIRECTORY_SEPARATOR, $fileName);
$directoryPosition = array_search('src', $fileNameParts, true);
if (!$directoryPosition) {
$directoryPosition = array_search('tests', $fileNameParts, true) + 1;
if ($directoryPosition === false) {
$testsPosition = array_search('tests', $fileNameParts, true);
$directoryPosition = $testsPosition === false ? 0 : $testsPosition + 1;
}
$classNameParts = array_slice($fileNameParts, $directoryPosition + 1);
$className = implode('\\', $classNameParts);
Expand Down
2 changes: 1 addition & 1 deletion PhpCollective/Sniffs/Classes/EnumCaseCasingSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function process(File $phpcsFile, $stackPtr): void
}

$result = mb_strtolower($content);
$result = ucfirst($result);
$result = mb_strtoupper(mb_substr($result, 0, 1)) . mb_substr($result, 1);

if ($result === $content) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public function process(File $phpcsFile, $stackPtr): void
return;
}

$openingBraceIndex = (int)$phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
if (!$openingBraceIndex) {
$openingBraceIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true);
if ($openingBraceIndex === false) {
return;
}
if (empty($tokens[$openingBraceIndex]['parenthesis_closer'])) {
Expand Down Expand Up @@ -113,8 +113,8 @@ protected function checkMethodCalls(File $phpcsFile, int $stackPtr): void
{
$tokens = $phpcsFile->getTokens();

$openingBraceIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1), $stackPtr + 4);
if (!$openingBraceIndex) {
$openingBraceIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1, $stackPtr + 4);
if ($openingBraceIndex === false) {
return;
}
if (empty($tokens[$openingBraceIndex]['parenthesis_closer'])) {
Expand Down
41 changes: 26 additions & 15 deletions PhpCollective/Sniffs/PHP/NoIsNullSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ public function process(File $phpcsFile, $stackPtr): void
}

if ($trailingComparison) {
$possibleEndIndex = $this->findUnnecessaryLeadingComparisonStart($phpcsFile, $endIndex);
if ($possibleEndIndex !== null) {
$endIndex = $possibleEndIndex;
$trailingResult = $this->findUnnecessaryTrailingComparisonEnd($phpcsFile, $endIndex);
if ($trailingResult !== null) {
$endIndex = $trailingResult['index'];
$trailingComparison = false;
if ($tokens[$endIndex]['code'] === T_FALSE) {
if ($trailingResult['negated']) {
$negated = !$negated;
}
}
Expand Down Expand Up @@ -189,13 +189,13 @@ protected function findUnnecessaryLeadingComparisonStart(File $phpcsFile, int $i
{
$tokens = $phpcsFile->getTokens();

$previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($index - 1), null, true);
if (!$previous || !in_array($tokens[$previous]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL])) {
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $index - 1, null, true);
if ($previous === false || !in_array($tokens[$previous]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], true)) {
return null;
}

$previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($previous - 1), null, true);
if (!$previous || !in_array($tokens[$previous]['code'], [T_TRUE, T_FALSE])) {
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $previous - 1, null, true);
if ($previous === false || !in_array($tokens[$previous]['code'], [T_TRUE, T_FALSE], true)) {
return null;
}

Expand All @@ -206,23 +206,34 @@ protected function findUnnecessaryLeadingComparisonStart(File $phpcsFile, int $i
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $index
*
* @return int|null
* @return array{index: int, negated: bool}|null
*/
protected function findUnnecessaryTrailingComparisonEnd(File $phpcsFile, int $index): ?int
protected function findUnnecessaryTrailingComparisonEnd(File $phpcsFile, int $index): ?array
{
$tokens = $phpcsFile->getTokens();

$next = (int)$phpcsFile->findNext(T_WHITESPACE, ($index + 1), null, true);
if (!$next || !in_array($tokens[$next]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL])) {
$operatorIndex = $phpcsFile->findNext(T_WHITESPACE, $index + 1, null, true);
if ($operatorIndex === false || !in_array($tokens[$operatorIndex]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], true)) {
return null;
}

$next = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), null, true);
if (!$next || !in_array($tokens[$next]['code'], [T_TRUE, T_FALSE])) {
$isNotIdentical = $tokens[$operatorIndex]['code'] === T_IS_NOT_IDENTICAL;

$valueIndex = $phpcsFile->findNext(T_WHITESPACE, $operatorIndex + 1, null, true);
if ($valueIndex === false || !in_array($tokens[$valueIndex]['code'], [T_TRUE, T_FALSE], true)) {
return null;
}

return $next;
$isFalse = $tokens[$valueIndex]['code'] === T_FALSE;

// Determine if negation is needed:
// === true -> no negation
// === false -> negate
// !== true -> negate
// !== false -> no negation (double negation)
$negated = $isNotIdentical !== $isFalse;

return ['index' => $valueIndex, 'negated' => $negated];
}

/**
Expand Down
12 changes: 6 additions & 6 deletions PhpCollective/Sniffs/PHP/PhpSapiConstantSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ public function process(File $phpcsFile, $stackPtr): void
return;
}

$previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
if (!$previous || in_array($tokens[$previous]['code'], $wrongTokens)) {
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($previous === false || in_array($tokens[$previous]['code'], $wrongTokens, true)) {
return;
}

$openingBrace = (int)$phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if (!$openingBrace || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') {
$openingBrace = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
if ($openingBrace === false || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') {
return;
}

$closingBrace = (int)$phpcsFile->findNext(T_WHITESPACE, ($openingBrace + 1), null, true);
if (!$closingBrace || $tokens[$closingBrace]['type'] !== 'T_CLOSE_PARENTHESIS') {
$closingBrace = $phpcsFile->findNext(T_WHITESPACE, $openingBrace + 1, null, true);
if ($closingBrace === false || $tokens[$closingBrace]['type'] !== 'T_CLOSE_PARENTHESIS') {
return;
}

Expand Down
8 changes: 4 additions & 4 deletions PhpCollective/Sniffs/PHP/PreferCastOverFunctionSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ public function process(File $phpcsFile, $stackPtr): void
return;
}

$previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
if (!$previous || in_array($tokens[$previous]['code'], $wrongTokens)) {
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($previous === false || in_array($tokens[$previous]['code'], $wrongTokens, true)) {
return;
}

$openingBraceIndex = (int)$phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if (!$openingBraceIndex || $tokens[$openingBraceIndex]['type'] !== 'T_OPEN_PARENTHESIS') {
$openingBraceIndex = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
if ($openingBraceIndex === false || $tokens[$openingBraceIndex]['type'] !== 'T_OPEN_PARENTHESIS') {
return;
}

Expand Down
30 changes: 30 additions & 0 deletions tests/PhpCollective/Sniffs/PHP/NoIsNullSniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace PhpCollective\Test\PhpCollective\Sniffs\PHP;

use PhpCollective\Sniffs\PHP\NoIsNullSniff;
use PhpCollective\Test\TestCase;

class NoIsNullSniffTest extends TestCase
{
/**
* @return void
*/
public function testNoIsNullSniffer(): void
{
$this->assertSnifferFindsFixableErrors(new NoIsNullSniff(), 8, 8);
}

/**
* @return void
*/
public function testNoIsNullFixer(): void
{
$this->assertSnifferCanFixErrors(new NoIsNullSniff(), 8);
}
}
70 changes: 70 additions & 0 deletions tests/_data/NoIsNull/after.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);

namespace PhpCollective;

class FixMe
{
/**
* Basic is_null() should become === null
*/
public function basicIsNull($x): bool
{
return $x === null;
}

/**
* Negated !is_null() should become !== null
*/
public function negatedIsNull($x): bool
{
return $x !== null;
}

/**
* Leading comparison: true === is_null($x) should simplify
*/
public function leadingComparisonTrue($x): bool
{
return $x === null;
}

/**
* Leading comparison: false === is_null($x) should simplify and negate
*/
public function leadingComparisonFalse($x): bool
{
return $x !== null;
}

/**
* Trailing comparison: is_null($x) === true should simplify
*/
public function trailingComparisonTrue($x): bool
{
return $x === null;
}

/**
* Trailing comparison: is_null($x) === false should simplify and negate
*/
public function trailingComparisonFalse($x): bool
{
return $x !== null;
}

/**
* Trailing comparison with !== true should simplify and negate
*/
public function trailingComparisonNotTrue($x): bool
{
return $x !== null;
}

/**
* Trailing comparison with !== false should simplify (double negation)
*/
public function trailingComparisonNotFalse($x): bool
{
return $x === null;
}
}
70 changes: 70 additions & 0 deletions tests/_data/NoIsNull/before.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);

namespace PhpCollective;

class FixMe
{
/**
* Basic is_null() should become === null
*/
public function basicIsNull($x): bool
{
return is_null($x);
}

/**
* Negated !is_null() should become !== null
*/
public function negatedIsNull($x): bool
{
return !is_null($x);
}

/**
* Leading comparison: true === is_null($x) should simplify
*/
public function leadingComparisonTrue($x): bool
{
return true === is_null($x);
}

/**
* Leading comparison: false === is_null($x) should simplify and negate
*/
public function leadingComparisonFalse($x): bool
{
return false === is_null($x);
}

/**
* Trailing comparison: is_null($x) === true should simplify
*/
public function trailingComparisonTrue($x): bool
{
return is_null($x) === true;
}

/**
* Trailing comparison: is_null($x) === false should simplify and negate
*/
public function trailingComparisonFalse($x): bool
{
return is_null($x) === false;
}

/**
* Trailing comparison with !== true should simplify and negate
*/
public function trailingComparisonNotTrue($x): bool
{
return is_null($x) !== true;
}

/**
* Trailing comparison with !== false should simplify (double negation)
*/
public function trailingComparisonNotFalse($x): bool
{
return is_null($x) !== false;
}
}
Loading