Finalize php5.6 transforms
This commit is contained in:
parent
128977ef7e
commit
9b35d45048
|
@ -2,9 +2,22 @@
|
|||
|
||||
namespace Phabel;
|
||||
|
||||
use SplStack;
|
||||
|
||||
/**
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @license MIT
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
/**
|
||||
* Parent nodes stack
|
||||
*
|
||||
* @var SplStack<Node>
|
||||
*/
|
||||
public SplStack $parents;
|
||||
public function __construct()
|
||||
{
|
||||
$this->parents = new SplStack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Phabel;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
/**
|
||||
* Root node
|
||||
*/
|
||||
class RootNode extends NodeAbstract
|
||||
{
|
||||
/**
|
||||
* Children
|
||||
*
|
||||
* @var Node[]
|
||||
*/
|
||||
public $stmts = [];
|
||||
public function __construct(array $stmts, array $attributes = [])
|
||||
{
|
||||
$this->stmts = $stmts;
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
public function getSubNodeNames(): array
|
||||
{
|
||||
return ['stmts'];
|
||||
}
|
||||
public function getType(): string
|
||||
{
|
||||
return 'rootNode';
|
||||
}
|
||||
}
|
|
@ -2,44 +2,71 @@
|
|||
|
||||
namespace Phabel\Target\Php70;
|
||||
|
||||
use Phabel\Context;
|
||||
use Phabel\Plugin;
|
||||
use Phabel\RootNode;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
|
||||
class AnonymousClassReplacer extends Plugin
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
* Anonymous class count.
|
||||
*/
|
||||
protected $anonymousClassNodes = [];
|
||||
public static $count = 0;
|
||||
private int $count = 0;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Current file name hash.
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
if (!$node instanceof Node\Expr\New_) {
|
||||
return;
|
||||
}
|
||||
private string $fileName = '';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function shouldRunFile(string $file): bool
|
||||
{
|
||||
$this->fileName = \hash('sha256', $file);
|
||||
return parent::shouldRunFile($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave new.
|
||||
*
|
||||
* @param New_ $node New stmt
|
||||
* @param Context $ctx Context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function leaveNew(New_ $node, Context $ctx): void
|
||||
{
|
||||
$classNode = $node->class;
|
||||
if (!$classNode instanceof Node\Stmt\Class_) {
|
||||
return;
|
||||
}
|
||||
|
||||
$newClassName = 'AnonymousClass'.(self::$count++);
|
||||
$classNode->name = 'PhabelAnonymousClass'.$this->fileName.($this->count++);
|
||||
|
||||
$classNode->name = $newClassName;
|
||||
|
||||
$this->anonymousClassNodes[] = $classNode;
|
||||
|
||||
// Generate new code that instantiate our new class
|
||||
$newNode = new Node\Expr\New_(
|
||||
new Node\Expr\ConstFetch(
|
||||
new Node\Name($newClassName)
|
||||
),
|
||||
$node->args
|
||||
$node->class = new Node\Expr\ConstFetch(
|
||||
new Node\Name($classNode->name)
|
||||
);
|
||||
|
||||
return $newNode;
|
||||
$prevNode = $node;
|
||||
foreach ($ctx->parents as $node) {
|
||||
if ($node instanceof Namespace_ || $node instanceof RootNode) {
|
||||
$foundIndex = -1;
|
||||
foreach ($node->stmts as $index => $curNode) {
|
||||
if ($curNode === $prevNode) {
|
||||
$foundIndex = $index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($foundIndex >= 0) {
|
||||
\array_splice($node->stmts, $foundIndex, 0, [$classNode]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$prevNode = $node;
|
||||
}
|
||||
throw new \RuntimeException('Could not find hook for inserting anonymous class!');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,23 +94,10 @@ class Traverser
|
|||
} elseif (!$reducedQueue->count()) {
|
||||
return;
|
||||
}
|
||||
$ast = $this->parser->parse(\file_get_contents($file));
|
||||
$ast = new RootNode($this->parser->parse(\file_get_contents($file)));
|
||||
$context = new Context;
|
||||
foreach ($reducedQueue as $queue) {
|
||||
$this->traverseArray($ast, $queue);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Traverse array of nodes.
|
||||
*
|
||||
* @param Node[] $nodes Nodes
|
||||
* @param SplQueue<Plugin> $plugins Plugins
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function traverseArray(array &$nodes, SplQueue $plugins): void
|
||||
{
|
||||
foreach ($nodes as &$node) {
|
||||
$this->traverseNode($node, $plugins);
|
||||
$this->traverseNode($ast, $queue, $context);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -118,9 +105,11 @@ class Traverser
|
|||
*
|
||||
* @param Node &$node Node
|
||||
* @param SplQueue<Plugin> $plugins Plugins
|
||||
* @param Context $context Context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function traverseNode(Node &$node, SplQueue $plugins): void
|
||||
public function traverseNode(Node &$node, SplQueue $plugins, Context $context): void
|
||||
{
|
||||
foreach ($plugins as $plugin) {
|
||||
foreach (PluginCache::enterMethods(\get_class($plugin)) as $type => $methods) {
|
||||
|
@ -128,7 +117,7 @@ class Traverser
|
|||
continue;
|
||||
}
|
||||
foreach ($methods as $method) {
|
||||
$result = $plugin->{$method}($node);
|
||||
$result = $plugin->{$method}($node, $context);
|
||||
if ($result instanceof Node) {
|
||||
if (!$result instanceof $node) {
|
||||
$node = $result;
|
||||
|
@ -139,21 +128,25 @@ class Traverser
|
|||
}
|
||||
}
|
||||
}
|
||||
$context->parents->push($node);
|
||||
foreach ($node->getSubNodeNames() as $name) {
|
||||
$subNode = &$node->{$name};
|
||||
if (\is_array($subNode)) {
|
||||
$this->traverseArray($subNode, $plugins);
|
||||
foreach ($subNode as &$subNodeNode) {
|
||||
$this->traverseNode($subNodeNode, $plugins, $context);
|
||||
}
|
||||
} else {
|
||||
$this->traverseNode($subNode, $plugins);
|
||||
$this->traverseNode($subNode, $plugins, $context);
|
||||
}
|
||||
}
|
||||
$context->parents->pop();
|
||||
foreach ($plugins as $plugin) {
|
||||
foreach (PluginCache::leaveMethods(\get_class($plugin)) as $type => $methods) {
|
||||
if (!$node instanceof $type) {
|
||||
continue;
|
||||
}
|
||||
foreach ($methods as $method) {
|
||||
$result = $plugin->{$method}($node);
|
||||
$result = $plugin->{$method}($node, $context);
|
||||
if ($result instanceof Node) {
|
||||
if (!$result instanceof $node) {
|
||||
$node = $result;
|
||||
|
|
Loading…
Reference in New Issue