decouple TemplateVariablesFactory

This commit is contained in:
Tomas Votruba 2018-10-23 18:57:56 +02:00
parent d24aea7c85
commit a8fe5abb03
4 changed files with 134 additions and 90 deletions

View File

@ -1,9 +1,10 @@
package: 'CodeQuality'
name: 'SimplifyMirrorAssignRector' # w/wo suffix
package: "CodeQuality"
name: "SimplifyMirrorAssignRector"
node_types:
- 'Assign'
- "Assign" # put main node first
description: 'Removes unneeded $a = $a assigns'
description: "Removes unneeded $a = $a assigns"
code_before: "$a = $a;"
code_after: ""
source: "" # e.g. link to RFC or headline in upgrade guide
level: "" # e.g. symfony30.yml, target config to append this rector to

View File

@ -4,15 +4,10 @@ namespace Rector\ContributorTools\Command;
use Nette\Utils\FileSystem;
use Nette\Utils\Strings;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Name\FullyQualified;
use Rector\CodingStyle\AfterRectorCodingStyle;
use Rector\Console\ConsoleStyle;
use Rector\ContributorTools\Configuration\Configuration;
use Rector\ContributorTools\Configuration\ConfigurationFactory;
use Rector\Printer\BetterStandardPrinter;
use Rector\ContributorTools\TemplateVariablesFactory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -42,11 +37,6 @@ final class CreateRectorCommand extends Command
*/
private $configurationFactory;
/**
* @var BetterStandardPrinter
*/
private $betterStandardPrinter;
/**
* @var FinderSanitizer
*/
@ -62,19 +52,29 @@ final class CreateRectorCommand extends Command
*/
private $afterRectorCodingStyle;
/**
* @var TemplateVariablesFactory
*/
private $templateVariablesFactory;
/**
* @var string
*/
private $testCasePath;
public function __construct(
ConsoleStyle $consoleStyle,
ConfigurationFactory $configurationFactory,
BetterStandardPrinter $betterStandardPrinter,
FinderSanitizer $finderSanitizer,
AfterRectorCodingStyle $afterRectorCodingStyle
AfterRectorCodingStyle $afterRectorCodingStyle,
TemplateVariablesFactory $templateVariablesFactory
) {
parent::__construct();
$this->consoleStyle = $consoleStyle;
$this->configurationFactory = $configurationFactory;
$this->betterStandardPrinter = $betterStandardPrinter;
$this->finderSanitizer = $finderSanitizer;
$this->afterRectorCodingStyle = $afterRectorCodingStyle;
$this->templateVariablesFactory = $templateVariablesFactory;
}
protected function configure(): void
@ -86,91 +86,32 @@ final class CreateRectorCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
$configuration = $this->configurationFactory->createFromConfigFile(getcwd() . '/create-rector.yml');
$data = $this->prepareData($configuration);
$testCasePath = null;
$templateVariables = $this->templateVariablesFactory->createFromConfiguration($configuration);
foreach ($this->findTemplateFileInfos() as $smartFileInfo) {
$destination = $smartFileInfo->getRelativeFilePathFromDirectory(self::TEMPLATES_DIRECTORY);
$destination = $this->applyData($destination, $data);
$content = $this->applyData($smartFileInfo->getContents(), $data);
$destination = $this->resolveDestination($smartFileInfo, $templateVariables);
$content = $this->resolveContent($smartFileInfo, $templateVariables);
FileSystem::write($destination, $content);
$this->generatedFiles[] = $destination;
if (! $testCasePath && Strings::endsWith($destination, 'Test.php')) {
$testCasePath = dirname($destination);
if (Strings::endsWith($destination, 'Test.php')) {
$this->testCasePath = dirname($destination);
}
}
$this->applyCodingStyle();
$this->printSuccess($configuration, $testCasePath);
$this->printSuccess($configuration->getName());
return ShellCode::SUCCESS;
}
/**
* @return mixed[]
* @param mixed[] $variables
*/
private function prepareData(Configuration $configuration): array
private function applyVariables(string $content, array $variables): string
{
$data = [
'_Package_' => $configuration->getPackage(),
'_Category_' => $configuration->getCategory(),
'_Description_' => $configuration->getDescription(),
'_Name_' => $configuration->getName(),
'_CodeBefore_' => trim($configuration->getCodeBefore()) . PHP_EOL,
'_CodeBeforeExample_' => $this->prepareCodeForDefinition($configuration->getCodeBefore()),
'_CodeAfter_' => trim($configuration->getCodeAfter()) . PHP_EOL,
'_CodeAfterExample_' => $this->prepareCodeForDefinition($configuration->getCodeAfter()),
'_Source_' => $this->prepareSourceDocBlock($configuration->getSource()),
];
$arrayNodes = [];
foreach ($configuration->getNodeTypes() as $nodeType) {
$arrayNodes[] = new ArrayItem(new ClassConstFetch(new FullyQualified($nodeType), 'class'));
}
$data['_NodeTypes_Php_'] = $this->betterStandardPrinter->prettyPrint([new Array_($arrayNodes)]);
$data['_NodeTypes_Doc_'] = '\\' . implode('|\\', $configuration->getNodeTypes());
return $data;
}
/**
* @param mixed[] $data
*/
private function applyData(string $content, array $data): string
{
return str_replace(array_keys($data), array_values($data), $content);
}
private function prepareCodeForDefinition(string $code): string
{
if (Strings::contains($code, PHP_EOL)) {
// multi lines
return sprintf("<<<'CODE_SAMPLE'%s%sCODE_SAMPLE%s", PHP_EOL, $code, PHP_EOL);
}
// single line
return "'" . str_replace("'", '"', $code) . "'";
}
private function prepareSourceDocBlock(string $source): string
{
if (! $source) {
return $source;
}
$sourceDocBlock = <<<'CODE_SAMPLE'
/**
* @see %s
*/
CODE_SAMPLE;
return sprintf($sourceDocBlock, $source);
return str_replace(array_keys($variables), array_values($variables), $content);
}
/**
@ -184,16 +125,16 @@ CODE_SAMPLE;
return $this->finderSanitizer->sanitize($finder);
}
private function printSuccess(Configuration $configuration, string $testCasePath): void
private function printSuccess(string $name): void
{
$this->consoleStyle->title(sprintf('New files generated for "%s"', $configuration->getName()));
$this->consoleStyle->title(sprintf('New files generated for "%s"', $name));
sort($this->generatedFiles);
$this->consoleStyle->listing($this->generatedFiles);
$this->consoleStyle->success(sprintf(
'Now make these tests green again:%svendor/bin/phpunit %s',
PHP_EOL,
$testCasePath
$this->testCasePath
));
}
@ -206,4 +147,22 @@ CODE_SAMPLE;
$this->afterRectorCodingStyle->apply($generatedPhpFiles);
}
/**
* @param string[] $templateVariables
*/
private function resolveDestination(SmartFileInfo $smartFileInfo, array $templateVariables): string
{
$destination = $smartFileInfo->getRelativeFilePathFromDirectory(self::TEMPLATES_DIRECTORY);
return $this->applyVariables($destination, $templateVariables);
}
/**
* @param string[] $templateVariables
*/
private function resolveContent(SmartFileInfo $smartFileInfo, array $templateVariables): string
{
return $this->applyVariables($smartFileInfo->getContents(), $templateVariables);
}
}

