Browse Source

Merge branch '2.12' into 2.14

* 2.12:
  fix FileLintingIterator current value on end/invalid
  MethodArgumentSpaceFixer - handle misplaced )
  fix conflicts
  MethodArgumentSpaceFixer - fix for on_multiline:ensure_fully_multiline with trailing comma in function call
  DX: test to ensure @PHPUnitMigration rule sets are correctly defined
  Fix non-static closure unbinding this on PHP 7.4
  FunctionTypehintSpaceFixer - Ensure single space between type declaration and parameter
  Test ReadmeCommand with CommandTester
  fix access to reference without checking existence
  DX: static call of markTestSkippedOrFail

# Conflicts:
#	tests/Fixer/FunctionNotation/PhpdocToReturnTypeFixerTest.php
SpacePossum 5 years ago
parent
commit
db00b778e6

+ 1 - 1
README.rst

@@ -705,7 +705,7 @@ Choose from the list of available rules:
 
 * **function_typehint_space** [@Symfony, @PhpCsFixer]
 
-  Add missing space between function's argument and its typehint.
+  Ensure single space between function's argument and its typehint.
 
 * **general_phpdoc_annotation_remove**
 

+ 2 - 2
src/Fixer/ControlStructure/NoBreakCommentFixer.php

@@ -74,7 +74,7 @@ switch ($foo) {
             (new FixerOptionBuilder('comment_text', 'The text to use in the added comment and to detect it.'))
                 ->setAllowedTypes(['string'])
                 ->setAllowedValues([
-                    function ($value) {
+                    static function ($value) {
                         if (\is_string($value) && Preg::match('/\R/', $value)) {
                             throw new InvalidOptionsException('The comment text must not contain new lines.');
                         }
@@ -82,7 +82,7 @@ switch ($foo) {
                         return true;
                     },
                 ])
-                ->setNormalizer(function (Options $options, $value) {
+                ->setNormalizer(static function (Options $options, $value) {
                     return rtrim($value);
                 })
                 ->setDefault('no break')

+ 21 - 21
src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php

@@ -15,6 +15,8 @@ namespace PhpCsFixer\Fixer\FunctionNotation;
 use PhpCsFixer\AbstractFixer;
 use PhpCsFixer\FixerDefinition\CodeSample;
 use PhpCsFixer\FixerDefinition\FixerDefinition;
+use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis;
+use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
 use PhpCsFixer\Tokenizer\Token;
 use PhpCsFixer\Tokenizer\Tokens;
 
@@ -29,8 +31,11 @@ final class FunctionTypehintSpaceFixer extends AbstractFixer
     public function getDefinition()
     {
         return new FixerDefinition(
-            'Add missing space between function\'s argument and its typehint.',
-            [new CodeSample("<?php\nfunction sample(array\$a)\n{}\n")]
+            'Ensure single space between function\'s argument and its typehint.',
+            [
+                new CodeSample("<?php\nfunction sample(array\$a)\n{}\n"),
+                new CodeSample("<?php\nfunction sample(array  \$a)\n{}\n"),
+            ]
         );
     }
 
@@ -47,6 +52,8 @@ final class FunctionTypehintSpaceFixer extends AbstractFixer
      */
     protected function applyFix(\SplFileInfo $file, Tokens $tokens)
     {
+        $functionsAnalyzer = new FunctionsAnalyzer();
+
         for ($index = $tokens->count() - 1; $index >= 0; --$index) {
             $token = $tokens[$index];
 
@@ -54,33 +61,26 @@ final class FunctionTypehintSpaceFixer extends AbstractFixer
                 continue;
             }
 
-            $startParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(', ';', [T_CLOSE_TAG]]);
-            if (!$tokens[$startParenthesisIndex]->equals('(')) {
-                continue;
-            }
+            $arguments = $functionsAnalyzer->getFunctionArguments($tokens, $index);
 
-            $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex);
+            foreach (array_reverse($arguments) as $argument) {
+                $type = $argument->getTypeAnalysis();
 
-            for ($iter = $endParenthesisIndex - 1; $iter > $startParenthesisIndex; --$iter) {
-                if (!$tokens[$iter]->isGivenKind(T_VARIABLE)) {
+                if (!$type instanceof TypeAnalysis) {
                     continue;
                 }
 
-                // skip ... before $variable for variadic parameter
-                $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter);
-                if ($tokens[$prevNonWhitespaceIndex]->isGivenKind(T_ELLIPSIS)) {
-                    $iter = $prevNonWhitespaceIndex;
-                }
+                $whitespaceTokenIndex = $type->getEndIndex() + 1;
 
-                // skip & before $variable for parameter passed by reference
-                $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter);
-                if ($tokens[$prevNonWhitespaceIndex]->equals('&')) {
-                    $iter = $prevNonWhitespaceIndex;
-                }
+                if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE])) {
+                    if (' ' === $tokens[$whitespaceTokenIndex]->getContent()) {
+                        continue;
+                    }
 
-                if (!$tokens[$iter - 1]->equalsAny([[T_WHITESPACE], [T_COMMENT], [T_DOC_COMMENT], '(', ','])) {
-                    $tokens->insertAt($iter, new Token([T_WHITESPACE, ' ']));
+                    $tokens->clearAt($whitespaceTokenIndex);
                 }
+
+                $tokens->insertAt($whitespaceTokenIndex, new Token([T_WHITESPACE, ' ']));
             }
         }
     }

+ 11 - 6
src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php

@@ -326,13 +326,13 @@ final class MethodArgumentSpaceFixer extends AbstractFixer implements Configurat
         $indentation = $existingIndentation.$this->whitespacesConfig->getIndent();
         $endFunctionIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startFunctionIndex);
 
-        if (!$this->isNewline($tokens[$endFunctionIndex - 1])) {
-            $tokens->ensureWhitespaceAtIndex(
-                $endFunctionIndex,
-                0,
-                $this->whitespacesConfig->getLineEnding().$existingIndentation
-            );
+        $wasWhitespaceBeforeEndFunctionAddedAsNewToken = $tokens->ensureWhitespaceAtIndex(
+            $tokens[$endFunctionIndex - 1]->isWhitespace() ? $endFunctionIndex - 1 : $endFunctionIndex,
+            0,
+            $this->whitespacesConfig->getLineEnding().$existingIndentation
+        );
 
+        if ($wasWhitespaceBeforeEndFunctionAddedAsNewToken) {
             ++$endFunctionIndex;
         }
 
@@ -390,6 +390,11 @@ final class MethodArgumentSpaceFixer extends AbstractFixer implements Configurat
             return;
         }
 
+        $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken($index);
+        if ($tokens[$nextMeaningfulTokenIndex]->equals(')')) {
+            return;
+        }
+
         $tokens->ensureWhitespaceAtIndex($index + 1, 0, $this->whitespacesConfig->getLineEnding().$indentation);
     }
 

