add ParsedStmtsAndTokens value object

This commit is contained in:
TomasVotruba 2020-06-19 12:23:25 +02:00
parent 09d28abed9
commit 9f3fb6eb19
6 changed files with 117 additions and 56 deletions

View File

@ -117,12 +117,12 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
$this->fileProcessor->parseFileInfoToLocalCache($smartFileInfo);
}
[$newStmts, $oldStmts] = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
$parsedStmtsAndTokens = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
// needed for format preserving
$this->oldStmts = $oldStmts;
$this->oldStmts = $parsedStmtsAndTokens->getOldStmts();
return $newStmts;
return $parsedStmtsAndTokens->getNewStmts();
}
/**

View File

@ -32,7 +32,7 @@ final class CurrentFileInfoProvider
/**
* @param Node[] $stmts
*/
public function setCurrentStmt(array $stmts): void
public function setCurrentStmts(array $stmts): void
{
$this->currentStmts = $stmts;
}

View File

@ -5,13 +5,13 @@ declare(strict_types=1);
namespace Rector\Core\Application;
use PhpParser\Lexer;
use PhpParser\Node;
use Rector\ChangesReporting\Collector\AffectedFilesCollector;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser;
use Rector\Core\PhpParser\Parser\Parser;
use Rector\Core\PhpParser\Printer\FormatPerservingPrinter;
use Rector\Core\Stubs\StubLoader;
use Rector\Core\ValueObject\Application\ParsedStmtsAndTokens;
use Rector\NodeTypeResolver\FileSystem\CurrentFileInfoProvider;
use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator;
use Rector\PostRector\Application\PostFileProcessor;
@ -101,22 +101,15 @@ final class FileProcessor
$this->currentFileInfoProvider->setCurrentFileInfo($smartFileInfo);
[$newStmts, $oldStmts, $oldTokens] = $this->parseAndTraverseFileInfoToNodes($smartFileInfo);
if ($newStmts === null) {
throw new ShouldNotHappenException(sprintf(
'Parsing of file "%s" went wrong. Might be caused by inlinced html. Does it have full "<?php" openings? Try re-run with --debug option to find out more.',
$smartFileInfo->getRealPath()
));
}
// store tokens by absolute path, so we don't have to print them right now
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens = $this->parseAndTraverseFileInfoToNodes($smartFileInfo);
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $parsedStmtsAndTokens);
}
public function printToFile(SmartFileInfo $smartFileInfo): string
{
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
return $this->formatPerservingPrinter->printToFile($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
return $this->formatPerservingPrinter->printParsedStmstAndTokens($smartFileInfo, $parsedStmtsAndTokens);
}
/**
@ -126,8 +119,8 @@ final class FileProcessor
{
$this->makeSureFileIsParsed($smartFileInfo);
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
return $this->formatPerservingPrinter->printToString($newStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
return $this->formatPerservingPrinter->printParsedStmstAndTokensToString($parsedStmtsAndTokens);
}
public function refactor(SmartFileInfo $smartFileInfo): void
@ -137,14 +130,12 @@ final class FileProcessor
$this->makeSureFileIsParsed($smartFileInfo);
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
$this->currentFileInfoProvider->setCurrentStmt($newStmts);
$newStmts = $this->rectorNodeTraverser->traverse($newStmts);
$parsedStmtsAndTokens = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
$this->currentFileInfoProvider->setCurrentStmts($parsedStmtsAndTokens->getNewStmts());
$newStmts = $this->rectorNodeTraverser->traverse($parsedStmtsAndTokens->getNewStmts());
// this is needed for new tokens added in "afterTraverse()"
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens->updateNewStmts($newStmts);
$this->affectedFilesCollector->removeFromList($smartFileInfo);
while ($otherTouchedFile = $this->affectedFilesCollector->getNext()) {
@ -158,31 +149,29 @@ final class FileProcessor
$this->parseFileInfoToLocalCache($smartFileInfo);
}
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
$parsedStmtsAndTokens = $this->tokensByFilePathStorage->getForFileInfo($smartFileInfo);
$this->currentFileInfoProvider->setCurrentStmt($newStmts);
$this->currentFileInfoProvider->setCurrentStmts($parsedStmtsAndTokens->getNewStmts());
$this->currentFileInfoProvider->setCurrentFileInfo($smartFileInfo);
$newStmts = $this->postFileProcessor->traverse($newStmts);
$newStmts = $this->postFileProcessor->traverse($parsedStmtsAndTokens->getNewStmts());
// this is needed for new tokens added in "afterTraverse()"
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens->updateNewStmts($newStmts);
}
/**
* @return Node[][]|mixed[]
*/
private function parseAndTraverseFileInfoToNodes(SmartFileInfo $smartFileInfo): array
private function parseAndTraverseFileInfoToNodes(SmartFileInfo $smartFileInfo): ParsedStmtsAndTokens
{
$oldStmts = $this->parser->parseFileInfo($smartFileInfo);
$oldTokens = $this->lexer->getTokens();
// needed for \Rector\NodeTypeResolver\PHPStan\Scope\NodeScopeResolver
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $oldStmts, $oldStmts, $oldTokens);
$parsedStmtsAndTokens = new ParsedStmtsAndTokens($oldStmts, $oldStmts, $oldTokens);
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo, $parsedStmtsAndTokens);
$newStmts = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($oldStmts, $smartFileInfo);
return [$newStmts, $oldStmts, $oldTokens];
return new ParsedStmtsAndTokens($newStmts, $oldStmts, $oldTokens);
}
private function makeSureFileIsParsed(SmartFileInfo $smartFileInfo): void

