add EventDispatcher

This commit is contained in:
TomasVotruba 2017-08-20 01:46:12 +02:00
parent d8d68ba767
commit 40c7d5366e
9 changed files with 149 additions and 18 deletions

View File

@ -11,7 +11,8 @@
"symfony/console": "^3.3",
"symfony/dependency-injection": "^3.3",
"nikic/php-parser": "4.0.x-dev as 3.0.2",
"nette/utils": "^2.4"
"nette/utils": "^2.4",
"symfony/event-dispatcher": "^3.3"
},
"require-dev": {
"phpunit/phpunit": "^6.2",
@ -37,5 +38,8 @@
"check-cs": "ecs check bin src tests",
"fix-cs": "ecs check bin src tests --fix",
"phpstan": "phpstan analyse bin src tests --level max --configuration phpstan.neon"
},
"config": {
"sort-packages": true
}
}

View File

@ -4,7 +4,7 @@ namespace Rector\Application;
use PhpParser\Lexer;
use PhpParser\NodeTraverser;
use PhpParser\Parser;
use Rector\Contract\Parser\ParserInterface;
use Rector\NodeTraverser\CloningNodeTraverser;
use Rector\Printer\FormatPerservingPrinter;
use SplFileInfo;
@ -12,7 +12,7 @@ use SplFileInfo;
final class FileProcessor
{
/**
* @var Parser
* @var ParserInterface
*/
private $parser;
@ -37,7 +37,7 @@ final class FileProcessor
private $cloningNodeTraverser;
public function __construct(
Parser $parser,
ParserInterface $parser,
FormatPerservingPrinter $codeStyledPrinter,
Lexer $lexer,
NodeTraverser $nodeTraverser,
@ -62,8 +62,7 @@ final class FileProcessor
public function processFile(SplFileInfo $file): void
{
$fileContent = file_get_contents($file->getRealPath());
$oldStmts = $this->parser->parse($fileContent);
$oldStmts = $this->parser->parseFile($file->getRealPath());
if ($oldStmts === null) {
return;
}

View File

@ -8,6 +8,8 @@ use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symplify\PackageBuilder\Adapter\Symfony\DependencyInjection\DefinitionCollector;
final class CollectorCompilerPass implements CompilerPassInterface
@ -16,6 +18,7 @@ final class CollectorCompilerPass implements CompilerPassInterface
{
$this->collectCommandsToConsoleApplication($containerBuilder);
$this->collectRectorsToRectorCollector($containerBuilder);
$this->collectEventSubscribersToEventDisptacher($containerBuilder);
}
private function collectCommandsToConsoleApplication(ContainerBuilder $containerBuilder): void
@ -37,4 +40,14 @@ final class CollectorCompilerPass implements CompilerPassInterface
'addRector'
);
}
private function collectEventSubscribersToEventDisptacher(ContainerBuilder $containerBuilder): void
{
DefinitionCollector::loadCollectorWithType(
$containerBuilder,
EventDispatcherInterface::class,
EventSubscriberInterface::class,
'addSubscriber'
);
}
}

View File

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
namespace Rector\Event;
use PhpParser\Node;
use Symfony\Component\EventDispatcher\Event;
final class AfterParseEvent extends Event
{
/**
* @param Node[] $nodes
*/
public function __construct(array $nodes)
{
$this->nodes = $nodes;
}
/**
* @return Node[]
*/
public function getNodes(): array
{
return $this->nodes;
}
/**
* @param Node[] $nodes
*/
public function changeNodes(array $nodes): void
{
$this->nodes = $nodes;
}
}

View File

@ -0,0 +1,25 @@
<?php declare(strict_types=1);
namespace Rector\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
final class ClassBasedEventDispatcher
{
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
public function __construct(EventDispatcherInterface $eventDispatcher)
{
$this->eventDispatcher = $eventDispatcher;
}
public function dispatch(Event $event): Event
{
$eventClass = get_class($event);
return $this->eventDispatcher->dispatch($eventClass, $event);
}
}

View File

