Browse Source

Init development

Filippo Tessarotto 7 years ago
parent
commit
aceb43495c

+ 5 - 0
README.rst

@@ -1836,6 +1836,11 @@ Choose from the list of available rules:
   Converts explicit variables in double-quoted strings and heredoc syntax
   from simple to complex format (``${`` to ``{$``).
 
+* **simplified_if_return**
+
+  Simplify ``if`` control structures that return the boolean result of their
+  condition.
+
 * **simplified_null_return**
 
   A return statement wishing to return ``void`` should not return ``null``.

+ 96 - 0
src/Fixer/ControlStructure/SimplifiedIfReturnFixer.php

@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * 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\Fixer\ControlStructure;
+
+use PhpCsFixer\AbstractFixer;
+use PhpCsFixer\FixerDefinition\CodeSample;
+use PhpCsFixer\FixerDefinition\FixerDefinition;
+use PhpCsFixer\Tokenizer\Token;
+use PhpCsFixer\Tokenizer\Tokens;
+
+/**
+ * @author Filippo Tessarotto <zoeslam@gmail.com>
+ */
+final class SimplifiedIfReturnFixer extends AbstractFixer
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefinition()
+    {
+        return new FixerDefinition(
+            'Simplify `if` control structures that return the boolean result of their condition.',
+            [new CodeSample("<?php\nif (\$foo) { return true; } return false;\n")]
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        // should be run before NoMultilineWhitespaceBeforeSemicolonsFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer.
+        return 1;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isCandidate(Tokens $tokens)
+    {
+        return $tokens->isAllTokenKindsFound([T_IF, T_RETURN, T_STRING]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function applyFix(\SplFileInfo $file, Tokens $tokens)
+    {
+        static $sequence = [
+            ')',
+            '{', [T_RETURN], [T_STRING, 'true'], ';', '}',
+            [T_RETURN], [T_STRING, 'false'], ';',
+        ];
+
+        $foundIndexes = $tokens->findGivenKind([T_IF, T_ELSEIF]);
+        $foundIndexes = array_reverse($foundIndexes[T_IF] + $foundIndexes[T_ELSEIF], true);
+        foreach ($foundIndexes as $ifIndex => $ifToken) {
+            $startParenthesisIndex = $tokens->getNextTokenOfKind($ifIndex, ['(']);
+            $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex);
+            $sequenceFound = $tokens->findSequence($sequence, $endParenthesisIndex - 1);
+            if (null === $sequenceFound) {
+                continue;
+            }
+
+            $firstSequenceIndex = key($sequenceFound);
+            if ($firstSequenceIndex !== $endParenthesisIndex) {
+                continue;
+            }
+
+            $indexesToClear = array_keys($sequenceFound);
+            array_pop($indexesToClear); // Preserve last semicolon
+            $indexesToClear[] = $startParenthesisIndex;
+            rsort($indexesToClear);
+
+            foreach ($indexesToClear as $index) {
+                $tokens->clearTokenAndMergeSurroundingWhitespace($index);
+            }
+
+            $tokens->overrideRange($ifIndex, $ifIndex, [
+                new Token([T_RETURN, 'return']),
+                new Token([T_WHITESPACE, ' ']),
+                new Token([T_BOOL_CAST, '(bool)']),
+            ]);
+        }
+    }
+}

+ 4 - 0
tests/AutoReview/FixerFactoryTest.php

@@ -153,6 +153,7 @@ final class FixerFactoryTest extends TestCase
             [$fixers['no_spaces_after_function_name'], $fixers['function_to_constant']],
             [$fixers['no_spaces_inside_parenthesis'], $fixers['function_to_constant']],
             [$fixers['no_superfluous_phpdoc_tags'], $fixers['no_empty_phpdoc']],
+            [$fixers['no_superfluous_elseif'], $fixers['simplified_if_return']],
             [$fixers['no_unneeded_control_parentheses'], $fixers['no_trailing_whitespace']],
             [$fixers['no_unneeded_curly_braces'], $fixers['no_useless_else']],
             [$fixers['no_unneeded_curly_braces'], $fixers['no_useless_return']],
@@ -166,6 +167,7 @@ final class FixerFactoryTest extends TestCase
             [$fixers['no_useless_else'], $fixers['no_trailing_whitespace']],
             [$fixers['no_useless_else'], $fixers['no_useless_return']],
             [$fixers['no_useless_else'], $fixers['no_whitespace_in_blank_line']],
+            [$fixers['no_useless_else'], $fixers['simplified_if_return']],
             [$fixers['no_useless_return'], $fixers['blank_line_before_return']],
             [$fixers['no_useless_return'], $fixers['blank_line_before_statement']],
             [$fixers['no_useless_return'], $fixers['no_extra_blank_lines']],
@@ -225,6 +227,8 @@ final class FixerFactoryTest extends TestCase
             [$fixers['pow_to_exponentiation'], $fixers['no_spaces_inside_parenthesis']],
             [$fixers['protected_to_private'], $fixers['ordered_class_elements']],
             [$fixers['return_assignment'], $fixers['blank_line_before_statement']],
+            [$fixers['simplified_if_return'], $fixers['no_multiline_whitespace_before_semicolons']],
+            [$fixers['simplified_if_return'], $fixers['no_singleline_whitespace_before_semicolons']],
             [$fixers['simplified_null_return'], $fixers['no_useless_return']],
             [$fixers['single_import_per_statement'], $fixers['multiline_whitespace_before_semicolons']],
             [$fixers['single_import_per_statement'], $fixers['no_leading_import_slash']],

+ 138 - 0
tests/Fixer/ControlStructure/SimplifiedIfReturnFixerTest.php

@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * 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\Fixer\ControlStructure;
+
+use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
+
+/**
+ * @author Filippo Tessarotto <zoeslam@gmail.com>
+ *
+ * @internal
+ *
+ * @covers \PhpCsFixer\Fixer\ControlStructure\SimplifiedIfReturnFixer
+ */
+final class SimplifiedIfReturnFixerTest extends AbstractFixerTestCase
+{
+    /**
+     * @param string      $expected
+     * @param null|string $input
+     *
+     * @dataProvider provideFixCases
+     */
+    public function testFix($expected, $input = null)
+    {
+        $this->doTest($expected, $input);
+    }
+
+    public function provideFixCases()
+    {
+        return [
+            [
+                '<?php return (bool) $foo      ;',
+                '<?php if ($foo) { return true; } return false;',
+            ],
+            [
+                '<?php if ($bar) { return 1; } return (bool) $foo      ;',
+                '<?php if ($bar) { return 1; } if ($foo) { return true; } return false;',
+            ],
+            [
+                <<<'EOT'
+<?php
+function f1() { return (bool) $f1      ; }
+function f2() { return true; } return false;
+function f3() { return (bool) $f3      ; }
+function f4() { return true; } return false;
+function f5() { return (bool) $f5      ; }
+EOT
+                ,
+                <<<'EOT'
+<?php
+function f1() { if ($f1) { return true; } return false; }
+function f2() { return true; } return false;
+function f3() { if ($f3) { return true; } return false; }
+function f4() { return true; } return false;
+function f5() { if ($f5) { return true; } return false; }
+EOT
+                ,
+            ],
+            [
+                <<<'EOT'
+<?php
+// C1
+return (bool)
+# C2
+
+/* C3 */
+$foo
+/** C4 */
+
+// C5
+
+# C6
+
+// C7
+
+# C8
+
+/* C9 */
+
+/** C10 */
+
+// C11
+
+# C12
+;
+/* C13 */
+EOT
+                ,
+                <<<'EOT'
+<?php
+// C1
+if
+# C2
+(
+/* C3 */
+$foo
+/** C4 */
+)
+// C5
+{
+# C6
+return
+// C7
+true
+# C8
+;
+/* C9 */
+}
+/** C10 */
+return
+// C11
+false
+# C12
+;
+/* C13 */
+EOT
+                ,
+            ],
+            [
+                '<?php if ($bar) { return $bar; } else return (bool) $foo      ;',
+                '<?php if ($bar) { return $bar; } else if ($foo) { return true; } return false;',
+            ],
+            [
+                '<?php if ($bar) { return $bar; } return (bool) $foo      ;',
+                '<?php if ($bar) { return $bar; } elseif ($foo) { return true; } return false;',
+            ],
+        ];
+    }
+}

+ 22 - 0
tests/Fixtures/Integration/priority/no_superfluous_elseif,simplified_if_return.test

@@ -0,0 +1,22 @@
+--TEST--
+Integration of fixers: no_superfluous_elseif,simplified_if_return.
+--RULESET--
+{"no_superfluous_elseif": true, "simplified_if_return": true}
+--EXPECT--
+<?php
+if ($a) {
+    return 1;
+}
+return (bool) $b 
+     
+
+ ;
+
+--INPUT--
+<?php
+if ($a) {
+    return 1;
+} elseif ($b) {
+    return true;
+}
+return false;

+ 19 - 0
tests/Fixtures/Integration/priority/no_useless_else,simplified_if_return.test

@@ -0,0 +1,19 @@
+--TEST--
+Integration of fixers: no_useless_else,simplified_if_return.
+--RULESET--
+{"no_useless_else": true, "simplified_if_return": true}
+--EXPECT--
+<?php
+return (bool) $a 
+     
+  
+     ;
+
+
+--INPUT--
+<?php
+if ($a) {
+    return true;
+} else {
+    return false;
+}

+ 14 - 0
tests/Fixtures/Integration/priority/simplified_if_return,no_multiline_whitespace_before_semicolons.test

@@ -0,0 +1,14 @@
+--TEST--
+Integration of fixers: simplified_if_return,no_multiline_whitespace_before_semicolons.
+--RULESET--
+{"simplified_if_return": true, "no_multiline_whitespace_before_semicolons": true}
+--EXPECT--
+<?php
+return (bool) $b;
+
+--INPUT--
+<?php
+if ($b) {
+    return true;
+}
+return false;

+ 11 - 0
tests/Fixtures/Integration/priority/simplified_if_return,no_singleline_whitespace_before_semicolons.test

@@ -0,0 +1,11 @@
+--TEST--
+Integration of fixers: simplified_if_return,no_singleline_whitespace_before_semicolons.
+--RULESET--
+{"simplified_if_return": true, "no_singleline_whitespace_before_semicolons": true}
+--EXPECT--
+<?php
+return (bool) $b;
+
+--INPUT--
+<?php
+if ($b) { return true; } return false;