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
29 changes: 0 additions & 29 deletions .github/workflows/compat_test.yaml

This file was deleted.

60 changes: 60 additions & 0 deletions .github/workflows/phpunit_and_phpstan_autoload_compat_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# see https://github.com/rectorphp/rector/issues/9416
# compat tests project lives in /compat-tests
name: PHPUnit and PHPStan Autoload Compat Test

on:
push:
branches:
- main
pull_request: null
schedule:
- cron: '0 6 * * *'

jobs:
compat_test:
strategy:
fail-fast: false
matrix:
actions:
-
name: 'Rector dev + PHPUnit 10'
run: composer require "phpunit/phpunit:10.*" -W
php: 8.2
-
name: 'Rector dev + PHPUnit 11'
run: composer require "phpunit/phpunit:11.*" -W
php: 8.2
-
name: 'Rector dev + PHPUnit 12'
run: composer require "phpunit/phpunit:12.*" -W
php: 8.3

name: ${{ matrix.actions.name }}

runs-on: ubuntu-latest

defaults:
run:
working-directory: compat-tests

steps:
- uses: actions/checkout@v4

-
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.actions.php }}
coverage: none

-
uses: "ramsey/composer-install@v4"
with:
working-directory: compat-tests

- run: ${{ matrix.actions.run }}

- run: vendor/bin/phpunit tests/Rector

- run: vendor/bin/phpunit tests/PHPStan

- run: vendor/bin/phpunit
9 changes: 9 additions & 0 deletions compat-tests/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
4 changes: 4 additions & 0 deletions compat-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
composer.lock
/vendor

.phpunit.result.cache
22 changes: 22 additions & 0 deletions compat-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Rector Compatibility Tests

