Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class IsTypeFunctions extends TestCase
{
public function test()
{
$this->assertTrue(is_array($value));
$this->assertTrue(is_bool($value));
$this->assertTrue(is_callable($value));
$this->assertTrue(is_float($value));
$this->assertTrue(is_int($value));
$this->assertTrue(is_iterable($value));
$this->assertTrue(is_numeric($value));
$this->assertTrue(is_object($value));
$this->assertTrue(is_scalar($value));
$this->assertTrue(is_string($value), 'the value must be a string');
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class IsTypeFunctions extends TestCase
{
public function test()
{
$this->assertIsArray($value);
$this->assertIsBool($value);
$this->assertIsCallable($value);
$this->assertIsFloat($value);
$this->assertIsInt($value);
$this->assertIsIterable($value);
$this->assertIsNumeric($value);
$this->assertIsObject($value);
$this->assertIsScalar($value);
$this->assertIsString($value, 'the value must be a string');
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class IsTypeFunctionsNegated extends TestCase
{
public function test()
{
$this->assertFalse(is_callable($value));
$this->assertNotTrue(is_array($value));
$this->assertNotFalse(is_string($value));
self::assertFalse(is_object($value), 'the value must not be an object');
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class IsTypeFunctionsNegated extends TestCase
{
public function test()
{
$this->assertIsNotCallable($value);
$this->assertIsNotArray($value);
$this->assertIsString($value);
self::assertIsNotObject($value, 'the value must not be an object');
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class SkipIsCallableWithSyntaxOnly extends TestCase
{
public function test()
{
$this->assertTrue(is_callable($value, true));
$this->assertTrue(is_callable($value, true, $callableName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\AssertTrueFalseToSpecificMethodRector\Fixture;

use PHPUnit\Framework\TestCase;

final class SkipNamedAndSpreadArgs extends TestCase
{
public function test()
{
$this->assertTrue(is_string(value: $value));
$this->assertTrue(is_readable(filename: $file));
$this->assertTrue(is_string(...$args));
$this->assertTrue(in_array(needle: '...', haystack: ['...'], strict: true));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ final class AssertTrueFalseToSpecificMethodRector extends AbstractRector
'is_nan' => ['is_nan', 'assertNan', ''],
'is_a' => ['is_a', 'assertInstanceOf', 'assertNotInstanceOf'],
'str_contains' => ['str_contains', 'assertStringContainsString', 'assertStringNotContainsString'],
'is_array' => ['is_array', 'assertIsArray', 'assertIsNotArray'],
'is_bool' => ['is_bool', 'assertIsBool', 'assertIsNotBool'],
'is_callable' => ['is_callable', 'assertIsCallable', 'assertIsNotCallable'],
'is_float' => ['is_float', 'assertIsFloat', 'assertIsNotFloat'],
'is_int' => ['is_int', 'assertIsInt', 'assertIsNotInt'],
'is_iterable' => ['is_iterable', 'assertIsIterable', 'assertIsNotIterable'],
'is_numeric' => ['is_numeric', 'assertIsNumeric', 'assertIsNotNumeric'],
'is_object' => ['is_object', 'assertIsObject', 'assertIsNotObject'],
'is_scalar' => ['is_scalar', 'assertIsScalar', 'assertIsNotScalar'],
'is_string' => ['is_string', 'assertIsString', 'assertIsNotString'],
];

/**
Expand Down Expand Up @@ -115,6 +125,10 @@ public function refactor(Node $node): ?Node
return null;
}

if ($firstArgumentValue instanceof FuncCall && $this->hasUnmovableArgs($firstArgumentValue)) {
return null;
}

if ($firstArgumentName === 'is_a') {
/** @var FuncCall $firstArgumentValue */
$args = $firstArgumentValue->getArgs();
Expand All @@ -130,6 +144,14 @@ public function refactor(Node $node): ?Node
}
}

// the is_callable() $syntax_only and $callable_name arguments have no counterpart in assertIsCallable()
if ($firstArgumentName === 'is_callable') {
/** @var FuncCall $firstArgumentValue */
if (count($firstArgumentValue->getArgs()) > 1) {
return null;
}
}

[$functionName, $assetMethodName, $notAssertMethodName] = self::FUNCTION_NAME_WITH_ASSERT_METHOD_NAMES[$firstArgumentName];

$functionNameWithAssertMethods = new FunctionNameWithAssertMethods($assetMethodName, $notAssertMethodName);
Expand All @@ -148,6 +170,28 @@ private function resolveFirstArgument(FuncCall|Empty_ $firstArgumentValue): ?str
: $this->getName($firstArgumentValue);
}

/**
* Args are moved up by position, so a named arg only survives when the assert method happens to
* use the same parameter name: is_readable(filename:) fits assertIsReadable(), while
* is_string(value:) does not fit assertIsString(), whose parameter is $actual. Bail out instead
* of tracking a parameter name per mapped function. Spread args cannot be moved up either,
* as their count is unknown.
*/
private function hasUnmovableArgs(FuncCall $funcCall): bool
{
foreach ($funcCall->getArgs() as $arg) {
if ($arg->name instanceof Identifier) {
return true;
}

if ($arg->unpack) {
return true;
}
}

return false;
}

private function renameMethod(
MethodCall|StaticCall $node,
FunctionNameWithAssertMethods $functionNameWithAssertMethods
Expand Down