Quantcast
Channel: Craft It Online!
Viewing all articles
Browse latest Browse all 92

Symfony CS Custom Fixer + Tests: Do focus on your goal!

$
0
0

Once again I received a closing ticket here https://github.com/fabpot/PHP-CS-Fixer/issues/381 in response to a feature request. There was no explanation why it was closed. However @stof kindly provided some reasoning. However what surprised me is what happened afterwards!

But it was great that @sstok picked it up and left a gist. This is amazing how the community can be so encouraging! Really thanks!

So I went and plugged this custom short syntax converter and here is the recipe!

<?php
 
namespace Decoupling\Fixer;
 
use Symfony\CS\FixerInterface;
use Symfony\CS\Tokens;
 
class ShortArraySyntaxFixer implements FixerInterface
{
    public function fix(\SplFileInfo $file, $content)
    {
        $tokens = Tokens::fromCode($content);
 
        for ($index = 0, $c = $tokens->count(); $index < $c; $index++) {
            $token = $tokens[$index];
 
            if (Tokens::isKeyword($token) && T_ARRAY === $token[0] && '(' === $tokens->getNextNonWhitespace($index)) {
                $this->fixArray($tokens, $index);
                continue;
            }
        }
 
        return $tokens->generateCode();
    }
 
    private function fixArray(Tokens $tokens, &$index)
    {
        $bracesLevel = 0;
 
        unset($tokens[$index]);
        $index++;
 
        for ($c = $tokens->count(); $index < $c; $index++) {
            $token = $tokens[$index];
 
            if ('(' === $token) {
                if (0 === $bracesLevel) {
                    $tokens[$index] = '[';
                }
 
                ++$bracesLevel;
                continue;
            }
 
            if (Tokens::isKeyword($token) && T_ARRAY === $token[0] && '(' === $tokens->getNextNonWhitespace($index)) {
                $this->fixArray($tokens, $index);
                continue;
            }
 
            if (')' === $token) {
                --$bracesLevel;
 
                if (0 === $bracesLevel) {
                    $tokens[$index] = ']';
                    break;
                }
            }
        }
    }
 
    public function getLevel()
    {
        return FixerInterface::ALL_LEVEL;
    }
 
    public function getPriority()
    {
        return 0;
    }
 
    public function supports(\SplFileInfo $file)
    {
        return 'php' === pathinfo($file->getFilename(), PATHINFO_EXTENSION);
    }
 
    public function getName()
    {
        return 'short_array_syntax';
    }
 
    public function getDescription()
    {
        return 'PHP array\'s should use the PHP 5.4 short-syntax';
    }
}

And its corresponding test:

<?php
 
namespace Decoupling\Tests\Fixer;
 
use Decoupling\Fixer\ShortArraySyntaxFixer;
 
class ShortArraySyntaxFixerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provideExamples
     */
    public function testFix($expected, $input)
    {
        $fixer = new ShortArraySyntaxFixer();
        $file = $this->getTestFile();
 
        $this->assertEquals($expected, $fixer->fix($file, $input));
    }
 
    public function provideExamples()
    {
        return [
            ['<?php $x = [];', '<?php $x = array();'],
            ['<?php $x = []; $y = [];', '<?php $x = array(); $y = array();'],
            ['<?php $x = [ ];', '<?php $x = array( );'],
            ['<?php $x = [\'foo\'];', '<?php $x = array(\'foo\');'],
            ['<?php $x = [ \'foo\' ];', '<?php $x = array( \'foo\' );'],
            ['<?php $x = [($y ? true : false)];', '<?php $x = array(($y ? true : false));'],
            ['<?php $x = [($y ? [true] : [false])];', '<?php $x = array(($y ? array(true) : array(false)));'],//
            ['<?php $x = [($y ? [true] : [ false ])];', '<?php $x = array(($y ? array(true) : array( false )));'],
            ['<?php $x = [($y ? ["t" => true] : ["f" => false])];', '<?php $x = array(($y ? array("t" => true) : array("f" => false)));'],
            ['<?php print_r([($y ? true : false)]);', '<?php print_r(array(($y ? true : false)));'],
            ['<?php $x = [[[]]];', '<?php $x = array(array(array()));'],
            ['<?php $x = [[[]]]; $y = [[[]]];', '<?php $x = array(array(array())); $y = array(array(array()));'],
        ];
    }
 
    private function getTestFile($filename = __FILE__)
    {
        static $files = [];
 
        if (!isset($files[$filename])) {
            $files[$filename] = new \SplFileInfo($filename);
        }
 
        return $files[$filename];
    }
}

This is also in a gist @sstok posted, however i have applied the fixer on the code itself :) and also fixed missing namespaces and opening php tags.

Your typical .php_cs then becomes:

<?php
 
require_once __DIR__.'/src/Decoupling/Fixer/ShortArraySyntaxFixer.php';
 
$finder = Symfony\CS\Finder\DefaultFinder::create()
    ->notName('README.md')
    ->notName('.php_cs')
    ->notName('composer.*')
    ->notName('phpunit.xml*')
    ->notName('*.xml')
    ->exclude('app')
    ->exclude('bin')
    ->exclude('migrations')
    ->exclude('vendor')
    ->exclude('web/bundles')
    ->in(__DIR__)
;
 
return Symfony\CS\Config\Config::create()
    ->addCustomFixer(new Decoupling\Fixer\ShortArraySyntaxFixer)
    ->fixers(
        [
            'encoding',
            'linefeed',
            'indentation',
            'trailing_spaces',
            'object_operator',
            'phpdoc_params',
            'visibility',
            'short_tag',
            'php_closing_tag',
            'return',
            'extra_empty_lines',
            'braces',
            'lowercase_constants',
            'lowercase_keywords',
            'include',
            'function_declaration',
            'controls_spaces',
            'spaces_cast',
            'psr0',
            'elseif',
            'eof_ending',
            'one_class_per_file',
            'unused_use',
            'short_array_syntax',
        ]
    )
    ->finder($finder)
;

Now go and run it:

~ php-cs-fixer fix .

It worked like a charm in my project and I am happy to use it even in gush now, PR coming!

joyfully undeservedly ending this post!

your friend @cordoval


Viewing all articles
Browse latest Browse all 92

Trending Articles