Start finalizing composer integration
This commit is contained in:
parent
12a33c4a33
commit
409c6c2f1f
|
@ -6,6 +6,8 @@ use Composer\Composer;
|
|||
use Composer\EventDispatcher\EventSubscriberInterface;
|
||||
use Composer\Installer\InstallerEvent;
|
||||
use Composer\Installer\InstallerEvents;
|
||||
use Composer\Installer\PackageEvent;
|
||||
use Composer\Installer\PackageEvents;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Plugin\PluginInterface;
|
||||
|
||||
|
@ -31,7 +33,7 @@ class Plugin implements PluginInterface, EventSubscriberInterface
|
|||
{
|
||||
$repoManager = $composer->getRepositoryManager();
|
||||
$repos = $repoManager->getRepositories();
|
||||
$repoManager->prependRepository();
|
||||
$repoManager->prependRepository(new Repository($repos[0]));
|
||||
$this->io = $io;
|
||||
}
|
||||
|
||||
|
@ -43,9 +45,15 @@ class Plugin implements PluginInterface, EventSubscriberInterface
|
|||
return [
|
||||
InstallerEvents::PRE_DEPENDENCIES_SOLVING =>
|
||||
['onDependencySolve', 100000],
|
||||
PackageEvents::POST_PACKAGE_INSTALL =>
|
||||
['onInstall', 100000],
|
||||
];
|
||||
}
|
||||
|
||||
public function onInstall(PackageEvent $event): void
|
||||
{
|
||||
var_dumP($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted before composer solves dependencies.
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace Phabel\Composer;
|
||||
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\ComposerRepository;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
|
||||
/**
|
||||
|
@ -100,8 +102,6 @@ class Repository extends ComposerRepository
|
|||
*/
|
||||
$myConfig = $package->getExtra()['phabel'] ?? [];
|
||||
$havePhabel = false;
|
||||
$myConfig['target'] ??= '7.0';
|
||||
/** @var array */
|
||||
foreach ($package->getRequires() as $link) {
|
||||
if ($link->getTarget() === 'phabel/phabel') {
|
||||
$havePhabel = true;
|
||||
|
@ -120,7 +120,7 @@ class Repository extends ComposerRepository
|
|||
$links = [];
|
||||
foreach ($package->getRequires() as $link) {
|
||||
$version = self::CONFIG_PREFIX.\json_encode($config)."\n".($link->getConstraint() ?? '');
|
||||
$links []= new Link($link->getSource(), $link->getTarget(), $version, $link->getDescription());
|
||||
$links []= new Link($link->getSource(), $link->getTarget(), new Constraint('>=', $version), $link->getDescription());
|
||||
}
|
||||
$package->setRequires($links);
|
||||
}
|
||||
|
@ -213,12 +213,8 @@ class Repository extends ComposerRepository
|
|||
continue;
|
||||
}
|
||||
$config = $version['extra']['phabel'] ?? [];
|
||||
if (!isset($config['target'])) {
|
||||
if (isset($version['require']['php'])) {
|
||||
$config['target'] = $version['require']['php'];
|
||||
} else {
|
||||
$config['target'] = '7.0';
|
||||
}
|
||||
if (!isset($config['target']) && isset($version['require']['php'])) {
|
||||
$config['target'] = $version['require']['php'];
|
||||
}
|
||||
foreach ($version['require'] as $package => &$version) {
|
||||
$version = self::CONFIG_PREFIX.\json_encode($config)."\n".$version;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Phabel;
|
||||
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\ErrorHandler\Throwing;
|
||||
use PhpParser\NameContext;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\ArrowFunction;
|
||||
|
@ -23,6 +25,7 @@ use PhpParser\Node\Expr\Variable;
|
|||
use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use SplStack;
|
||||
|
||||
/**
|
||||
|
@ -45,6 +48,12 @@ class Context
|
|||
* @var SplStack<VariableContext>
|
||||
*/
|
||||
public SplStack $variables;
|
||||
/**
|
||||
* Name resolver.
|
||||
*
|
||||
* @var NameResolver
|
||||
*/
|
||||
public NameResolver $nameResolver;
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
@ -54,6 +63,8 @@ class Context
|
|||
$this->parents = new SplStack;
|
||||
/** @var SplStack<VariableContext> */
|
||||
$this->variables = new SplStack;
|
||||
$this->nameResolver = new NameResolver(new Throwing, ['replaceNodes' => false]);
|
||||
$this->nameResolver->beforeTraverse([]);
|
||||
}
|
||||
/**
|
||||
* Push node.
|
||||
|
@ -67,6 +78,8 @@ class Context
|
|||
$this->parents->push($node);
|
||||
if ($node instanceof RootNode) {
|
||||
$this->variables->push(new VariableContext);
|
||||
} else {
|
||||
$this->nameResolver->enterNode($node);
|
||||
}
|
||||
if ($node instanceof FunctionLike) {
|
||||
$variables = \array_fill_keys(
|
||||
|
@ -293,4 +306,14 @@ class Context
|
|||
$subNodeIndex = $parent->getAttribute('currentNodeIndex');
|
||||
\array_splice($parent->{$subNode}, $subNodeIndex+1, 0, $nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets name context
|
||||
*
|
||||
* @return NameContext
|
||||
*/
|
||||
public function getNameContext(): NameContext
|
||||
{
|
||||
return $this->nameResolver->getNameContext();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,72 +92,81 @@ class PluginCache
|
|||
* Get runBefore requirements.
|
||||
*
|
||||
* @param class-string<PluginInterface> $plugin Plugin
|
||||
* @param array $config Config
|
||||
*
|
||||
* @return array<class-string<PluginInterface>, array>
|
||||
* @return array<string, array>
|
||||
* @psalm-return array<class-string<PluginInterface>, array>
|
||||
*/
|
||||
public static function runBefore(string $plugin): array
|
||||
public static function runBefore(string $plugin, array $config): array
|
||||
{
|
||||
/** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
|
||||
static $cache = [];
|
||||
if (isset($cache[$plugin])) {
|
||||
return $cache[$plugin];
|
||||
}
|
||||
return $cache[$plugin] = self::simplify($plugin::runBefore());
|
||||
return $cache[$plugin] = self::simplify($plugin::runBefore($config));
|
||||
}
|
||||
/**
|
||||
* Get runAfter requirements.
|
||||
*
|
||||
* @param class-string<PluginInterface> $plugin Plugin
|
||||
* @param array $config Config
|
||||
*
|
||||
* @return array<class-string<PluginInterface>, array>
|
||||
* @return array<string, array>
|
||||
* @psalm-return array<class-string<PluginInterface>, array>
|
||||
*/
|
||||
public static function runAfter(string $plugin): array
|
||||
public static function runAfter(string $plugin, array $config): array
|
||||
{
|
||||
/** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
|
||||
static $cache = [];
|
||||
if (isset($cache[$plugin])) {
|
||||
return $cache[$plugin];
|
||||
}
|
||||
return $cache[$plugin] = self::simplify($plugin::runAfter());
|
||||
return $cache[$plugin] = self::simplify($plugin::runAfter($config));
|
||||
}
|
||||
/**
|
||||
* Get runWithBefore requirements.
|
||||
*
|
||||
* @param class-string<PluginInterface> $plugin Plugin
|
||||
* @param array $config Config
|
||||
*
|
||||
* @return array<class-string<PluginInterface>, array>
|
||||
* @return array<string, array>
|
||||
* @psalm-return array<class-string<PluginInterface>, array>
|
||||
*/
|
||||
public static function runWithBefore(string $plugin): array
|
||||
public static function runWithBefore(string $plugin, array $config): array
|
||||
{
|
||||
/** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
|
||||
static $cache = [];
|
||||
if (isset($cache[$plugin])) {
|
||||
return $cache[$plugin];
|
||||
}
|
||||
return $cache[$plugin] = self::simplify($plugin::runWithBefore());
|
||||
return $cache[$plugin] = self::simplify($plugin::runWithBefore($config));
|
||||
}
|
||||
/**
|
||||
* Get runWithAfter requirements.
|
||||
*
|
||||
* @param class-string<PluginInterface> $plugin Plugin
|
||||
* @param array $config Config
|
||||
*
|
||||
* @return array<class-string<PluginInterface>, array>
|
||||
* @return array<string, array>
|
||||
* @psalm-return array<class-string<PluginInterface>, array>
|
||||
*/
|
||||
public static function runWithAfter(string $plugin): array
|
||||
public static function runWithAfter(string $plugin, array $config): array
|
||||
{
|
||||
/** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
|
||||
static $cache = [];
|
||||
if (isset($cache[$plugin])) {
|
||||
return $cache[$plugin];
|
||||
}
|
||||
return $cache[$plugin] = self::simplify($plugin::runWithAfter());
|
||||
return $cache[$plugin] = self::simplify($plugin::runWithAfter($config));
|
||||
}
|
||||
/**
|
||||
* Simplify requirements.
|
||||
*
|
||||
* @param (array<class-string<PluginInterface>, array>|class-string<PluginInterface>[]) $requirements Requirements
|
||||
*
|
||||
* @return array<class-string<PluginInterface>, array>
|
||||
* @return array<string, array>
|
||||
* @psalm-return array<class-string<PluginInterface>, array>
|
||||
*/
|
||||
private static function simplify(array $requirements): array
|
||||
{
|
||||
|
|
|
@ -57,10 +57,12 @@ class GraphInternal
|
|||
/**
|
||||
* Add plugin.
|
||||
*
|
||||
* @param class-string<PluginInterface> $plugin Plugin to add
|
||||
* @param array $config Plugin configuration
|
||||
* @param PackageContext $ctx Package context
|
||||
* @param string $plugin Plugin to add
|
||||
* @param array $config Plugin configuration
|
||||
* @param PackageContext $ctx Package context
|
||||
*
|
||||
* @psalm-param class-string<PluginInterface> $plugin Plugin to add
|
||||
*
|
||||
* @return Node[]
|
||||
*/
|
||||
public function addPlugin(string $plugin, array $config, PackageContext $ctx): array
|
||||
|
|
|
@ -38,28 +38,28 @@ class Node
|
|||
/**
|
||||
* Nodes that this node requires.
|
||||
*
|
||||
* @var SplObjectStorage<Node, void>
|
||||
* @var SplObjectStorage<Node>
|
||||
*/
|
||||
private SplObjectStorage $requires;
|
||||
|
||||
/**
|
||||
* Nodes that this node extends.
|
||||
*
|
||||
* @var SplObjectStorage<Node, void>
|
||||
* @var SplObjectStorage<Node>
|
||||
*/
|
||||
private SplObjectStorage $extends;
|
||||
|
||||
/**
|
||||
* Nodes that require this node.
|
||||
*
|
||||
* @var SplObjectStorage<Node, void>
|
||||
* @var SplObjectStorage<Node>
|
||||
*/
|
||||
private SplObjectStorage $requiredBy;
|
||||
|
||||
/**
|
||||
* Nodes that extend this node.
|
||||
*
|
||||
* @var SplObjectStorage<Node, void>
|
||||
* @var SplObjectStorage<Node>
|
||||
*/
|
||||
private SplObjectStorage $extendedBy;
|
||||
|
||||
|
@ -109,22 +109,22 @@ class Node
|
|||
$this->plugin = new Plugins($plugin, $config);
|
||||
|
||||
$this->canBeRequired = PluginCache::canBeRequired($plugin);
|
||||
foreach (PluginCache::runAfter($plugin) as $class => $config) {
|
||||
foreach (PluginCache::runAfter($plugin, $config) as $class => $config) {
|
||||
foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
|
||||
$this->require($node);
|
||||
}
|
||||
}
|
||||
foreach (PluginCache::runBefore($plugin) as $class => $config) {
|
||||
foreach (PluginCache::runBefore($plugin, $config) as $class => $config) {
|
||||
foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
|
||||
$node->require($this);
|
||||
}
|
||||
}
|
||||
foreach (PluginCache::runWithAfter($plugin) as $class => $config) {
|
||||
foreach (PluginCache::runWithAfter($plugin, $config) as $class => $config) {
|
||||
foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
|
||||
$this->extend($node);
|
||||
}
|
||||
}
|
||||
foreach (PluginCache::runWithBefore($plugin) as $class => $config) {
|
||||
foreach (PluginCache::runWithBefore($plugin, $config) as $class => $config) {
|
||||
foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
|
||||
$node->extend($this);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php55\YieldDetector;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill syntaxes of various PHP versions.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php extends Plugin
|
||||
{
|
||||
/**
|
||||
* PHP versions.
|
||||
*/
|
||||
private const VERSIONS = [
|
||||
'55',
|
||||
'56',
|
||||
'70',
|
||||
'71',
|
||||
'72',
|
||||
'73',
|
||||
'74',
|
||||
'80',
|
||||
];
|
||||
/**
|
||||
* Default target.
|
||||
*/
|
||||
private const DEFAULT_TARGET = '70';
|
||||
/**
|
||||
* Get PHP version range to target.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
private static function getRange(array $config): array
|
||||
{
|
||||
$target = $config['target'] ?? PHP_MAJOR_VERSION.PHP_MINOR_VERSION;
|
||||
if (preg_match(":^\D*(\d+\.\d+)\..*:", $config['target'], $matches)) {
|
||||
$target = $matches[1];
|
||||
}
|
||||
$key = \array_search(str_replace('.', '', $target), self::VERSIONS);
|
||||
return \array_slice(
|
||||
self::VERSIONS,
|
||||
$key === false ? self::DEFAULT_TARGET : $key
|
||||
);
|
||||
}
|
||||
public static function composerRequires(array $config): array
|
||||
{
|
||||
return \array_fill_keys(
|
||||
\array_map(fn (string $version): string => "symfony/polyfill-$version", self::getRange($config)),
|
||||
'*'
|
||||
);
|
||||
}
|
||||
public static function runWithAfter(array $config): array
|
||||
{
|
||||
$classes = [];
|
||||
foreach (self::getRange($config) as $version) {
|
||||
foreach (scandir(__DIR__."/Php$version") as $file) {
|
||||
if (substr($file, -4) !== '.php') continue;
|
||||
$class = basename($version, '.php');
|
||||
$classes[$class] = $config[$class] ?? [];
|
||||
}
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php55\YieldDetector;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 5.5 and run on PHP 5.4 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php55 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php55' => '*'];
|
||||
}
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
YieldDetector::class
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php70\AnonymousClassReplacer;
|
||||
use Phabel\Target\Php70\ClosureCallReplacer;
|
||||
use Phabel\Target\Php70\CompoundAccess;
|
||||
use Phabel\Target\Php70\DefineArrayReplacer;
|
||||
use Phabel\Target\Php70\GroupUseReplacer;
|
||||
use Phabel\Target\Php70\IssetExpressionFixer;
|
||||
use Phabel\Target\Php70\NestedExpressionFixer;
|
||||
use Phabel\Target\Php70\NullCoalesceReplacer;
|
||||
use Phabel\Target\Php70\ReservedNameReplacer;
|
||||
use Phabel\Target\Php70\ScalarTypeHints;
|
||||
use Phabel\Target\Php70\SpaceshipOperatorReplacer;
|
||||
use Phabel\Target\Php70\StrictTypesDeclareStatementRemover;
|
||||
use Phabel\Target\Php70\ThrowableReplacer;
|
||||
use Phabel\Target\Php70\YieldFromReturnDetector;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 7.0 and run on PHP 5.6 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php70 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php70' => '*'];
|
||||
}
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
AnonymousClassReplacer::class,
|
||||
ClosureCallReplacer::class,
|
||||
CompoundAccess::class,
|
||||
DefineArrayReplacer::class,
|
||||
GroupUseReplacer::class,
|
||||
NullCoalesceReplacer::class,
|
||||
ReservedNameReplacer::class,
|
||||
ScalarTypeHints::class,
|
||||
SpaceshipOperatorReplacer::class,
|
||||
StrictTypesDeclareStatementRemover::class,
|
||||
ThrowableReplacer::class,
|
||||
YieldFromReturnDetector::class
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php71\ArrayList;
|
||||
use Phabel\Target\Php71\ClassConstantVisibilityModifiersRemover;
|
||||
use Phabel\Target\Php71\IssetExpressionFixer;
|
||||
use Phabel\Target\Php71\IterableHint;
|
||||
use Phabel\Target\Php71\ListKey;
|
||||
use Phabel\Target\Php71\MultipleCatchReplacer;
|
||||
use Phabel\Target\Php71\NestedExpressionFixer;
|
||||
use Phabel\Target\Php71\NullableType;
|
||||
use Phabel\Target\Php71\VoidReturnType;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 7.1 and run on PHP 7.0 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php71 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php71' => '*'];
|
||||
}
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
ArrayList::class,
|
||||
ClassConstantVisibilityModifiersRemover::class,
|
||||
ListKey::class,
|
||||
IterableHint::class,
|
||||
MultipleCatchReplacer::class,
|
||||
VoidReturnType::class,
|
||||
NullableType::class
|
||||
];
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace Phabel\Target\Php71;
|
|||
|
||||
use Phabel\Context;
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php73\ListReference;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php72\IssetExpressionFixer;
|
||||
use Phabel\Target\Php72\NestedExpressionFixer;
|
||||
use Phabel\Target\Php72\ObjectTypeHintReplacer;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 7.2 and run on PHP 7.1 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php72 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php72' => '*'];
|
||||
}
|
||||
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
ObjectTypeHintReplacer::class
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php73\IssetExpressionFixer;
|
||||
use Phabel\Target\Php73\NestedExpressionFixer;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 7.3 and run on PHP 7.2 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php73 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php73' => '*'];
|
||||
}
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php74\ArrayUnpack;
|
||||
use Phabel\Target\Php74\ArrowClosure;
|
||||
use Phabel\Target\Php74\IssetExpressionFixer;
|
||||
use Phabel\Target\Php74\NestedExpressionFixer;
|
||||
use Phabel\Target\Php74\NullCoalesceAssignment;
|
||||
use Phabel\Target\Php74\TypedProperty;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 7.4 and run on PHP 7.3 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php74 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php74' => '*'];
|
||||
}
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
ArrayUnpack::class,
|
||||
ArrowClosure::class,
|
||||
NullCoalesceAssignment::class,
|
||||
TypedProperty::class
|
||||
];
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Phabel\Target\Php74;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php70\NullCoalesceReplacer;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\AssignOp\Coalesce;
|
||||
use PhpParser\Node\Expr\BinaryOp\Coalesce as BinaryOpCoalesce;
|
||||
|
@ -17,4 +18,8 @@ class NullCoalesceAssignment extends Plugin
|
|||
{
|
||||
return new Assign($coalesce->var, new BinaryOpCoalesce($coalesce->var, $coalesce->expr), $coalesce->getAttributes());
|
||||
}
|
||||
public static function runWithBefore(): array
|
||||
{
|
||||
return [NullCoalesceReplacer::class];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target\Php74;
|
||||
|
||||
use Phabel\Context;
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Tools;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Serializable as GlobalSerializable;
|
||||
|
||||
/**
|
||||
* Implement __serialize and __unserialize.
|
||||
*/
|
||||
class Serializable extends Plugin
|
||||
{
|
||||
public function enter(Class_ $class, Context $context): void
|
||||
{
|
||||
/** @var array<string, &ClassMethod> */
|
||||
$methods = [];
|
||||
foreach ($class->stmts as $stmt) {
|
||||
if ($stmt instanceof ClassMethod) {
|
||||
$name = $stmt->name->toLowerString();
|
||||
$methods[$name] = $stmt;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($methods['__serialize']) && !isset($methods['__unserialize'])) {
|
||||
return;
|
||||
}
|
||||
foreach ($class->implements as $name) {
|
||||
$resolved = $context->getNameContext()->getResolvedClassName($name);
|
||||
if ($resolved->toLowerString() === 'serializable' || $name->toLowerString() === 'serializable') {
|
||||
return; // Already implements
|
||||
}
|
||||
}
|
||||
if (isset($methods['__sleep'])) {
|
||||
$methods['__sleep']->name = new Identifier('__phabelSleep');
|
||||
}
|
||||
if (isset($methods['__wakeup'])) {
|
||||
$methods['__wakeup']->name = new Identifier('__phabelWakeup');
|
||||
}
|
||||
|
||||
$class->implements []= new FullyQualified(GlobalSerializable::class);
|
||||
$methods['serialize'] = new ClassM
|
||||
}
|
||||
}
|
|
@ -2,11 +2,33 @@
|
|||
|
||||
namespace Phabel\Target\Php74;
|
||||
|
||||
use Phabel\Context;
|
||||
use Phabel\Plugin;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implement typed properties.
|
||||
*/
|
||||
class TypedProperty extends Plugin
|
||||
{
|
||||
public function enter(Class_ $class, Context $context): void
|
||||
{
|
||||
/** @var Property[] */
|
||||
$typed = [];
|
||||
foreach ($class->stmts as $stmt) {
|
||||
if ($stmt instanceof Property && $stmt->type) {
|
||||
$typed []= $stmt;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($typed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if
|
||||
foreach ($typed as $property) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel\Target;
|
||||
|
||||
use Phabel\Plugin;
|
||||
use Phabel\Target\Php80\IssetExpressionFixer;
|
||||
use Phabel\Target\Php80\NestedExpressionFixer;
|
||||
use Phabel\UnionTypeStripper;
|
||||
|
||||
/**
|
||||
* Makes changes necessary to polyfill PHP 8.0 and run on PHP 7.4 and below.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Php80 extends Plugin
|
||||
{
|
||||
public static function composerRequires(): array
|
||||
{
|
||||
return ['symfony/polyfill-php80' => '*'];
|
||||
}
|
||||
|
||||
public static function runWithAfter(): array
|
||||
{
|
||||
return [
|
||||
IssetExpressionFixer::class,
|
||||
NestedExpressionFixer::class,
|
||||
UnionTypeStripper::class,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Phabel;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\Parser;
|
||||
use PhpParser\ParserFactory;
|
||||
use SplQueue;
|
||||
|
|
Loading…
Reference in New Issue