Skip to content

Commit

Permalink
[Downgrade] Add composer platform check (#4721)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba authored Nov 27, 2020
1 parent dade407 commit d962e3f
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 2 deletions.
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@
"Rector\\Twig\\": "rules/twig/src",
"Rector\\TypeDeclaration\\": "rules/type-declaration/src",
"Rector\\VendorLocker\\": "packages/vendor-locker/src",
"Rector\\Carbon\\": "rules/carbon/src"
"Rector\\Carbon\\": "rules/carbon/src",
"Rector\\Downgrade\\": "rules/downgrade/src"
}
},
"autoload-dev": {
Expand Down Expand Up @@ -281,7 +282,8 @@
"Rector\\Utils\\PHPStanAttributeTypeSyncer\\": "utils/phpstan-attribute-type-syncer/src",
"Rector\\Utils\\PHPStanStaticTypeMapperChecker\\": "utils/phpstan-static-type-mapper-checker/src",
"Rector\\Utils\\ProjectValidator\\": "utils/project-validator/src",
"Rector\\Carbon\\Tests\\": "rules/carbon/tests"
"Rector\\Carbon\\Tests\\": "rules/carbon/tests",
"Rector\\Downgrade\\Tests\\": "rules/downgrade/tests"
}
},
"scripts": {
Expand Down
5 changes: 5 additions & 0 deletions config/set/downgrade-php71.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\DowngradePhp71\Rector\ClassConst\DowngradeClassConstantVisibilityRector;
use Rector\DowngradePhp71\Rector\FunctionLike\DowngradeNullableTypeParamDeclarationRector;
use Rector\DowngradePhp71\Rector\FunctionLike\DowngradeNullableTypeReturnDeclarationRector;
Expand All @@ -14,4 +15,8 @@
$services->set(DowngradeNullableTypeReturnDeclarationRector::class);
$services->set(DowngradeVoidTypeReturnDeclarationRector::class);
$services->set(DowngradeClassConstantVisibilityRector::class);
$services->set(ChangePhpVersionInPlatformCheckRector::class)
->call('configure', [[
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 70100,
]]);
};
5 changes: 5 additions & 0 deletions config/set/downgrade-php72.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeParamObjectTypeDeclarationRector;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeReturnObjectTypeDeclarationRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
Expand All @@ -10,4 +11,8 @@
$services = $containerConfigurator->services();
$services->set(DowngradeParamObjectTypeDeclarationRector::class);
$services->set(DowngradeReturnObjectTypeDeclarationRector::class);
$services->set(ChangePhpVersionInPlatformCheckRector::class)
->call('configure', [[
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 70200,
]]);
};
5 changes: 5 additions & 0 deletions config/set/downgrade-php73.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\DowngradePhp73\Rector\List_\DowngradeListReferenceAssignmentRector;
use Rector\DowngradePhp73\Rector\String_\DowngradeFlexibleHeredocSyntaxRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
Expand All @@ -10,4 +11,8 @@
$services = $containerConfigurator->services();
$services->set(DowngradeFlexibleHeredocSyntaxRector::class);
$services->set(DowngradeListReferenceAssignmentRector::class);
$services->set(ChangePhpVersionInPlatformCheckRector::class)
->call('configure', [[
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 70300,
]]);
};
5 changes: 5 additions & 0 deletions config/set/downgrade-php74.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\DowngradePhp74\Rector\Array_\DowngradeArraySpreadRector;
use Rector\DowngradePhp74\Rector\ArrowFunction\ArrowFunctionToAnonymousFunctionRector;
use Rector\DowngradePhp74\Rector\Coalesce\DowngradeNullCoalescingOperatorRector;
Expand All @@ -20,4 +21,8 @@
$services->set(DowngradeStripTagsCallWithArrayRector::class);
$services->set(DowngradeArraySpreadRector::class);
$services->set(DowngradeArrayMergeCallWithoutArgumentsRector::class);
$services->set(ChangePhpVersionInPlatformCheckRector::class)
->call('configure', [[
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 70400,
]]);
};
5 changes: 5 additions & 0 deletions config/set/downgrade-php80.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeParamMixedTypeDeclarationRector;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnMixedTypeDeclarationRector;
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnStaticTypeDeclarationRector;
Expand All @@ -18,4 +19,8 @@
$services->set(DowngradeParamMixedTypeDeclarationRector::class);
$services->set(DowngradeReturnMixedTypeDeclarationRector::class);
$services->set(DowngradeReturnStaticTypeDeclarationRector::class);
$services->set(ChangePhpVersionInPlatformCheckRector::class)
->call('configure', [[
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 80000,
]]);
};
1 change: 1 addition & 0 deletions rector-ci.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
'*/Fixture/*',
'*/Source/*',
'*/Expected/*',

