Browse Source

feature: DescribeCommand - allow describing custom fixers (#6957)

John Paul E. Balandan, CPA 1 year ago
parent
commit
fd80d9ea63

+ 14 - 0
src/Console/Command/DescribeCommand.php

@@ -14,6 +14,8 @@ declare(strict_types=1);
 
 namespace PhpCsFixer\Console\Command;
 
+use PhpCsFixer\Config;
+use PhpCsFixer\Console\ConfigurationResolver;
 use PhpCsFixer\Differ\DiffConsoleFormatter;
 use PhpCsFixer\Differ\FullDiffer;
 use PhpCsFixer\Fixer\ConfigurableFixerInterface;
@@ -30,6 +32,7 @@ use PhpCsFixer\Preg;
 use PhpCsFixer\RuleSet\RuleSets;
 use PhpCsFixer\StdinFileInfo;
 use PhpCsFixer\Tokenizer\Tokens;
+use PhpCsFixer\ToolInfo;
 use PhpCsFixer\Utils;
 use PhpCsFixer\WordMatcher;
 use Symfony\Component\Console\Attribute\AsCommand;
@@ -37,6 +40,7 @@ use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Formatter\OutputFormatter;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\ConsoleOutputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
@@ -83,6 +87,7 @@ final class DescribeCommand extends Command
             ->setDefinition(
                 [
                     new InputArgument('name', InputArgument::REQUIRED, 'Name of rule / set.'),
+                    new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The path to a .php-cs-fixer.php file.'),
                 ]
             )
             ->setDescription('Describe rule / ruleset.')
@@ -96,6 +101,15 @@ final class DescribeCommand extends Command
             $stdErr->writeln($this->getApplication()->getLongVersion());
         }
 
+        $resolver = new ConfigurationResolver(
+            new Config(),
+            ['config' => $input->getOption('config')],
+            getcwd(),
+            new ToolInfo()
+        );
+
+        $this->fixerFactory->registerCustomFixers($resolver->getConfig()->getCustomFixers());
+
         $name = $input->getArgument('name');
 
         try {

+ 36 - 0
tests/Console/Command/DescribeCommandTest.php

@@ -23,6 +23,7 @@ use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
 use PhpCsFixer\FixerDefinition\CodeSample;
 use PhpCsFixer\FixerDefinition\FixerDefinition;
 use PhpCsFixer\FixerFactory;
+use PhpCsFixer\Tests\Fixtures\DescribeCommand\DescribeFixtureFixer;
 use PhpCsFixer\Tests\TestCase;
 use PhpCsFixer\Tokenizer\Token;
 use Prophecy\Argument;
@@ -211,6 +212,41 @@ Fixing examples:
         self::assertStringContainsString(\get_class($mock), $commandTester->getDisplay(true));
     }
 
+    public function testCommandDescribesCustomFixer(): void
+    {
+        $application = new Application();
+        $application->add(new DescribeCommand());
+
+        $command = $application->find('describe');
+
+        $commandTester = new CommandTester($command);
+        $commandTester->execute([
+            'command' => $command->getName(),
+            'name' => (new DescribeFixtureFixer())->getName(),
+            '--config' => __DIR__.'/../../Fixtures/DescribeCommand/.php-cs-fixer.fixture.php',
+        ]);
+
+        $expected =
+"Description of Vendor/describe_fixture rule.
+Fixture for describe command.
+
+Fixing examples:
+ * Example #1.
+   ---------- begin diff ----------
+   --- Original
+   +++ New
+   @@ -1,2 +1,2 @@
+    <?php
+   -echo 'describe fixture';
+   +echo 'fixture for describe';
+   ".'
+   ----------- end diff -----------
+
+';
+        self::assertSame($expected, $commandTester->getDisplay(true));
+        self::assertSame(0, $commandTester->getStatusCode());
+    }
+
     private function execute(string $name, bool $decorated): CommandTester
     {
         $fixer = $this->prophesize();

+ 9 - 0
tests/Fixtures/DescribeCommand/.php-cs-fixer.fixture.php

@@ -0,0 +1,9 @@
+<?php
+
+use PhpCsFixer\Config;
+use PhpCsFixer\Finder;
+use PhpCsFixer\Tests\Fixtures\DescribeCommand\DescribeFixtureFixer;
+
+return (new Config())
+    ->setFinder((new Finder())->in(__DIR__))
+    ->registerCustomFixers([new DescribeFixtureFixer()]);

+ 62 - 0
tests/Fixtures/DescribeCommand/DescribeFixtureFixer.php

@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of PHP CS Fixer.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace PhpCsFixer\Tests\Fixtures\DescribeCommand;
+
+use PhpCsFixer\AbstractFixer;
+use PhpCsFixer\FixerDefinition\CodeSample;
+use PhpCsFixer\FixerDefinition\FixerDefinition;
+use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
+use PhpCsFixer\Tokenizer\Token;
+use PhpCsFixer\Tokenizer\Tokens;
+
+final class DescribeFixtureFixer extends AbstractFixer
+{
+    public function getName(): string
+    {
+        return 'Vendor/describe_fixture';
+    }
+
+    public function isCandidate(Tokens $tokens): bool
+    {
+        return $tokens->isTokenKindFound(T_CONSTANT_ENCAPSED_STRING);
+    }
+
+    public function getDefinition(): FixerDefinitionInterface
+    {
+        return new FixerDefinition(
+            'Fixture for describe command.',
+            [
+                new CodeSample(
+                    "<?php\necho 'describe fixture';\n"
+                ),
+            ],
+        );
+    }
+
+    protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
+    {
+        for ($index = $tokens->count() - 1; $index > 0; --$index) {
+            if (!$tokens[$index]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) {
+                continue;
+            }
+
+            if ('\'describe fixture\'' !== strtolower($tokens[$index]->getContent())) {
+                continue;
+            }
+
+            $tokens[$index] = new Token([T_CONSTANT_ENCAPSED_STRING, '\'fixture for describe\'']);
+        }
+    }
+}