+ 6 - 7
src/Runner/FileLintingIterator.php

@@ -28,7 +28,7 @@ final class FileLintingIterator extends \IteratorIterator
     private $currentResult;
 
     /**
-     * @var LinterInterface
+     * @var null|LinterInterface
      */
     private $linter;
 
@@ -39,6 +39,9 @@ final class FileLintingIterator extends \IteratorIterator
         $this->linter = $linter;
     }
 
+    /**
+     * @return null|LinterInterface
+     */
     public function currentLintingResult()
     {
         return $this->currentResult;
@@ -48,18 +51,14 @@ final class FileLintingIterator extends \IteratorIterator
     {
         parent::next();
 
-        if ($this->valid()) {
-            $this->currentResult = $this->handleItem($this->current());
-        }
+        $this->currentResult = $this->valid() ? $this->handleItem($this->current()) : null;
     }
 
     public function rewind()
     {
         parent::rewind();
 
-        if ($this->valid()) {
-            $this->currentResult = $this->handleItem($this->current());
-        }
+        $this->currentResult = $this->valid() ? $this->handleItem($this->current()) : null;
     }
 
     private function handleItem(\SplFileInfo $file)

+ 1 - 1
src/ToolInfo.php

@@ -64,7 +64,7 @@ final class ToolInfo implements ToolInfoInterface
 
         $versionSuffix = '';
 
-        if (isset($package['dist'])) {
+        if (isset($package['dist']['reference'])) {
             $versionSuffix = '#'.$package['dist']['reference'];
         }
 

+ 0 - 1
tests/AutoReview/ProjectCodeTest.php

@@ -48,7 +48,6 @@ final class ProjectCodeTest extends TestCase
         \PhpCsFixer\Fixer\Operator\AlignEqualsFixerHelper::class,
         \PhpCsFixer\Fixer\Whitespace\NoExtraConsecutiveBlankLinesFixer::class,
         \PhpCsFixer\Runner\FileCachingLintingIterator::class,
-        \PhpCsFixer\Runner\FileLintingIterator::class,
         \PhpCsFixer\Test\AccessibleObject::class,
     ];
 

+ 5 - 10
tests/Console/Command/ReadmeCommandTest.php

@@ -14,9 +14,7 @@ namespace PhpCsFixer\Tests\Console\Command;
 
 use PhpCsFixer\Console\Application;
 use PhpCsFixer\Tests\TestCase;
-use Symfony\Component\Console\Input\ArrayInput;
-use Symfony\Component\Console\Output\BufferedOutput;
-use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Tester\CommandTester;
 
 /**
  * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
@@ -36,15 +34,12 @@ final class ReadmeCommandTest extends TestCase
         $fileContent = file_get_contents($readmeFile);
         static::assertInternalType('string', $fileContent, sprintf('Failed to get content of "%s"', $readmeFile));
 
-        $app = new Application();
-        $input = new ArrayInput(['readme']);
+        $application = new Application();
 
-        $output = new BufferedOutput();
-        $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
-        $output->setDecorated(false);
+        $commandTester = new CommandTester($application->get('readme'));
 
-        $exitCode = $app->get('readme')->run($input, $output);
-        $output = $output->fetch();
+        $exitCode = $commandTester->execute([]);
+        $output = $commandTester->getDisplay();
         // normalize line breaks, these are not important for the tests
         $output = str_replace(PHP_EOL, "\n", $output);
 

+ 68 - 2
tests/Fixer/FunctionNotation/FunctionTypehintSpaceFixerTest.php

@@ -52,58 +52,124 @@ final class FunctionTypehintSpaceFixerTest extends AbstractFixerTestCase
             [
                 '<?php function foo(/**int*/$param) {}',
             ],