A small test harness that verifies [Rector](https://github.com/rectorphp/rector) keeps working alongside other tools in the PHP static-analysis ecosystem.

It runs a minimal real-world setup — a custom Rector rule, a custom PHPStan rule, and a PHPUnit test suite — against multiple combinations of dependencies in CI, to catch breakage early.

## What it checks

* A custom **Rector** rule (`MakeClassFinalRector`, `UseGetArgRector`) loads and applies correctly.
* A custom **PHPStan** rule (`CustomPHPStanRule`) loads and runs alongside Rector.
* **PHPUnit 10, 11, and 12** all work with Rector's preloaded dependencies.
* Manually including **`nikic/php-parser`** in user code does not conflict with the copy Rector ships.
* `rector-laravel` + `nikic/php-parser` upgrade scenarios run cleanly (see [rectorphp/rector#9470](https://github.com/rectorphp/rector/issues/9470)).

This project lives inside `rector/rector-src` (under `compat-tests/`) and pulls in `rector/rector:dev-main` as a downstream dependency, so the compat suite is maintained in one place. It mirrors the standalone [rectorphp/rector-compat-tests](https://github.com/rectorphp/rector-compat-tests).

## How it runs

GitHub Actions runs the matrix daily (`0 6 * * *`) and on every push/PR, from the repository root `.github/workflows`:

* `compat_test.yaml` — Rector dev + PHPUnit 10 / 11 / 12
* `rector_laravel_rector_dev.yaml` — Rector + rector-laravel + php-parser
24 changes: 24 additions & 0 deletions compat-tests/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "rector/rector-compat-tests",
"license": "MIT",
"description": "Tests for compatibility with PHPStand and PHPUnit preload magic",
"require-dev": {
"php": "^8.2",
"phpunit/phpunit": "10.*|11.*|12.*",
"nikic/php-parser": "5.4.*|5.5.*|5.6.*|5.7.*",
"rector/rector": "dev-main as 2.4.4",
"phpstan/phpstan": "^2.2",
"driftingly/rector-laravel": "^2.4"
},
"autoload": {
"psr-4": {
"Rector\\RectorCompatTests\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Rector\\RectorCompatTests\\Tests\\": "tests",
"Fixture\\": "fixture"
}
}
}
11 changes: 11 additions & 0 deletions compat-tests/fixture/FixtureWithFuncCall.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Fixture;

final class FixtureWithFuncCall
{
public function run(): int
{
return strlen('hello');
}
}
14 changes: 14 additions & 0 deletions compat-tests/phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Project Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
17 changes: 17 additions & 0 deletions compat-tests/rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\RectorCompatTests\Rector\UseGetArgRector;

return RectorConfig::configure()
->withPaths([
__DIR__ . '/src',
__DIR__ . '/tests',
__DIR__ . '/fixture',
])
->withRules([UseGetArgRector::class])
->withTypeCoverageLevel(0)
->withDeadCodeLevel(0)
->withCodeQualityLevel(0);
42 changes: 42 additions & 0 deletions compat-tests/src/PHPStan/CustomPHPStanRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Rector\RectorCompatTests\PHPStan;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;

/**
* @implements Rule<Class_>
*/
final class CustomPHPStanRule implements Rule
{
public const ERROR_MESSAGE = 'Class "%s" is not final.';

public function getNodeType(): string
{
return Class_::class;
}

/**
* @param Class_ $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->isFinal()) {
return [];
}

$ruleErrorMessage = RuleErrorBuilder::message(
sprintf(self::ERROR_MESSAGE, $node->name->toString())
)->build();

return [$ruleErrorMessage];
}
}
35 changes: 35 additions & 0 deletions compat-tests/src/Rector/MakeClassFinalRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Rector\RectorCompatTests\Rector;

use PhpParser\Modifiers;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Rector\AbstractRector;

final class MakeClassFinalRector extends AbstractRector
{
/**
* @return array<class-string<Class_>>
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node)
{
if ($node->isFinal()) {
return null;
}

$node->flags |= Modifiers::FINAL;

return $node;
}
}
41 changes: 41 additions & 0 deletions compat-tests/src/Rector/UseGetArgRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Rector\RectorCompatTests\Rector;

use PhpParser\Modifiers;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Function_;
use Rector\Rector\AbstractRector;

final class UseGetArgRector extends AbstractRector
{
/**
* @return array<class-string<Class_>>
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
}

/**
* @param FuncCall $node
*/
public function refactor(Node $node)
{
// here we should load Rector's php-parser 5.6, that already has getArg() method
$firstArg = $node->getArg('', 0);
if (! $firstArg instanceof Arg) {
return null;;
}

$firstArg->value = new String_('changed_value');

return $node;
}
}
20 changes: 20 additions & 0 deletions compat-tests/tests/ConflictingPhpParserLibraryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php declare(strict_types=1);

namespace BBurnichon\RectorIssue9437\Tests;

use PHPUnit\Framework\TestCase;
use PHPUnit\Runner\Version;

final class ConflictingPhpParserLibraryTest extends TestCase
{
public function testItShouldNotConflictWhenIncludingPhpParserManually(): void
{
if (Version::id() >= 12) {
$this->markTestSkipped('This test requires PHPUnit < 12');
}

include_once dirname(__DIR__, 1) . '/vendor/nikic/php-parser/lib/PhpParser/Parser.php';

$this->assertTrue(true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Rector\RectorCompatTests\Tests\PHPStan\CustomPHPStanRule;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use Rector\RectorCompatTests\PHPStan\CustomPHPStanRule;

final class CustomPHPStanRuleTest extends RuleTestCase
{
public function testRule(): void
{
$this->analyse([__DIR__ . '/Fixture/NonFinalClass.php'], [
[sprintf(CustomPHPStanRule::ERROR_MESSAGE, "NonFinalClass"), 7]
]);
}

protected function getRule(): Rule
{
return new CustomPHPStanRule();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Rector\RectorCompatTests\Tests\PHPStan\CustomPHPStanRule\Fixture;

class NonFinalClass
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Rector\RectorCompatTests\Tests\Rector\MakeClassFinalRector\Fixture;

class SomeNonFinalClass
{
}

?>
-----
<?php

namespace Rector\RectorCompatTests\Tests\Rector\MakeClassFinalRector\Fixture;

final class SomeNonFinalClass
{
}

?>
Loading
Loading