Skip to content

Commit

Permalink
SlevomatCodingStandard.ControlStructures.RequireNullSafeObjectOperato…
Browse files Browse the repository at this point in the history
…r: Fixed false positive
  • Loading branch information
kukulich committed May 6, 2023
1 parent c090666 commit 7d9062c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,36 +69,23 @@ public function process(File $phpcsFile, $identicalPointer): int

$tokens = $phpcsFile->getTokens();

$pointerBeforeIdentical = TokenHelper::findPreviousEffective($phpcsFile, $identicalPointer - 1);
$pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $identicalPointer + 1);
[$pointerBeforeIdentical, $pointerAfterIdentical] = $this->getIndenticalData($phpcsFile, $identicalPointer);

if ($tokens[$pointerBeforeIdentical]['code'] !== T_NULL && $tokens[$pointerAfterIdentical]['code'] !== T_NULL) {
return $identicalPointer + 1;
}

$isYoda = $tokens[$pointerBeforeIdentical]['code'] === T_NULL;

if ($isYoda) {
$identificatorStartPointer = $pointerAfterIdentical;
$identificatorEndPointer = $this->findIdentificatorEnd($phpcsFile, $identificatorStartPointer);

if ($identificatorEndPointer === null) {
return $pointerAfterIdentical + 1;
}

$conditionStartPointer = $pointerBeforeIdentical;

} else {
$identificatorEndPointer = $pointerBeforeIdentical;
$identificatorStartPointer = $this->findIdentificatorStart($phpcsFile, $identificatorEndPointer);

if ($identificatorStartPointer === null) {
return $identificatorEndPointer + 1;
}
[$identificatorStartPointer, $identificatorEndPointer, $conditionStartPointer] = $this->getConditionData(
$phpcsFile,
$pointerBeforeIdentical,
$pointerAfterIdentical
);

$conditionStartPointer = $identificatorStartPointer;
if ($identificatorStartPointer === null || $identificatorEndPointer === null) {
return $identicalPointer + 1;
}

$isYoda = $tokens[$pointerBeforeIdentical]['code'] === T_NULL;
$identificator = IdentificatorHelper::getContent($phpcsFile, $identificatorStartPointer, $identificatorEndPointer);

$pointerAfterCondition = TokenHelper::findNextEffective(
Expand Down Expand Up @@ -159,6 +146,40 @@ private function checkTernaryOperator(

} while (true);

$pointerBeforeCondition = TokenHelper::findPreviousEffective($phpcsFile, $conditionStartPointer - 1);
if (in_array($tokens[$pointerBeforeCondition]['code'], [T_BOOLEAN_AND, T_BOOLEAN_OR], true)) {
$previousIdenticalPointer = TokenHelper::findPreviousLocal(
$phpcsFile,
[T_IS_IDENTICAL, T_IS_NOT_IDENTICAL],
$pointerBeforeCondition
);

if ($previousIdenticalPointer !== null) {
[$pointerBeforePreviousIdentical, $pointerAfterPreviousIdentical] = $this->getIndenticalData(
$phpcsFile,
$previousIdenticalPointer
);

[$previousIdentificatorStartPointer, $previousIdentificatorEndPointer] = $this->getConditionData(
$phpcsFile,
$pointerBeforePreviousIdentical,
$pointerAfterPreviousIdentical
);

if ($previousIdentificatorStartPointer !== null && $previousIdentificatorEndPointer !== null) {
$previousIdentificator = IdentificatorHelper::getContent(
$phpcsFile,
$previousIdentificatorStartPointer,
$previousIdentificatorEndPointer
);

if (!self::areIdentificatorsCompatible($previousIdentificator, $identificator)) {
return;
}
}
}
}

$defaultInElse = $tokens[$identicalPointer]['code'] === T_IS_NOT_IDENTICAL;
$inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer);
$inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer);
Expand Down Expand Up @@ -274,7 +295,7 @@ private function checkNextCondition(
$nextIdentificator = IdentificatorHelper::getContent($phpcsFile, $nextIdentificatorStartPointer, $nextIdentificatorEndPointer);

if (!$this->areIdentificatorsCompatible($identificator, $nextIdentificator)) {
return $nextConditionBooleanPointer;
return $nextIdentificatorEndPointer;
}

$pointerAfterNexIdentificator = TokenHelper::findNextEffective($phpcsFile, $nextIdentificatorEndPointer + 1);
Expand All @@ -285,16 +306,16 @@ private function checkNextCondition(
$tokens[$pointerAfterNexIdentificator]['code'] !== $tokens[$identicalPointer]['code']
&& !in_array($tokens[$pointerAfterNexIdentificator]['code'], [T_INLINE_THEN, T_SEMICOLON], true)
) {
return $nextConditionBooleanPointer;
return $pointerAfterNexIdentificator;
}

if (!in_array($tokens[$pointerAfterNexIdentificator]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], true)) {
return $nextConditionBooleanPointer;
return $pointerAfterNexIdentificator;
}

$pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $pointerAfterNexIdentificator + 1);
if ($tokens[$pointerAfterIdentical]['code'] !== T_NULL) {
return $nextConditionBooleanPointer;
return $pointerAfterNexIdentificator;
}

$identificatorDifference = $this->getIdentificatorDifference(
Expand All @@ -307,7 +328,7 @@ private function checkNextCondition(
$fix = $phpcsFile->addFixableError('Operator ?-> is required.', $identicalPointer, self::CODE_REQUIRED_NULL_SAFE_OBJECT_OPERATOR);

if (!$fix) {
return $nextConditionBooleanPointer;
return $pointerAfterNexIdentificator;
}

$isConditionOfTernaryOperator = TernaryOperatorHelper::isConditionOfTernaryOperator($phpcsFile, $identicalPointer);
Expand All @@ -324,7 +345,7 @@ private function checkNextCondition(
return TokenHelper::findNext($phpcsFile, T_INLINE_THEN, $identicalPointer + 1);
}

return $nextConditionBooleanPointer;
return $pointerAfterNexIdentificator;
}

/**
Expand Down Expand Up @@ -451,4 +472,40 @@ private function getIdentificatorDifference(
return TokenHelper::getContent($phpcsFile, $differencePointer, $nextIdentificatorEndPointer);
}

/**
* @return array{0: int, 1: int}
*/
private function getIndenticalData(File $phpcsFile, int $identicalPointer): array
{
/** @var int $pointerBeforeIdentical */
$pointerBeforeIdentical = TokenHelper::findPreviousEffective($phpcsFile, $identicalPointer - 1);
/** @var int $pointerAfterIdentical */
$pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $identicalPointer + 1);

return [$pointerBeforeIdentical, $pointerAfterIdentical];
}

/**
* @return array{0: int|null, 1: int|null, 2: int|null}
*/
private function getConditionData(File $phpcsFile, int $pointerBeforeIdentical, int $pointerAfterIdentical): array
{
$tokens = $phpcsFile->getTokens();

$isYoda = $tokens[$pointerBeforeIdentical]['code'] === T_NULL;

if ($isYoda) {
$identificatorStartPointer = $pointerAfterIdentical;
$identificatorEndPointer = $this->findIdentificatorEnd($phpcsFile, $identificatorStartPointer);
$conditionStartPointer = $pointerBeforeIdentical;

} else {
$identificatorEndPointer = $pointerBeforeIdentical;
$identificatorStartPointer = $this->findIdentificatorStart($phpcsFile, $identificatorEndPointer);
$conditionStartPointer = $identificatorStartPointer;
}

return [$identificatorStartPointer, $identificatorEndPointer, $conditionStartPointer];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,10 @@ function ($something): bool {

if ($a === null || $a->size() === 0) {
}

function format($format, $date): ?string
{
return $format !== null && $date !== null
? $date->format($format)
: null;
}

0 comments on commit 7d9062c

Please sign in to comment.