+            [
+                '<?php function foo(bool /**bla bla*/ $param) {}',
+            ],
+            [
+                '<?php function foo(bool /**bla bla*/$param) {}',
+                '<?php function foo(bool/**bla bla*/$param) {}',
+            ],
+            [
+                '<?php function foo(bool /**bla bla*/$param) {}',
+                '<?php function foo(bool  /**bla bla*/$param) {}',
+            ],
             [
                 '<?php function foo(callable $param) {}',
                 '<?php function foo(callable$param) {}',
             ],
+            [
+                '<?php function foo(callable $param) {}',
+                '<?php function foo(callable  $param) {}',
+            ],
             [
                 '<?php function foo(array &$param) {}',
                 '<?php function foo(array&$param) {}',
             ],
+            [
+                '<?php function foo(array &$param) {}',
+                '<?php function foo(array  &$param) {}',
+            ],
             [
                 '<?php function foo(array & $param) {}',
                 '<?php function foo(array& $param) {}',
             ],
+            [
+                '<?php function foo(array & $param) {}',
+                '<?php function foo(array  & $param) {}',
+            ],
             [
                 '<?php function foo(Bar $param) {}',
                 '<?php function foo(Bar$param) {}',
             ],
+            [
+                '<?php function foo(Bar $param) {}',
+                '<?php function foo(Bar  $param) {}',
+            ],
             [
                 '<?php function foo(Bar\Baz $param) {}',
                 '<?php function foo(Bar\Baz$param) {}',
             ],
+            [
+                '<?php function foo(Bar\Baz $param) {}',
+                '<?php function foo(Bar\Baz  $param) {}',
+            ],
             [
                 '<?php function foo(Bar\Baz &$param) {}',
                 '<?php function foo(Bar\Baz&$param) {}',
             ],
+            [
+                '<?php function foo(Bar\Baz &$param) {}',
+                '<?php function foo(Bar\Baz  &$param) {}',
+            ],
             [
                 '<?php function foo(Bar\Baz & $param) {}',
                 '<?php function foo(Bar\Baz& $param) {}',
             ],
+            [
+                '<?php function foo(Bar\Baz & $param) {}',
+                '<?php function foo(Bar\Baz  & $param) {}',
+            ],
             [
                 '<?php $foo = function(Bar\Baz $param) {};',
                 '<?php $foo = function(Bar\Baz$param) {};',
             ],
+            [
+                '<?php $foo = function(Bar\Baz $param) {};',
+                '<?php $foo = function(Bar\Baz  $param) {};',
+            ],
             [
                 '<?php $foo = function(Bar\Baz &$param) {};',
                 '<?php $foo = function(Bar\Baz&$param) {};',
             ],
