diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index b8a8e436..4215bb9f 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -18,7 +18,7 @@ jobs: actions: - name: 'Active Classes' - run: vendor/bin/class-leak check config bin src rules --skip-type="Rector\PhpSpecToPHPUnit\Rector\Class_\ImplicitLetInitializationRector" + run: vendor/bin/class-leak check config bin src rules - name: "Composer Analyser" diff --git a/composer.json b/composer.json index 2a71fd3f..a292028e 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "phpstan/extension-installer": "^1.3", "tomasvotruba/class-leak": "^2.0", "tracy/tracy": "^2.10", - "shipmonk/composer-dependency-analyser": "^1.8" + "shipmonk/composer-dependency-analyser": "^1.8", + "symplify/phpstan-extensions": "^12.0" }, "autoload": { "psr-4": { diff --git a/phpstan.neon b/phpstan.neon index b3cb9119..d9bde64e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,14 +9,14 @@ parameters: - rules-tests reportUnmatchedIgnoredErrors: false - treatPhpDocTypesAsCertain: false + errorFormat: symplify excludePaths: - */Fixture/* ignoreErrors: - # bool property + # bool property changed inside another call, false positive - message: '#Negated boolean expression is always true#' path: src/NodeFactory/AssertMethodCallFactory.php @@ -24,8 +24,6 @@ parameters: - '#PHPDoc tag @return contains generic type PhpParser\\Node\\Stmt\\Expression<(.*?)> but class PhpParser\\Node\\Stmt\\Expression is not generic#' # known value - - '#Cannot call method toString\(\) on PhpParser\\Node\\Identifier\|null#' - '#Call to an undefined method PhpParser\\Node\\Expr\|PhpParser\\Node\\Identifier\:\:toString\(\)#' - - - identifier: phpstanApi.instanceofType + - identifier: phpstanApi.instanceofType diff --git a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/implicit_creation.php.inc b/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/implicit_creation.php.inc deleted file mode 100644 index 6595f18c..00000000 --- a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/implicit_creation.php.inc +++ /dev/null @@ -1,36 +0,0 @@ -modify(); - } -} - -?> ------ -justOnce = new \Rector\PhpSpecToPHPUnit\Tests\Rector\Class_\ImplicitLetInitializationRector\Fixture\JustOnce(); - } - public function it_should() - { - $this->modify(); - } -} - -?> diff --git a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_multiple_if_be_constructed.php.inc b/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_multiple_if_be_constructed.php.inc deleted file mode 100644 index 19900f0a..00000000 --- a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_multiple_if_be_constructed.php.inc +++ /dev/null @@ -1,22 +0,0 @@ -beConstructedThrough('some'); - $this->shouldHaveType(Result::class); - } - - public function it_does_again() - { - $item = $this->beConstructedThrough('some'); - $this->shouldHaveType(Result::class); - } -} - - diff --git a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_with_let.php.inc b/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_with_let.php.inc deleted file mode 100644 index 67fd902c..00000000 --- a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/Fixture/skip_with_let.php.inc +++ /dev/null @@ -1,15 +0,0 @@ -someItem = new \stdClass(); - } -} diff --git a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/ImplicitLetInitializationRectorTest.php b/rules-tests/Rector/Class_/ImplicitLetInitializationRector/ImplicitLetInitializationRectorTest.php deleted file mode 100644 index 967afc4c..00000000 --- a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/ImplicitLetInitializationRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/config/configured_rule.php b/rules-tests/Rector/Class_/ImplicitLetInitializationRector/config/configured_rule.php deleted file mode 100644 index 389b9663..00000000 --- a/rules-tests/Rector/Class_/ImplicitLetInitializationRector/config/configured_rule.php +++ /dev/null @@ -1,10 +0,0 @@ -rules([ImplicitLetInitializationRector::class]); -}; diff --git a/rules/Rector/Class_/ImplicitLetInitializationRector.php b/rules/Rector/Class_/ImplicitLetInitializationRector.php deleted file mode 100644 index bed1935e..00000000 --- a/rules/Rector/Class_/ImplicitLetInitializationRector.php +++ /dev/null @@ -1,138 +0,0 @@ -> - */ - public function getNodeTypes(): array - { - return [Class_::class]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - 'Add implicit object property to setUp() PHPUnit method', - [ - new CodeSample( - <<<'CODE_SAMPLE' -use PhpSpec\ObjectBehavior; - -final class SomeTypeSpec extends ObjectBehavior -{ - public function let() - { - $this->run(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PhpSpec\ObjectBehavior; - -final class SomeTypeSpec extends ObjectBehavior -{ - private SomeType $someType; - - protected function setUp(): void - { - $this->someType = new SomeType(); - } - - public function let() - { - $this->someType->run(); - } -} -CODE_SAMPLE - ), - ] - ); - } - - /** - * @param Class_ $node - */ - public function refactor(Node $node): ?Node - { - // just to be sure the method is there - $originalClass = $node->getAttribute(AttributeKey::ORIGINAL_NODE); - - $letClassMethod = $originalClass->getMethod(PhpSpecMethodName::LET); - if ($letClassMethod instanceof ClassMethod) { - return null; - } - - // has be constructed through in every public method - if ($this->hasConstructedThroughInEveryClassMethod($node)) { - return null; - } - - $testedObject = $this->phpSpecRenaming->resolveTestedObject($node); - - $testedObjectProperty = $this->createTestedObjectProperty($testedObject); - - $setUpClassMethod = $this->setUpInstanceFactory->createSetUpClassMethod($testedObject); - $node->stmts = [$testedObjectProperty, $setUpClassMethod, ...(array) $node->stmts]; - - return $node; - } - - private function createTestedObjectProperty(TestedObject $testedObject): Property - { - return $this->nodeFactory->createPrivatePropertyFromNameAndType( - $testedObject->getPropertyName(), - $testedObject->getTestedObjectType() - ); - } - - private function hasConstructedThroughInEveryClassMethod(Class_ $class): bool - { - foreach ($class->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - - if (MethodCallFinder::hasByName($classMethod, PhpSpecMethodName::BE_CONSTRUCTED_WITH)) { - continue; - } - - if (MethodCallFinder::hasByName($classMethod, PhpSpecMethodName::BE_CONSTRUCTED_THROUGH)) { - continue; - } - - return false; - } - - return true; - } -} diff --git a/rules/Rector/Class_/PhpSpecClassToPHPUnitClassRector.php b/rules/Rector/Class_/PhpSpecClassToPHPUnitClassRector.php index 342f1464..efbd4865 100644 --- a/rules/Rector/Class_/PhpSpecClassToPHPUnitClassRector.php +++ b/rules/Rector/Class_/PhpSpecClassToPHPUnitClassRector.php @@ -9,6 +9,7 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; use Rector\PhpSpecToPHPUnit\Naming\PhpSpecRenaming; +use Rector\PHPUnit\Enum\PHPUnitClassName; use Rector\Privatization\NodeManipulator\VisibilityManipulator; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -38,6 +39,10 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { + if (! $node->name instanceof Identifier) { + return null; + } + // skip already renamed /** @var string $className */ $className = $node->name->toString(); @@ -48,7 +53,7 @@ public function refactor(Node $node): ?Node // rename class and parent class $phpunitTestClassName = $this->phpSpecRenaming->createPHPUnitTestClassName($node); $node->name = new Identifier($phpunitTestClassName); - $node->extends = new FullyQualified('PHPUnit\Framework\TestCase'); + $node->extends = new FullyQualified(PHPUnitClassName::TEST_CASE); $this->visibilityManipulator->makeFinal($node); diff --git a/src/DocFactory.php b/src/DocFactory.php index d0110b66..4f0e7d15 100644 --- a/src/DocFactory.php +++ b/src/DocFactory.php @@ -5,6 +5,7 @@ namespace Rector\PhpSpecToPHPUnit; use PhpParser\Comment\Doc; +use Rector\PhpSpecToPHPUnit\Enum\PHPUnitClassName; use Rector\PhpSpecToPHPUnit\ValueObject\ServiceMock; final class DocFactory @@ -14,7 +15,7 @@ public static function createForMockAssign(ServiceMock $serviceMock): Doc $comment = sprintf( "/** @var \%s|\%s $%s */", $serviceMock->getMockClassName(), - 'PHPUnit\Framework\MockObject\MockObject', + PHPUnitClassName::MOCK_OBJECT, $serviceMock->getVariableName() . 'Mock' ); @@ -27,7 +28,7 @@ public static function createForMockProperty(ServiceMock $serviceMock): Doc "/**%s * @var \%s|\%s%s */", PHP_EOL, $serviceMock->getMockClassName(), - 'PHPUnit\Framework\MockObject\MockObject', + PHPUnitClassName::MOCK_OBJECT, PHP_EOL ); diff --git a/src/Enum/PHPUnitClassName.php b/src/Enum/PHPUnitClassName.php new file mode 100644 index 00000000..946b9702 --- /dev/null +++ b/src/Enum/PHPUnitClassName.php @@ -0,0 +1,10 @@ +nodeFactory->createPrivatePropertyFromNameAndType($parameterName, $objectType); }