diff --git a/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php b/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php index 4d999f9f5ba..024f0a49d73 100644 --- a/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php @@ -24,6 +24,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -286,6 +287,10 @@ private function fixAssertTrueFalse(Tokens $tokens, ArgumentsAnalyzer $arguments $testIndex = $tokens->getNextMeaningfulToken($assertCall['openBraceIndex']); if (!$tokens[$testIndex]->isGivenKind([T_EMPTY, T_STRING])) { + if ($this->fixAssertTrueFalseInstanceof($tokens, $assertCall, $testIndex)) { + return; + } + if (!$tokens[$testIndex]->isGivenKind(T_NS_SEPARATOR)) { return; } @@ -370,6 +375,66 @@ private function fixAssertTrueFalse(Tokens $tokens, ArgumentsAnalyzer $arguments } } + private function fixAssertTrueFalseInstanceof(Tokens $tokens, array $assertCall, int $testIndex): bool + { + if ($tokens[$testIndex]->equals('!')) { + $variableIndex = $tokens->getNextMeaningfulToken($testIndex); + $positive = false; + } else { + $variableIndex = $testIndex; + $positive = true; + } + + if (!$tokens[$variableIndex]->isGivenKind(T_VARIABLE)) { + return false; + } + + $instanceOfIndex = $tokens->getNextMeaningfulToken($variableIndex); + + if (!$tokens[$instanceOfIndex]->isGivenKind(T_INSTANCEOF)) { + return false; + } + + $classEndIndex = $instanceOfIndex; + $classPartTokens = []; + + do { + $classEndIndex = $tokens->getNextMeaningfulToken($classEndIndex); + $classPartTokens[] = $tokens[$classEndIndex]; + } while ($tokens[$classEndIndex]->isGivenKind([T_STRING, T_NS_SEPARATOR, T_VARIABLE])); + + if ($tokens[$classEndIndex]->equalsAny([',', ')'])) { // do the fixing + array_pop($classPartTokens); + $isInstanceOfVar = (reset($classPartTokens))->isGivenKind(T_VARIABLE); + $insertIndex = $testIndex - 1; + $newTokens = []; + + foreach ($classPartTokens as $token) { + $newTokens[++$insertIndex] = clone $token; + } + + if (!$isInstanceOfVar) { + $newTokens[++$insertIndex] = new Token([T_DOUBLE_COLON, '::']); + $newTokens[++$insertIndex] = new Token([CT::T_CLASS_CONSTANT, 'class']); + } + + $newTokens[++$insertIndex] = new Token(','); + $newTokens[++$insertIndex] = new Token([T_WHITESPACE, ' ']); + $newTokens[++$insertIndex] = clone $tokens[$variableIndex]; + + for ($i = $classEndIndex - 1; $i >= $testIndex; --$i) { + if (!$tokens[$i]->isComment()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + } + + $tokens->insertSlices($newTokens); + $tokens[$assertCall['index']] = new Token([T_STRING, $positive ? 'assertInstanceOf' : 'assertNotInstanceOf']); + } + + return true; + } + private function fixAssertSameEquals(Tokens $tokens, array $assertCall): void { // @ $this->/self::assertEquals/Same([$nextIndex]) diff --git a/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php index 0fad8e4d8f1..0495a3e0407 100644 --- a/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php @@ -267,6 +267,55 @@ public function provideTestFixCases(): \Generator self::generateTest('self::assertStringEndsNotWith($needle, $haystack);'), self::generateTest('self::assertFalse(str_ends_with($haystack, $needle));'), ]; + + yield '$a instanceof class' => [ + self::generateTest(' + $this->assertInstanceOf(SomeClass::class, $x); + $this->assertInstanceOf(SomeClass::class, $y, $message); + '), + self::generateTest(' + $this->assertTrue($x instanceof SomeClass); + $this->assertTrue($y instanceof SomeClass, $message); + '), + ]; + + yield '$a instanceof class\a\b' => [ + self::generateTest(' + $this->assertInstanceOf(\PhpCsFixer\Tests\Fixtures\Test\AbstractFixerTest\SimpleFixer::class, $ii); + '), + self::generateTest(' + $this->assertTrue($ii instanceof \PhpCsFixer\Tests\Fixtures\Test\AbstractFixerTest\SimpleFixer); + '), + ]; + + yield '$a instanceof $b' => [ + self::generateTest(' + $this->assertInstanceOf($tty, $abc/* 1 *//* 2 */); + $this->assertInstanceOf($oo, $def, $message); + '), + self::generateTest(' + $this->assertTrue($abc instanceof /* 1 */$tty /* 2 */); + $this->assertTrue($def instanceof $oo, $message); + '), + ]; + + yield 'do not fix instance of' => [ + self::generateTest(' + $this->assertTrue($gg instanceof $ijl . "X", $something); + $this->assertTrue($ff instanceof $klh . $b(1,2,$message), $noMsg); + '), + ]; + + yield '!$a instanceof class' => [ + self::generateTest(' + $this->assertNotInstanceOf(SomeClass::class, $x); + $this->assertNotInstanceOf(SomeClass::class, $y, $message); + '), + self::generateTest(' + $this->assertTrue(!$x instanceof SomeClass); + $this->assertTrue(!$y instanceof SomeClass, $message); + '), + ]; } /**