Open create command to public

This commit is contained in:
TomasVotruba 2019-11-24 13:40:43 +01:00
parent 665977b9e2
commit 68fd377d82
5 changed files with 110 additions and 55 deletions

View File

@ -1,31 +0,0 @@
# run "bin/rector create" to create a new Rector + tests from this config
package: "Celebrity"
name: "SplitToExplodeRector"
node_types:
- "Assign" # put main node first
description: "Removes unneeded $a = $a assigns"
code_before: |
<?php
class SomeClass
{
public function run()
{
$a = $a;
}
}
code_after: |
<?php
class SomeClass
{
public function run()
{
}
}
source: # e.g. link to RFC or headline in upgrade guide, 1 or more in the list
- ""
set: "" # e.g. symfony30.yaml, target config to append this rector to

View File

@ -12,3 +12,7 @@ parameters:
# so Rector code is still PHP 7.1 compatible
php_version_features: '7.1'
rector_recipe:
package: "Utils"

View File

@ -9,3 +9,38 @@ services:
exclude:
- '../src/Exception/*'
- '../src/ValueObject/*'
parameters:
rector_recipe:
# run "bin/rector create" to create a new Rector + tests from this config
package: "Celebrity"
name: "SplitToExplodeRector"
node_types:
# put main node first, it is used to create namespace
- "Assign"
description: "Removes unneeded $a = $a assigns"
code_before: >
<?php
class SomeClass
{
public function run()
{
$a = $a;
}
}
code_after: >
<?php
class SomeClass
{
public function run()
{
}
}
source: # e.g. link to RFC or headline in upgrade guide, 1 or more in the list
- ""
set: "" # e.g. symfony30, target config to append this rector to

View File