@ -0,0 +1,35 @@
<?php declare(strict_types=1);
namespace Rector\EventSubscriber;
use PhpParser\NodeTraverser;
use Rector\Event\AfterParseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
final class TraverseAfterParsingEventSubscriber implements EventSubscriberInterface
{
/**
* @var NodeTraverser
*/
private $nodeTraverser;
public function __construct(NodeTraverser $nodeTraverser)
{
$this->nodeTraverser = $nodeTraverser;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [AfterParseEvent::class => 'afterParse'];
}
public function afterParse(AfterParseEvent $afterParseEvent): void
{
$nodes = $afterParseEvent->getNodes();
$nodes = $this->nodeTraverser->traverse($nodes);
$afterParseEvent->changeNodes($nodes);
}
}

View File

@ -5,6 +5,8 @@ namespace Rector\Parser;
use PhpParser\Node;
use PhpParser\Parser as NikicParser;
use Rector\Contract\Parser\ParserInterface;
use Rector\Event\AfterParseEvent;
use Rector\EventDispatcher\ClassBasedEventDispatcher;
final class Parser implements ParserInterface
{
@ -18,9 +20,15 @@ final class Parser implements ParserInterface
*/
private $nodesByFile = [];
public function __construct(NikicParser $nikicParser)
/**
* @var ClassBasedEventDispatcher
*/
private $eventDispatcher;
public function __construct(NikicParser $nikicParser, ClassBasedEventDispatcher $eventDispatcher)
{
$this->nikicParser = $nikicParser;
$this->eventDispatcher = $eventDispatcher;
}
/**
@ -33,8 +41,23 @@ final class Parser implements ParserInterface
}
$fileContent = file_get_contents($filePath);
$this->nodesByFile[$filePath] = $this->nikicParser->parse($fileContent);
$nodes = $this->nikicParser->parse($fileContent);
$this->nodesByFile[$filePath] = $this->processByEventDisptacher($nodes);
return $this->nodesByFile[$filePath];
}
/**
* @param Node[] $nodes
* @return Node[]
*/
private function processByEventDisptacher(array $nodes): array
{
$afterParseEvent = new AfterParseEvent($nodes);
$this->eventDispatcher->dispatch($afterParseEvent);
return $afterParseEvent->getNodes();
}
}

View File

@ -6,6 +6,7 @@ use PhpParser\Lexer;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\Parser;
use Rector\Contract\Parser\ParserInterface;
use Rector\NodeTraverser\CloningNodeTraverser;
use Rector\Printer\FormatPerservingPrinter;
use Rector\Rector\RectorCollector;
@ -14,7 +15,7 @@ use SplFileInfo;
final class FileProcessor
{
/**
* @var Parser
* @var ParserInterface
*/
private $parser;
@ -45,7 +46,7 @@ final class FileProcessor
public function __construct(
CloningNodeTraverser $cloningNodeTraverser,
Parser $parser,
ParserInterface $parser,
FormatPerservingPrinter $codeStyledPrinter,
Lexer $lexer,
NodeTraverser $nodeTraverser,
@ -78,9 +79,7 @@ final class FileProcessor
*/
public function processFile(SplFileInfo $file): string
{
$fileContent = $this->getFileContent($file);
$oldStmts = $this->parser->parse($fileContent);
$oldStmts = $this->parser->parseFile($file->getRealPath());
$oldTokens = $this->lexer->getTokens();
$newStmts = $this->cloningNodeTraverser->traverse($oldStmts);
@ -88,9 +87,4 @@ final class FileProcessor
return $this->codeStyledPrinter->printToString($newStmts, $oldStmts, $oldTokens);
}
private function getFileContent(SplFileInfo $file): string
{
return file_get_contents($file->getRealPath());
}
}

View File

@ -5,10 +5,12 @@ parameters:
services:
_defaults:
autowire: true
autoconfigure: true
# PSR-4 autodiscovery
Rector\:
resource: '../../src'
exclude: '../../src/{Event}'
# autowire by interface
Rector\Contract\Parser\ParserInterface:
@ -19,6 +21,9 @@ services:
arguments:
$name: "Rector"
# Event Distpatcher
Symfony\Component\EventDispatcher\EventDispatcher: ~
# PhpParser - Parser
PhpParser\Parser:
factory: ['@Rector\Parser\ParserFactory', 'create']