+            [
+                '<?php $foo = function(Bar\Baz &$param) {};',
+                '<?php $foo = function(Bar\Baz  &$param) {};',
+            ],
             [
                 '<?php $foo = function(Bar\Baz & $param) {};',
                 '<?php $foo = function(Bar\Baz& $param) {};',
             ],
+            [
+                '<?php $foo = function(Bar\Baz & $param) {};',
+                '<?php $foo = function(Bar\Baz  & $param) {};',
+            ],
             [
                 '<?php class Test { public function foo(Bar\Baz $param) {} }',
                 '<?php class Test { public function foo(Bar\Baz$param) {} }',
             ],
+            [
+                '<?php class Test { public function foo(Bar\Baz $param) {} }',
+                '<?php class Test { public function foo(Bar\Baz  $param) {} }',
+            ],
             [
                 '<?php $foo = function(array $a,
-                    array $b, array     $c, array
-                    $d) {};',
+                    array $b, array $c, array $d) {};',
                 '<?php $foo = function(array $a,
                     array$b, array     $c, array
                     $d) {};',
             ],
+            [
+                '<?php $foo = function(
+                    array $a,
+                    $b
+                ) {};',
+            ],
+            [
+                '<?php $foo = function(
+                    $a,
+                    array $b
+                ) {};',
+            ],
             [
                 '<?php function foo(...$param) {}',
             ],

+ 70 - 43
tests/Fixer/FunctionNotation/MethodArgumentSpaceFixerTest.php

@@ -878,6 +878,25 @@ INPUT
                     'keep_multiple_spaces_after_comma' => true,
                 ],
             ],
+            'fix closing parenthesis (without trailing comma)' => [
+                '<?php
+if (true) {
+    execute(
+        $foo,
+        $bar
+    );
+}',
+                '<?php
+if (true) {
+    execute(
+        $foo,
+        $bar
+        );
+}',
+                [
+                    'on_multiline' => 'ensure_fully_multiline',
+                ],
+            ],
         ];
     }
 
@@ -902,6 +921,57 @@ INPUT
         ];
     }
 
+    /**
+     * @param string      $expected
+     * @param null|string $input
+     *
+     * @dataProvider provideFix73Cases
+     * @requires PHP 7.3
+     */
+    public function testFix73($expected, $input = null, array $config = [])
+    {
+        $this->fixer->configure($config);
+        $this->doTest($expected, $input);
+    }
+
+    public function provideFix73Cases()
+    {
+        return [
+            [
+                <<<'EXPECTED'
+<?php
+foo(
+    $bar,
+    $baz,
+);
+EXPECTED
+                ,
+                null,
+                ['on_multiline' => 'ensure_fully_multiline'],
+            ],
+            [
+                '<?php
+functionCall(
+    1,
+    2,
+    3,
+);',
+                '<?php
+functionCall(
+    1, 2,
+    3,
+);',
+                [
+                    'on_multiline' => 'ensure_fully_multiline',
+                ],
+            ],
+            [
+                '<?php foo(1, 2, 3, );',
+                '<?php foo(1,2,3,);',
+            ],
+        ];
+    }
+
     /**
      * @group legacy
      * @expectedDeprecation PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer::fixSpace is deprecated and will be removed in 3.0.
@@ -940,47 +1010,4 @@ INPUT;
 
         $this->doTest($expected, $input);
     }
-
-    /**
-     * @param string      $expected
-     * @param null|string $input
-     * @param null|array  $config
-     *
-     * @requires PHP 7.3
-     * @dataProvider provideFix73Cases
-     */
-    public function testFix73($expected, $input = null, array $config = null)
-    {
-        if (null !== $config) {
-            $this->fixer->configure($config);
-        }
-
-        $this->doTest($expected, $input);
-    }
-
-    public function provideFix73Cases()
-    {
-        return [
-            [
-                '<?php
-functionCall(
-    1,
-    2,
-    3,
-);',
-                '<?php
-functionCall(
-    1, 2,
-    3,
-);',
-                [
-                    'on_multiline' => 'ensure_fully_multiline',
-                ],
-            ],
-            [
-                '<?php foo(1, 2, 3, );',
-                '<?php foo(1,2,3,);',
-            ],
-        ];
-    }
 }

Some files were not shown because too many files changed in this diff