@ -34,6 +34,11 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
*/
private const RECTOR_FQN_NAME_PATTERN = 'Rector\_Package_\Rector\_Category_\_Name_';
/**
* @var string
*/
private const UTILS_KEYWORD = 'Utils';
/**
* @var string
*/
@ -64,17 +69,27 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
*/
private $templateVariablesFactory;
/**
* @var mixed[]
*/
private $rectorRecipe = [];
/**
* @param mixed[] $rectorRecipe
*/
public function __construct(
SymfonyStyle $symfonyStyle,
ConfigurationFactory $configurationFactory,
FinderSanitizer $finderSanitizer,
TemplateVariablesFactory $templateVariablesFactory
TemplateVariablesFactory $templateVariablesFactory,
array $rectorRecipe
) {
parent::__construct();
$this->symfonyStyle = $symfonyStyle;
$this->configurationFactory = $configurationFactory;
$this->finderSanitizer = $finderSanitizer;
$this->templateVariablesFactory = $templateVariablesFactory;
$this->rectorRecipe = $rectorRecipe;
}
protected function configure(): void
@ -85,7 +100,7 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
protected function execute(InputInterface $input, OutputInterface $output): int
{
$configuration = $this->configurationFactory->createFromConfigFile(getcwd() . '/create-rector.yaml');
$configuration = $this->configurationFactory->createFromRectorRecipe($this->rectorRecipe);
$templateVariables = $this->templateVariablesFactory->createFromConfiguration($configuration);
// setup psr-4 autoload, if not already in
@ -94,6 +109,10 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
foreach ($this->findTemplateFileInfos() as $smartFileInfo) {
$destination = $this->resolveDestination($smartFileInfo, $templateVariables, $configuration);
dump($templateVariables);
dump($destination);
die;
$content = $this->resolveContent($smartFileInfo, $templateVariables);
if ($configuration->getPackage() === 'Rector') {
@ -109,6 +128,7 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
$this->generatedFiles[] = $destination;
// is test case?
if (Strings::endsWith($destination, 'Test.php')) {
$this->testCasePath = dirname($destination);
}
@ -126,6 +146,8 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
*/
private function processComposerAutoload(array $templateVariables): void
{
// @todo decouple to own service...
$composerJsonFilePath = getcwd() . '/composer.json';
$composerJson = $this->loadFileToJson($composerJsonFilePath);
@ -136,16 +158,36 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
return;
}
$namespace = 'Rector\\' . $package . '\\';
$namespaceTest = 'Rector\\' . $package . '\\Tests\\';
if ($package === self::UTILS_KEYWORD) {
$namespace = 'Utils\\Rector\\';
$namespaceTest = 'Utils\\Rector\\Tests\\';
} else {
$namespace = 'Rector\\' . $package . '\\';
$namespaceTest = 'Rector\\' . $package . '\\Tests\\';
}
// already autoloaded?
if (isset($composerJson['autoload']['psr-4'][$namespace])) {
return;
}
$composerJson['autoload']['psr-4'][$namespace] = 'packages/' . $package . '/src';
$composerJson['autoload-dev']['psr-4'][$namespaceTest] = 'packages/' . $package . '/tests';
if ($package === self::UTILS_KEYWORD) {
$srcDirectory = 'utils/rector/src';
$testsDirectory = 'utils/rector/tests';
} else {
$srcDirectory = 'packages/' . $package . '/src';
$testsDirectory = 'packages/' . $package . '/tests';
}
// is the namespace already in composer.json? → skip it
if (isset($composerJson['autoload']['psr-4'][$namespace])) {
if ($composerJson['autoload-dev']['psr-4'][$namespaceTest]) {
return;
}
}
$composerJson['autoload']['psr-4'][$namespace] = $srcDirectory;
$composerJson['autoload-dev']['psr-4'][$namespaceTest] = $testsDirectory;
$this->saveJsonToFile($composerJsonFilePath, $composerJson);
@ -181,6 +223,11 @@ final class CreateRectorCommand extends Command implements ContributorCommandInt
$destination = Strings::replace($destination, '#packages\/_Package_/src/Rector#', 'src/Rector');
}
// special keyword for 3rd party Rectors, not for core Github contribution
if ($configuration->getPackage() === self::UTILS_KEYWORD) {
$destination = Strings::replace($destination, '#packages\/_Package_#', 'utils/rector');
}
if (! Strings::match($destination, '#fixture[\d+]*\.php\.inc#')) {
$destination = rtrim($destination, '.inc');
}

View File

@ -28,26 +28,26 @@ final class ConfigurationFactory
$this->nodeClassProvider = $nodeClassProvider;
}
public function createFromConfigFile(string $configFile): Configuration
/**
* @param mixed[] $rectorRecipe
*/
public function createFromRectorRecipe(array $rectorRecipe): Configuration
{
$this->ensureConfigFileIsFound($configFile);
$this->ensureRecipeIsValid($rectorRecipe);
$config = (array) Yaml::parseFile($configFile);
$this->ensureConfigIsValid($config, $configFile);
$fqnNodeTypes = $this->resolveFullyQualifiedNodeTypes($config['node_types']);
$fqnNodeTypes = $this->resolveFullyQualifiedNodeTypes($rectorRecipe['node_types']);
$category = $this->resolveCategoryFromFqnNodeTypes($fqnNodeTypes);
return new Configuration(
$config['package'],
$config['name'],
$rectorRecipe['package'],
$rectorRecipe['name'],
$category,
$this->resolveFullyQualifiedNodeTypes($config['node_types']),
$config['description'],
trim(ltrim($config['code_before'], '<?php')),
trim(ltrim($config['code_after'], '<?php')),
array_filter((array) $config['source']),
$this->resolveSetConfig($config['set'])
$this->resolveFullyQualifiedNodeTypes($rectorRecipe['node_types']),
$rectorRecipe['description'],
trim(ltrim($rectorRecipe['code_before'], '<?php')),
trim(ltrim($rectorRecipe['code_after'], '<?php')),
array_filter((array) $rectorRecipe['source']),
$this->resolveSetConfig($rectorRecipe['set'])
);
}
@ -61,9 +61,9 @@ final class ConfigurationFactory
}
/**
* @param mixed[][] $config
* @param mixed[] $rectorRecipe
*/
private function ensureConfigIsValid(array $config, string $configFile): void
private function ensureRecipeIsValid(array $rectorRecipe): void
{
$requiredKeys = [
'package',
@ -76,8 +76,8 @@ final class ConfigurationFactory
'set',
];
if (count(array_intersect(array_keys($config), $requiredKeys)) === count($requiredKeys)) {
if (count($config['node_types']) < 1) {
if (count(array_intersect(array_keys($rectorRecipe), $requiredKeys)) === count($requiredKeys)) {
if (count($rectorRecipe['node_types']) < 1) {
throw new ConfigurationException(sprintf(
'"%s" option requires at least one node, e.g. "FuncCall"',
'node_types'