View File

@ -0,0 +1,84 @@
<?php declare(strict_types=1);
namespace Rector\ContributorTools;
use Nette\Utils\Strings;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Name\FullyQualified;
use Rector\ContributorTools\Configuration\Configuration;
use Rector\Printer\BetterStandardPrinter;
use function Safe\sprintf;
final class TemplateVariablesFactory
{
/**
* @var BetterStandardPrinter
*/
private $betterStandardPrinter;
public function __construct(BetterStandardPrinter $betterStandardPrinter)
{
$this->betterStandardPrinter = $betterStandardPrinter;
}
/**
* @return mixed[]
*/
public function createFromConfiguration(Configuration $configuration): array
{
$data = [
'_Package_' => $configuration->getPackage(),
'_Category_' => $configuration->getCategory(),
'_Description_' => $configuration->getDescription(),
'_Name_' => $configuration->getName(),
'_CodeBefore_' => trim($configuration->getCodeBefore()) . PHP_EOL,
'_CodeBeforeExample_' => $this->createCodeForDefinition($configuration->getCodeBefore()),
'_CodeAfter_' => trim($configuration->getCodeAfter()) . PHP_EOL,
'_CodeAfterExample_' => $this->createCodeForDefinition($configuration->getCodeAfter()),
'_Source_' => $this->createSourceDocBlock($configuration->getSource()),
];
$data['_NodeTypes_Php_'] = $this->createNodeTypePhp($configuration);
$data['_NodeTypes_Doc_'] = '\\' . implode('|\\', $configuration->getNodeTypes());
return $data;
}
private function createCodeForDefinition(string $code): string
{
if (Strings::contains($code, PHP_EOL)) {
// multi lines
return sprintf("<<<'CODE_SAMPLE'%s%sCODE_SAMPLE%s", PHP_EOL, $code, PHP_EOL);
}
// single line
return "'" . str_replace("'", '"', $code) . "'";
}
private function createSourceDocBlock(string $source): string
{
if (! $source) {
return $source;
}
$sourceDocBlock = <<<'CODE_SAMPLE'
/**
* @see %s
*/
CODE_SAMPLE;
return sprintf($sourceDocBlock, $source);
}
private function createNodeTypePhp(Configuration $configuration): string
{
$arrayNodes = [];
foreach ($configuration->getNodeTypes() as $nodeType) {
$arrayNodes[] = new ArrayItem(new ClassConstFetch(new FullyQualified($nodeType), 'class'));
}
return $this->betterStandardPrinter->prettyPrint([new Array_($arrayNodes)]);
}
}