__DIR__ . '/packages/doctrine-annotation-generated/src',
// template files
__DIR__ . '/packages/rector-generator/templates',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

declare(strict_types=1);

namespace Rector\Downgrade\Rector\LNumber;

use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Greater;
use PhpParser\Node\Expr\BinaryOp\GreaterOrEqual;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Util\PhpVersionFactory;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;

/**
* @see https://php.watch/articles/composer-platform-check
* @see https://getcomposer.org/doc/06-config.md#platform-check
*
* @see \Rector\Downgrade\Tests\Rector\LNumber\ChangePhpVersionInPlatformCheckRector\ChangePhpVersionInPlatformCheckRectorTest
*/
final class ChangePhpVersionInPlatformCheckRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var string
*/
public const TARGET_PHP_VERSION = 'target_php_version';

/**
* @see https://regex101.com/r/oVWPoe/1/
* @var string
*/
private const PHP_VERSION_REGEX = '#(?<sign>>=|>) (?<version>\d\.\d\.\d)#';

/**
* @var int
*/
private $targetPhpVersion;

/**
* @var PhpVersionFactory
*/
private $phpVersionFactory;

public function __construct(PhpVersionFactory $phpVersionFactory)
{
$this->phpVersionFactory = $phpVersionFactory;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change `vendor/composer/platform_check.php` to desired minimal PHP version', [
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
$issues = [];
if (!(PHP_VERSION_ID >= 70300)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$issues = [];
if (!(PHP_VERSION_ID >= 70100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.0". You are running ' . PHP_VERSION . '.';
}
CODE_SAMPLE
,
[
self::TARGET_PHP_VERSION => 70100,
]
),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [LNumber::class, String_::class];
}

/**
* @param LNumber|String_ $node
*/
public function refactor(Node $node): ?Node
{
if ($node instanceof LNumber) {
return $this->refactorLNumber($node);
}

if ($node instanceof String_) {
return $this->refactorString($node);
}

return null;
}

/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
$targetPhpVersion = $configuration[self::TARGET_PHP_VERSION] ?? null;
Assert::integer($targetPhpVersion);

$this->targetPhpVersion = $targetPhpVersion;
}

private function refactorLNumber(LNumber $lNumber): ?LNumber
{
if (Strings::length((string) $lNumber->value) !== 5) {
return null;
}

$parent = $lNumber->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Greater && ! $parent instanceof GreaterOrEqual) {
return null;
}

return new LNumber($this->targetPhpVersion);
}

private function refactorString(String_ $string): ?String_
{
$match = Strings::match($string->value, self::PHP_VERSION_REGEX);
if ($match === null) {
return null;
}

$stringPhpVersion = $this->phpVersionFactory->createStringVersion($this->targetPhpVersion);
$changedContent = Strings::replace($string->value, self::PHP_VERSION_REGEX, function (array $match) use (
$stringPhpVersion
): string {
return $match['sign'] . ' ' . $stringPhpVersion;
});

if ($string->value === $changedContent) {
return null;
}

return new String_($changedContent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Rector\Downgrade\Tests\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;

use Iterator;
use Rector\Downgrade\Rector\LNumber\ChangePhpVersionInPlatformCheckRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class ChangePhpVersionInPlatformCheckRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [
ChangePhpVersionInPlatformCheckRector::class => [
ChangePhpVersionInPlatformCheckRector::TARGET_PHP_VERSION => 70100,
],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Rector\Downgrade\Tests\Rector\LNumber\ChangePhpVersionInPlatformCheckRector\Fixture;

$issues = [];

if (!(PHP_VERSION_ID >= 70300)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
}

?>
-----
<?php

namespace Rector\Downgrade\Tests\Rector\LNumber\ChangePhpVersionInPlatformCheckRector\Fixture;

$issues = [];

if (!(PHP_VERSION_ID >= 70100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1". You are running ' . PHP_VERSION . '.';
}

?>
8 changes: 8 additions & 0 deletions src/Util/PhpVersionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Rector\Core\Util;

use PHPStan\Php\PhpVersion;

final class PhpVersionFactory
{
public function createIntVersion(string $version): int
Expand All @@ -26,4 +28,10 @@ public function createIntVersion(string $version): int

return (int) $version;
}

public function createStringVersion(int $version): string
{
$phpVersion = new PhpVersion($version);
return $phpVersion->getVersionString();
}
}

0 comments on commit d962e3f

Please sign in to comment.