diff --git a/.travis.yml b/.travis.yml index e466f4d9f4e..44ba55df313 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ jobs: | grep -v tests/TestCase.php \ && (echo "UNKNOWN FILES DETECTED" && travis_terminate 1) || echo "NO UNKNOWN FILES" - ./check_trailing_spaces.sh || travis_terminate 1 - - php -d auto_prepend_file=dev-tools/vendor/autoload.php ./dev-tools/tools/phpstan analyse + - dev-tools/vendor/bin/phpstan analyse - if [ -n "$CHANGED_PHP_FILES" ]; then ./dev-tools/vendor/bin/phpmd `echo "$CHANGED_PHP_FILES" | xargs | sed 's/ /,/g'` text phpmd.xml || travis_terminate 1; fi - ./dev-tools/tools/composer-require-checker check composer.json --config-file $(realpath .composer-require-checker.json) || travis_terminate 1 - ./dev-tools/tools/composer-normalize composer.json --dry-run diff --git a/dev-tools/composer.json b/dev-tools/composer.json index 3a048730eff..9f27dbda155 100644 --- a/dev-tools/composer.json +++ b/dev-tools/composer.json @@ -7,6 +7,7 @@ "jangregor/phpstan-prophecy": "^0.6", "mi-schi/phpmd-extension": "^4.3", "phpmd/phpmd": "^2.6", + "phpstan/phpstan": "0.12.18", "phpstan/phpstan-phpunit": "^0.12" }, "conflict": { diff --git a/dev-tools/install.sh b/dev-tools/install.sh index a6e3f607dbd..9e7a5837695 100755 --- a/dev-tools/install.sh +++ b/dev-tools/install.sh @@ -39,7 +39,7 @@ fi bin/phive --version echo λλλ phive packages -./bin/phive install --trust-gpg-keys D2CCAC42F6295E7D,8E730BA25823D8B5,C00543248C87FB13,CF1A108D0E7AE720 +./bin/phive install --trust-gpg-keys D2CCAC42F6295E7D,8E730BA25823D8B5,C00543248C87FB13 echo λλλ checkbashisms if [ ! -x bin/checkbashisms ]; then diff --git a/dev-tools/phive.xml b/dev-tools/phive.xml index 2325d678222..1020304b79d 100644 --- a/dev-tools/phive.xml +++ b/dev-tools/phive.xml @@ -2,5 +2,4 @@ - diff --git a/phpstan.neon b/phpstan.neon index 35e19d1b86c..2634812be32 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,9 +1,10 @@ includes: - dev-tools/vendor/jangregor/phpstan-prophecy/src/extension.neon + - dev-tools/vendor/phpstan/phpstan/conf/bleedingEdge.neon - dev-tools/vendor/phpstan/phpstan-phpunit/extension.neon parameters: - level: 3 + level: 5 paths: - src - tests @@ -16,3 +17,33 @@ parameters: - message: '/^Unsafe usage of new static\(\)\.$/' path: src/Config.php + - + message: '/^Else branch is unreachable because previous condition is always true\.$/' + path: src/Event/Event.php + - + message: '/^Strict comparison using !== between ''@git-commit@'' and ''@git-commit@'' will always evaluate to false\.$/' + path: src/Console/Application.php + - + message: '/^Result of && is always false\.$/' + path: src/Config.php + - + message: '/^Strict comparison using === between false and true will always evaluate to false\.$/' + path: src/Config.php + - + message: '/^Else branch is unreachable because ternary operator condition is always true\.$/' + paths: + - src/Config.php + - src/Tokenizer/Token.php + - + message: '/^Parameter #1 \$fixers of method PhpCsFixer\\Config::registerCustomFixers\(\) expects iterable, string given\.$/' + path: tests/ConfigTest.php + - + message: '/^Parameter #1 \$options of method PhpCsFixer\\FixerConfiguration\\FixerConfigurationResolverRootless::resolve\(\) expects array, array given\.$/' + path: tests/FixerConfiguration/FixerConfigurationResolverRootlessTest.php + - + message: '/^Parameter #1 \$function of function register_shutdown_function expects callable\(\): void, array\(\$this\(PhpCsFixer\\FileRemoval\), ''clean''\) given\.$/' + path: src/FileRemoval.php + - + message: '/^Parameter #1 \$finder of method PhpCsFixer\\Config::setFinder\(\) expects iterable, int given\.$/' + path: tests/ConfigTest.php + tipsOfTheDay: false diff --git a/src/AbstractNoUselessElseFixer.php b/src/AbstractNoUselessElseFixer.php index 1ff0faf9530..947362b5d67 100644 --- a/src/AbstractNoUselessElseFixer.php +++ b/src/AbstractNoUselessElseFixer.php @@ -162,7 +162,7 @@ private function isInConditionWithoutBraces(Tokens $tokens, $index, $lowerLimitI return true; } - if ($token->equals(';', '}')) { + if ($token->equals(';')) { return false; } if ($token->equals('{')) { diff --git a/src/Cache/Cache.php b/src/Cache/Cache.php index cf75f9ed11d..a2e7aa7e959 100644 --- a/src/Cache/Cache.php +++ b/src/Cache/Cache.php @@ -55,13 +55,6 @@ public function get($file) public function set($file, $hash) { - if (!\is_int($hash)) { - throw new \InvalidArgumentException(sprintf( - 'Value needs to be an integer, got "%s".', - \is_object($hash) ? \get_class($hash) : \gettype($hash) - )); - } - $this->hashes[$file] = $hash; } @@ -105,7 +98,7 @@ public static function fromJson($json) if (null === $data && JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException(sprintf( 'Value needs to be a valid JSON string, got "%s", error: "%s".', - \is_object($json) ? \get_class($json) : \gettype($json), + $json, json_last_error_msg() )); } diff --git a/src/ConfigurationException/InvalidConfigurationException.php b/src/ConfigurationException/InvalidConfigurationException.php index f73ff193e0c..3c4e43978a9 100644 --- a/src/ConfigurationException/InvalidConfigurationException.php +++ b/src/ConfigurationException/InvalidConfigurationException.php @@ -25,10 +25,11 @@ class InvalidConfigurationException extends \InvalidArgumentException { /** - * @param string $message - * @param null|int $code + * @param string $message + * @param null|int $code + * @param null|\Throwable $previous */ - public function __construct($message, $code = null, \Exception $previous = null) + public function __construct($message, $code = null, $previous = null) { parent::__construct( $message, diff --git a/src/ConfigurationException/InvalidFixerConfigurationException.php b/src/ConfigurationException/InvalidFixerConfigurationException.php index 9936cdb0a52..b5c3322e7d8 100644 --- a/src/ConfigurationException/InvalidFixerConfigurationException.php +++ b/src/ConfigurationException/InvalidFixerConfigurationException.php @@ -30,10 +30,11 @@ class InvalidFixerConfigurationException extends InvalidConfigurationException private $fixerName; /** - * @param string $fixerName - * @param string $message + * @param string $fixerName + * @param string $message + * @param null|\Throwable $previous */ - public function __construct($fixerName, $message, \Exception $previous = null) + public function __construct($fixerName, $message, $previous = null) { parent::__construct( sprintf('[%s] %s', $fixerName, $message), diff --git a/src/Console/Application.php b/src/Console/Application.php index ab4a2a5b745..9dcbbcd2622 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -97,11 +97,11 @@ public function doRun(InputInterface $input, OutputInterface $output) */ public function getLongVersion() { - $version = parent::getLongVersion(); - if (self::VERSION_CODENAME) { - $version .= ' '.self::VERSION_CODENAME.''; - } - $version .= ' by Fabien Potencier and Dariusz Ruminski'; + $version = sprintf( + '%s %s by Fabien Potencier and Dariusz Ruminski', + parent::getLongVersion(), + self::VERSION_CODENAME + ); $commit = '@git-commit@'; diff --git a/src/Console/ConfigurationResolver.php b/src/Console/ConfigurationResolver.php index de8a095f896..28da8856914 100644 --- a/src/Console/ConfigurationResolver.php +++ b/src/Console/ConfigurationResolver.php @@ -847,7 +847,7 @@ static function ($path) { } return new \CallbackFilterIterator( - $nestedFinder, + new \IteratorIterator($nestedFinder), static function (\SplFileInfo $current) use ($pathsByType) { $currentRealPath = $current->getRealPath(); diff --git a/src/Fixer/Basic/BracesFixer.php b/src/Fixer/Basic/BracesFixer.php index 765a776a3fa..3af76754caa 100644 --- a/src/Fixer/Basic/BracesFixer.php +++ b/src/Fixer/Basic/BracesFixer.php @@ -212,12 +212,15 @@ private function fixCommentBeforeBrace(Tokens $tokens) continue; } + /** @var Token $tokenTmp */ $tokenTmp = $tokens[$braceIndex]; $newBraceIndex = $prevIndex + 1; for ($i = $braceIndex; $i > $newBraceIndex; --$i) { // we might be moving one white space next to another, these have to be merged - $tokens[$i] = $tokens[$i - 1]; + /** @var Token $previousToken */ + $previousToken = $tokens[$i - 1]; + $tokens[$i] = $previousToken; if ($tokens[$i]->isWhitespace() && $tokens[$i + 1]->isWhitespace()) { $tokens[$i] = new Token([T_WHITESPACE, $tokens[$i]->getContent().$tokens[$i + 1]->getContent()]); $tokens->clearAt($i + 1); @@ -809,8 +812,6 @@ private function findStatementEnd(Tokens $tokens, $parenthesisEndIndex) return $tokens->getPrevNonWhitespace($index); } } - - throw new \RuntimeException('Statement end not found.'); } private function getControlTokens() diff --git a/src/Fixer/Basic/EncodingFixer.php b/src/Fixer/Basic/EncodingFixer.php index b193a8dc474..9bb271223b5 100644 --- a/src/Fixer/Basic/EncodingFixer.php +++ b/src/Fixer/Basic/EncodingFixer.php @@ -77,6 +77,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens) $content = $tokens[0]->getContent(); if (0 === strncmp($content, $this->BOM, 3)) { + /** @var false|string $newContent until support for PHP 5.6 is dropped */ $newContent = substr($content, 3); if (false === $newContent) { diff --git a/src/Fixer/Basic/Psr0Fixer.php b/src/Fixer/Basic/Psr0Fixer.php index e3fb55c9f06..f0ce65a1205 100644 --- a/src/Fixer/Basic/Psr0Fixer.php +++ b/src/Fixer/Basic/Psr0Fixer.php @@ -105,6 +105,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens) $dir = \dirname($path); if ('' !== $this->configuration['dir']) { + /** @var false|string $dir until support for PHP 5.6 is dropped */ $dir = substr($dir, \strlen(realpath($this->configuration['dir'])) + 1); if (false === $dir) { @@ -120,6 +121,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens) } } + /** @var false|string $dir until support for PHP 5.6 is dropped */ $dir = substr($dir, -\strlen($normNamespace)); if (false === $dir) { $dir = ''; diff --git a/src/Fixer/ClassNotation/OrderedClassElementsFixer.php b/src/Fixer/ClassNotation/OrderedClassElementsFixer.php index 5a64e64cc05..02292d08d30 100644 --- a/src/Fixer/ClassNotation/OrderedClassElementsFixer.php +++ b/src/Fixer/ClassNotation/OrderedClassElementsFixer.php @@ -346,8 +346,6 @@ private function getElements(Tokens $tokens, $startIndex) $elements[] = $element; $startIndex = $element['end'] + 1; } - - return []; } /** diff --git a/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php b/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php index 0ab1a334222..d06235f0d63 100644 --- a/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php +++ b/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php @@ -225,7 +225,7 @@ private function combineDirnames(Tokens $tokens, array $dirnameInfoArray) $prev = $tokens->getPrevMeaningfulToken($outerDirnameInfo['end']); $items = []; if (!$tokens[$prev]->equals(',')) { - $items[] = new Token(','); + $items = [new Token(','), new Token([T_WHITESPACE, ' '])]; } $items[] = $levelsToken; $tokens->insertAt($outerDirnameInfo['end'], $items); diff --git a/src/Fixer/Phpdoc/PhpdocAlignFixer.php b/src/Fixer/Phpdoc/PhpdocAlignFixer.php index 9bad750395c..b814a12c0fd 100644 --- a/src/Fixer/Phpdoc/PhpdocAlignFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAlignFixer.php @@ -333,7 +333,7 @@ private function fixDocBlock(DocBlock $docBlock) * @param string $line * @param bool $matchCommentOnly * - * @return null|string[] + * @return null|array */ private function getMatches($line, $matchCommentOnly = false) { diff --git a/src/Runner/FileFilterIterator.php b/src/Runner/FileFilterIterator.php index a1c6d54a977..7a4ac229afa 100644 --- a/src/Runner/FileFilterIterator.php +++ b/src/Runner/FileFilterIterator.php @@ -41,10 +41,14 @@ final class FileFilterIterator extends \FilterIterator private $visitedElements = []; public function __construct( - \Iterator $iterator, + \Traversable $iterator, EventDispatcherInterface $eventDispatcher = null, CacheManagerInterface $cacheManager ) { + if (!$iterator instanceof \Iterator) { + $iterator = new \IteratorIterator($iterator); + } + parent::__construct($iterator); $this->eventDispatcher = $eventDispatcher; diff --git a/src/Tokenizer/Tokens.php b/src/Tokenizer/Tokens.php index ae019c04898..5a29196a42e 100644 --- a/src/Tokenizer/Tokens.php +++ b/src/Tokenizer/Tokens.php @@ -25,9 +25,6 @@ * @author Dariusz Rumiński * * @extends \SplFixedArray - * - * @method Token current() - * @method Token offsetGet($index) */ class Tokens extends \SplFixedArray { @@ -315,7 +312,7 @@ public function offsetSet($index, $newval) { $this->blockEndCache = []; - if (!$this[$index] || !$this[$index]->equals($newval)) { + if (!isset($this[$index]) || !$this[$index]->equals($newval)) { $this->changed = true; if (isset($this[$index])) { @@ -365,7 +362,9 @@ public function clearEmptyTokens() for ($count = $index; $index < $limit; ++$index) { if (!$this->isEmptyAt($index)) { - $this[$count++] = $this[$index]; + /** @var Token $token */ + $token = $this[$index]; + $this[$count++] = $token; } } @@ -870,8 +869,8 @@ public function findSequence(array $sequence, $start = 0, $end = null, $caseSens /** * Insert instances of Token inside collection. * - * @param int $index start inserting index - * @param Token|Token[]|Tokens $items instances of Token to insert + * @param int $index start inserting index + * @param array|Token|Tokens $items instances of Token to insert */ public function insertAt($index, $items) { @@ -963,9 +962,9 @@ public function overrideAt($index, $token) /** * Override tokens at given range. * - * @param int $indexStart start overriding index - * @param int $indexEnd end overriding index - * @param Token[]|Tokens $items tokens to insert + * @param int $indexStart start overriding index + * @param int $indexEnd end overriding index + * @param array|Tokens $items tokens to insert */ public function overrideRange($indexStart, $indexEnd, $items) { diff --git a/tests/Cache/CacheTest.php b/tests/Cache/CacheTest.php index 35161e9f07a..f5c3dfc778d 100644 --- a/tests/Cache/CacheTest.php +++ b/tests/Cache/CacheTest.php @@ -63,19 +63,6 @@ public function testDefaults() static::assertNull($cache->get($file)); } - public function testSetThrowsInvalidArgumentExceptionIfValueIsNotAnInteger() - { - $this->expectException(\InvalidArgumentException::class); - - $signature = $this->getSignatureDouble(); - - $cache = new Cache($signature); - - $file = 'test.php'; - - $cache->set($file, null); - } - public function testCanSetAndGetValue() { $signature = $this->getSignatureDouble(); diff --git a/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php b/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php index 05e95bbd02d..bdb503e7923 100644 --- a/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php +++ b/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php @@ -48,19 +48,19 @@ public function provideFixCases() 'doTest($expected, $input); diff --git a/tests/FixerDefinition/FixerDefinitionTest.php b/tests/FixerDefinition/FixerDefinitionTest.php index ee74a1d1d4a..edc10300bff 100644 --- a/tests/FixerDefinition/FixerDefinitionTest.php +++ b/tests/FixerDefinition/FixerDefinitionTest.php @@ -12,6 +12,7 @@ namespace PhpCsFixer\Tests\FixerDefinition; +use PhpCsFixer\FixerDefinition\CodeSampleInterface; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\Tests\TestCase; @@ -31,9 +32,14 @@ public function testGetSummary() public function testGetCodeSamples() { - $definition = new FixerDefinition('', ['Bar', 'Baz']); + $samples = [ + $this->prophesize(CodeSampleInterface::class)->reveal(), + $this->prophesize(CodeSampleInterface::class)->reveal(), + ]; - static::assertSame(['Bar', 'Baz'], $definition->getCodeSamples()); + $definition = new FixerDefinition('', $samples); + + static::assertSame($samples, $definition->getCodeSamples()); } public function testGetDescription() diff --git a/tests/Fixtures/Integration/misc/combine_nested_dirname,no_trailing_whitespace.test b/tests/Fixtures/Integration/misc/combine_nested_dirname,no_trailing_whitespace.test index 4de41fd5ea0..7621a110a0e 100644 --- a/tests/Fixtures/Integration/misc/combine_nested_dirname,no_trailing_whitespace.test +++ b/tests/Fixtures/Integration/misc/combine_nested_dirname,no_trailing_whitespace.test @@ -7,7 +7,7 @@ Integration of fixers: combine_nested_dirname,no_trailing_whitespace. --EXPECT-- addToAssertionCount(1); + if (!$setup()) { + $this->addToAssertionCount(1); + } } /** @@ -147,7 +149,9 @@ public function testPatternsValidation($pattern, $expected = null, $expectedExce return; } - $setup() || $this->addToAssertionCount(1); + if (!$setup()) { + $this->addToAssertionCount(1); + } } public function testMatchAllFailing() diff --git a/tests/RuleSetTest.php b/tests/RuleSetTest.php index e65dc2a85d8..43e70b84453 100644 --- a/tests/RuleSetTest.php +++ b/tests/RuleSetTest.php @@ -663,8 +663,6 @@ public function testHasIntegrationTest($setDefinitionName) if (\in_array($setDefinitionName, $setsWithoutTests, true)) { static::markTestIncomplete(sprintf('Set "%s" has no integration test.', $setDefinitionName)); - - return; } $setDefinitionFileNamePrefix = str_replace(':', '-', $setDefinitionName); diff --git a/tests/Test/IntegrationCase.php b/tests/Test/IntegrationCase.php index b0995d2af12..41487990c2b 100644 --- a/tests/Test/IntegrationCase.php +++ b/tests/Test/IntegrationCase.php @@ -120,13 +120,6 @@ public function getInputCode() */ public function getRequirement($name) { - if (!\is_string($name)) { - throw new \InvalidArgumentException(sprintf( - 'Requirement key must be a string, got "%s".', - \is_object($name) ? \get_class($name) : \gettype($name).'#'.$name - )); - } - if (!\array_key_exists($name, $this->requirements)) { throw new \InvalidArgumentException(sprintf( 'Unknown requirement key "%s", expected any of "%s".',