View File

@ -4,32 +4,19 @@ declare(strict_types=1);
namespace Rector\Core\Application;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use Rector\Core\ValueObject\Application\ParsedStmtsAndTokens;
use Symplify\SmartFileSystem\SmartFileInfo;
final class TokensByFilePathStorage
{
/**
* @todo use value object
* @var Node[][][]|Stmt[][][]
* @var ParsedStmtsAndTokens[]
*/
private $tokensByFilePath = [];
/**
* @todo replace with SmartFileInfo $realPath
*
* @param Node[]|Stmt[] $newStmts
* @param Node[]|Stmt[] $oldStmts
* @param Node[]|Stmt[] $oldTokens
*/
public function addForRealPath(
SmartFileInfo $smartFileInfo,
array $newStmts,
array $oldStmts,
array $oldTokens
): void {
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$newStmts, $oldStmts, $oldTokens];
public function addForRealPath(SmartFileInfo $smartFileInfo, ParsedStmtsAndTokens $parsedStmtsAndTokens): void
{
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = $parsedStmtsAndTokens;
}
public function hasForFileInfo(SmartFileInfo $smartFileInfo): bool
@ -37,10 +24,7 @@ final class TokensByFilePathStorage
return isset($this->tokensByFilePath[$smartFileInfo->getRealPath()]);
}
/**
* @return Node[][]|Stmt[][]
*/
public function getForFileInfo(SmartFileInfo $smartFileInfo): array
public function getForFileInfo(SmartFileInfo $smartFileInfo): ParsedStmtsAndTokens
{
return $this->tokensByFilePath[$smartFileInfo->getRealPath()];
}

View File

@ -6,6 +6,7 @@ namespace Rector\Core\PhpParser\Printer;
use Nette\Utils\FileSystem;
use PhpParser\Node;
use Rector\Core\ValueObject\Application\ParsedStmtsAndTokens;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
@ -46,4 +47,22 @@ final class FormatPerservingPrinter
{
return $this->betterStandardPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens);
}
public function printParsedStmstAndTokensToString(ParsedStmtsAndTokens $parsedStmtsAndTokens): string
{
return $this->betterStandardPrinter->printFormatPreserving($parsedStmtsAndTokens->getNewStmts(),
$parsedStmtsAndTokens->getOldStmts(), $parsedStmtsAndTokens->getOldTokens());
}
public function printParsedStmstAndTokens(
SmartFileInfo $smartFileInfo,
ParsedStmtsAndTokens $parsedStmtsAndTokens
): string {
return $this->printToFile(
$smartFileInfo,
$parsedStmtsAndTokens->getNewStmts(),
$parsedStmtsAndTokens->getOldStmts(),
$parsedStmtsAndTokens->getOldTokens()
);
}
}

View File

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace Rector\Core\ValueObject\Application;
use PhpParser\Node;
final class ParsedStmtsAndTokens
{
/**
* @var Node[]
*/
private $newStmts = [];
/**
* @var Node[]
*/
private $oldStmts = [];
/**
* @var mixed[]
*/
private $oldTokens = [];
/**
* @param Node[] $newStmts
* @param Node[] $oldStmts
* @param mixed[] $oldTokens
*/
public function __construct(array $newStmts, array $oldStmts, array $oldTokens)
{
$this->newStmts = $newStmts;
$this->oldStmts = $oldStmts;
$this->oldTokens = $oldTokens;
}
/**
* @return Node[]
*/
public function getNewStmts(): array
{
return $this->newStmts;
}
/**
* @return Node[]
*/
public function getOldStmts(): array
{
return $this->oldStmts;
}
/**
* @return mixed[]
*/
public function getOldTokens(): array
{
return $this->oldTokens;
}
/**
* @param Node[] $newStmts
*/
public function updateNewStmts(array $newStmts): void
{
$this->newStmts = $newStmts;
}
}