diff --git a/.github/disabled-workflows/e2e_php74.yaml b/.github/disabled-workflows/e2e_php74.yaml new file mode 100644 index 00000000000..627e932cb09 --- /dev/null +++ b/.github/disabled-workflows/e2e_php74.yaml @@ -0,0 +1,44 @@ +# This workflow runs system tests: Use the Rector application from the source +# checkout to process "fixture" projects in e2e/ directory +# to see if those can be processed successfully +name: End to End tests on PHP 7.4 + +on: + pull_request: + branches: + - main + push: + branches: + - main + +env: + # see https://github.com/composer/composer/issues/9368#issuecomment-718112361 + COMPOSER_ROOT_VERSION: "dev-main" + +jobs: + end_to_end: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + directory: + - 'e2e/php74-parse-static' + + name: End to end test - ${{ matrix.directory }} + + steps: + - uses: actions/checkout@v2 + + - uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + coverage: none + + # run in e2e subdir + - + run: composer install --ansi + working-directory: ${{ matrix.directory }} + + # run e2e test - there should be no reports + - run: vendor/bin/rector --ansi --dry-run + working-directory: ${{ matrix.directory }} diff --git a/.github/workflows/downgrade_phpstan_parser.yaml b/.github/workflows/downgrade_phpstan_parser.yaml new file mode 100644 index 00000000000..b4912110cc5 --- /dev/null +++ b/.github/workflows/downgrade_phpstan_parser.yaml @@ -0,0 +1,27 @@ +# ref https://github.com/rectorphp/rector/issues/6970 +name: Downgrade PHPStan Parser + +on: + pull_request: null + +env: + # see https://github.com/composer/composer/issues/9368#issuecomment-718112361 + COMPOSER_ROOT_VERSION: "dev-main" + +jobs: + downgrade_phpstan_parser: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + # see https://github.com/shivammathur/setup-php + - + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + coverage: none + + - uses: "ramsey/composer-install@v1" + + - run: bin/rector p vendor/clue/ndjson-react/src/Decoder.php --config tests/config/downgrade-phpstan-parser.php --dry-run diff --git a/config/phpstan/parser.neon b/config/phpstan/parser.neon index c9ab4a65bd6..623e87feb66 100644 --- a/config/phpstan/parser.neon +++ b/config/phpstan/parser.neon @@ -10,27 +10,15 @@ services: arguments: originalParser: @rectorParser cachedNodesByStringCountMax: %cache.nodesByStringCountMax% - autowired: no - - cachedRectorSimpleParser: - class: PHPStan\Parser\CachedParser - arguments: - originalParser: @rectorSimpleParser - cachedNodesByStringCountMax: %cache.nodesByStringCountMax% - - rectorSimpleParser: - class: PHPStan\Parser\CleaningParser - arguments: - wrappedParser: @currentPhpVersionSimpleDirectParser - autowired: no + autowired: false pathRoutingParser: - class: Rector\Core\PhpParser\Parser\RectorPathRoutingParser + class: PHPStan\Parser\PathRoutingParser arguments: currentPhpVersionRichParser: @cachedRectorParser - currentPhpVersionSimpleParser: @cachedRectorSimpleParser + currentPhpVersionSimpleParser: @cachedRectorParser php8Parser: @php8Parser - autowired: no + autowired: false rectorParser: class: PHPStan\Parser\RichParser diff --git a/config/services.php b/config/services.php index 8e8832ab523..cf13e566b2c 100644 --- a/config/services.php +++ b/config/services.php @@ -72,6 +72,7 @@ return static function (ContainerConfigurator $containerConfigurator): void { __DIR__ . '/../src/PhpParser/ValueObject', __DIR__ . '/../src/functions', __DIR__ . '/../src/constants.php', + ]); $services->alias(Application::class, ConsoleApplication::class); diff --git a/e2e/php74-parse-static/composer.json b/e2e/php74-parse-static/composer.json new file mode 100644 index 00000000000..4b8b7475bb8 --- /dev/null +++ b/e2e/php74-parse-static/composer.json @@ -0,0 +1,11 @@ +{ + "require": { + "php": "7.4.*", + "api-platform/core": "^2.6", + "symfony/framework-bundle": "^5.4", + "symfony/http-client": "^5.4" + }, + "require-dev": { + "rector/rector": "dev-main" + } +} diff --git a/e2e/php74-parse-static/rector.php b/e2e/php74-parse-static/rector.php new file mode 100644 index 00000000000..01a79a9eb32 --- /dev/null +++ b/e2e/php74-parse-static/rector.php @@ -0,0 +1,19 @@ +parameters(); + + $parameters->set(Option::PARALLEL, true); + $parameters->set(Option::PATHS, [ + __DIR__ . '/tests', + ]); + + $services = $containerConfigurator->services(); + $services->set(DowngradeJsonDecodeNullAssociativeArgRector::class); +}; diff --git a/e2e/php74-parse-static/tests/ApiTest.php b/e2e/php74-parse-static/tests/ApiTest.php new file mode 100644 index 00000000000..b58fd237afd --- /dev/null +++ b/e2e/php74-parse-static/tests/ApiTest.php @@ -0,0 +1,15 @@ + [ - __DIR__ . '/src/PhpParser/Parser/RectorPathRoutingParser.php', - ], - // test paths '*/tests/**/Fixture/*', '*/rules-tests/**/Fixture/*', diff --git a/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/array_assoc.php.inc b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/array_assoc.php.inc new file mode 100644 index 00000000000..17fd2b5e3c8 --- /dev/null +++ b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/array_assoc.php.inc @@ -0,0 +1,27 @@ + +----- + diff --git a/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/clue_json_decode.php.inc b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/clue_json_decode.php.inc new file mode 100644 index 00000000000..56b135fe351 --- /dev/null +++ b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/clue_json_decode.php.inc @@ -0,0 +1,49 @@ +options === 0) { + $data = \json_decode($data, $this->assoc, $this->depth); + } else { + $data = \json_decode($data, $this->assoc, $this->depth, $this->options); + } + } +} + +?> +----- +options === 0) { + $data = \json_decode($data, $this->assoc === null ?: $this->assoc, $this->depth); + } else { + $data = \json_decode($data, $this->assoc === null ?: $this->assoc, $this->depth, $this->options); + } + } +} + +?> diff --git a/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/possibly_null.php.inc b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/possibly_null.php.inc index e75ff048eee..f71185f7552 100644 --- a/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/possibly_null.php.inc +++ b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/possibly_null.php.inc @@ -24,10 +24,7 @@ class PossiblyNull { function run(string $json, ?bool $associative) { - if ($associative === null) { - $associative = true; - } - $value = json_decode($json, $associative); + $value = json_decode($json, $associative === null ?: $associative); } } diff --git a/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/skip_already_downgraded.php.inc b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/skip_already_downgraded.php.inc new file mode 100644 index 00000000000..a93aec9f9fb --- /dev/null +++ b/rules-tests/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector/Fixture/skip_already_downgraded.php.inc @@ -0,0 +1,13 @@ +assoc = $assoc; + } + + public function run($data) + { + $data = \json_decode($data, $this->assoc, $this->depth); + } +} diff --git a/rules/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector.php b/rules/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector.php index a477305e7d0..013ff2fa997 100644 --- a/rules/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector.php +++ b/rules/DowngradePhp72/Rector/FuncCall/DowngradeJsonDecodeNullAssociativeArgRector.php @@ -5,31 +5,25 @@ declare(strict_types=1); namespace Rector\DowngradePhp72\Rector\FuncCall; use PhpParser\Node; -use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\BinaryOp\Identical; -use PhpParser\Node\Expr\Cast\Bool_; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Expr\FuncCall; -use PhpParser\Node\Expr\PropertyFetch; -use PhpParser\Node\Expr\StaticPropertyFetch; -use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Stmt\Expression; +use PhpParser\Node\Expr\Ternary; use PHPStan\Type\BooleanType; use Rector\Core\NodeAnalyzer\ArgsAnalyzer; -use Rector\Core\NodeManipulator\IfManipulator; use Rector\Core\Rector\AbstractRector; -use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradeJsonDecodeNullAssociativeArgRector\DowngradeJsonDecodeNullAssociativeArgRectorTest + * + * @changelog https://3v4l.org/b1mA6 */ final class DowngradeJsonDecodeNullAssociativeArgRector extends AbstractRector { public function __construct( private readonly ArgsAnalyzer $argsAnalyzer, - private readonly IfManipulator $ifManipulator ) { } @@ -38,8 +32,6 @@ final class DowngradeJsonDecodeNullAssociativeArgRector extends AbstractRector return new RuleDefinition('Downgrade json_decode() with null associative argument function', [ new CodeSample( <<<'CODE_SAMPLE' -declare(strict_types=1); - function exactlyNull(string $json) { $value = json_decode($json, null); @@ -53,8 +45,6 @@ CODE_SAMPLE , <<<'CODE_SAMPLE' -declare(strict_types=1); - function exactlyNull(string $json) { $value = json_decode($json, true); @@ -62,10 +52,7 @@ function exactlyNull(string $json) function possiblyNull(string $json, ?bool $associative) { - if ($associative === null) { - $associative = true; - } - $value = json_decode($json, $associative); + $value = json_decode($json, $associative === null ?: $associative); } CODE_SAMPLE ), @@ -100,35 +87,25 @@ CODE_SAMPLE $associativeValue = $args[1]->value; - if ($associativeValue instanceof Bool_) { + // already converted + if ($associativeValue instanceof Ternary && $associativeValue->if === null) { return null; } - $type = $this->nodeTypeResolver->getType($associativeValue); - - if ($type instanceof BooleanType) { + $associativeValueType = $this->nodeTypeResolver->getType($associativeValue); + if ($associativeValueType instanceof BooleanType) { return null; } if ($associativeValue instanceof ConstFetch && $this->valueResolver->isNull($associativeValue)) { - $node->args[1]->value = $this->nodeFactory->createTrue(); + $args[1]->value = $this->nodeFactory->createTrue(); return $node; } - if (! in_array( - $associativeValue::class, - [Variable::class, PropertyFetch::class, StaticPropertyFetch::class], - true - )) { - return null; - } - - $currentExpression = $node->getAttribute(AttributeKey::CURRENT_STATEMENT); - $if = $this->ifManipulator->createIfExpr( - new Identical($associativeValue, $this->nodeFactory->createNull()), - new Expression(new Assign($associativeValue, $this->nodeFactory->createTrue())) - ); - $this->nodesToAddCollector->addNodeBeforeNode($if, $currentExpression); + // add conditional ternary + $nullIdentical = new Identical($associativeValue, $this->nodeFactory->createNull()); + $ternary = new Ternary($nullIdentical, null, $associativeValue); + $args[1]->value = $ternary; return $node; } diff --git a/src/PhpParser/Parser/RectorPathRoutingParser.php b/src/PhpParser/Parser/RectorPathRoutingParser.php deleted file mode 100644 index a698ec73b49..00000000000 --- a/src/PhpParser/Parser/RectorPathRoutingParser.php +++ /dev/null @@ -1,43 +0,0 @@ -currentPhpVersionRichParser = $currentPhpVersionRichParser; - parent::__construct($fileHelper, $currentPhpVersionRichParser, $currentPhpVersionSimpleParser, $php8Parser); - } - - /** - * @return Stmt[] - */ - public function parseFile(string $file): array - { - // for tests, always parse nodes with directly rich parser to be aware of types - if (defined('PHPUNIT_COMPOSER_INSTALL')) { - return $this->currentPhpVersionRichParser->parseFile($file); - } - - return parent::parseFile($file); - } -} diff --git a/tests/config/downgrade-phpstan-parser.php b/tests/config/downgrade-phpstan-parser.php new file mode 100644 index 00000000000..ac943738d35 --- /dev/null +++ b/tests/config/downgrade-phpstan-parser.php @@ -0,0 +1,11 @@ +services(); + $services->set(DowngradeJsonDecodeNullAssociativeArgRector::class); +};