From 026da2b05082e02609bc9ce7288ffd88f274d7e3 Mon Sep 17 00:00:00 2001 From: PedroTroller Date: Thu, 1 Dec 2022 09:04:12 +0100 Subject: [PATCH] refactor: fix phpstan errors --- .circleci/config.yml | 6 +- .php-cs-fixer.dist.php | 2 +- composer.json | 5 +- phpstan.neon.dist | 5 + src/PedroTroller/CS/Fixer/AbstractFixer.php | 6 +- .../AbstractOrderedClassElementsFixer.php | 83 +++++++--- .../CS/Fixer/Behat/OrderBehatStepsFixer.php | 2 +- .../OrderedWithGetterAndSetterFirstFixer.php | 32 ++++ .../ExceptionsPunctuationFixer.php | 10 +- .../LineBreakBetweenMethodArgumentsFixer.php | 10 +- .../LineBreakBetweenStatementsFixer.php | 17 +- src/PedroTroller/CS/Fixer/Fixers.php | 25 +-- src/PedroTroller/CS/Fixer/PhpspecFixer.php | 58 ++++++- src/PedroTroller/CS/Fixer/Priority.php | 14 +- src/PedroTroller/CS/Fixer/RuleSetFactory.php | 115 +++++--------- src/PedroTroller/CS/Fixer/TokenSignatures.php | 15 -- src/PedroTroller/CS/Fixer/TokensAnalyzer.php | 147 ++++++++---------- tests/Runner.php | 4 +- tests/TokensAnalyzerIntegration.php | 25 +-- tests/TokensAnalyzerIntegration/InSwitch.php | 5 +- .../LineIndentation.php | 5 +- .../MethodArguments.php | 5 +- .../NextSemiColon.php | 8 +- .../TokensAnalyzerIntegration/Parenthesis.php | 7 +- .../ReturnedType.php | 13 +- .../SizeOfTheLine.php | 8 +- .../Regression/Case1.php | 4 +- tests/UseCase/Phpspec/Regression/Case1.php | 4 +- tests/UseCase/Phpspec/Regression/Case2.php | 4 +- .../Regression/Case1.php | 4 +- 30 files changed, 331 insertions(+), 317 deletions(-) create mode 100644 phpstan.neon.dist delete mode 100644 src/PedroTroller/CS/Fixer/TokenSignatures.php diff --git a/.circleci/config.yml b/.circleci/config.yml index e16fd37..3fd6488 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -111,15 +111,15 @@ workflows: - tests: matrix: parameters: - php-version: ["7.4", "8.0", "8.1"] + php-version: ["8.0", "8.1"] - tests-with-future-mode: matrix: parameters: - php-version: ["7.4", "8.0", "8.1"] + php-version: ["8.0", "8.1"] - tests-with-lowest-dependencies: matrix: parameters: - php-version: ["7.4", "8.0", "8.1"] + php-version: ["8.0", "8.1"] - release-test - release: requires: diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 12b7c32..570f541 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -10,7 +10,7 @@ ->setRules( RuleSetFactory::create() ->phpCsFixer(true) - ->php(7.4, true) + ->php(8.0, true) ->pedrotroller(true) ->enable('ordered_imports') ->enable('ordered_interfaces') diff --git a/composer.json b/composer.json index 9db60fd..cab7159 100644 --- a/composer.json +++ b/composer.json @@ -3,11 +3,12 @@ "description": "PHP-CS-FIXER : my custom fixers", "license": "MIT", "require": { - "php": "^7.4 || ^8.0", - "friendsofphp/php-cs-fixer": "^3.7" + "php": "^8.0", + "friendsofphp/php-cs-fixer": "^3.9" }, "require-dev": { "phpspec/phpspec": "^7.0", + "phpstan/phpstan": "^1.8", "twig/twig": "^3.3", "webmozart/assert": "^1.10" }, diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..7c87780 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,5 @@ +parameters: + level: 7 + paths: + - src + - tests diff --git a/src/PedroTroller/CS/Fixer/AbstractFixer.php b/src/PedroTroller/CS/Fixer/AbstractFixer.php index 549e599..4a4efb8 100644 --- a/src/PedroTroller/CS/Fixer/AbstractFixer.php +++ b/src/PedroTroller/CS/Fixer/AbstractFixer.php @@ -27,7 +27,7 @@ public function getName(): string } /** - * @return array + * @return array> */ public function getSampleConfigurations(): array { @@ -45,7 +45,7 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( $this->getDocumentation(), array_map( - fn (array $configutation = null) => new CodeSample($this->getSampleCode(), $configutation), + fn (?array $configutation): CodeSample => new CodeSample($this->getSampleCode(), $configutation), $this->getSampleConfigurations() ) ); @@ -76,6 +76,8 @@ protected function hasUseStatements(Tokens $tokens, $fqcn): bool /** * @param string|string[] $fqcn + * + * @return null|array */ protected function getUseStatements(Tokens $tokens, $fqcn): ?array { diff --git a/src/PedroTroller/CS/Fixer/AbstractOrderedClassElementsFixer.php b/src/PedroTroller/CS/Fixer/AbstractOrderedClassElementsFixer.php index 4209dad..8e28215 100644 --- a/src/PedroTroller/CS/Fixer/AbstractOrderedClassElementsFixer.php +++ b/src/PedroTroller/CS/Fixer/AbstractOrderedClassElementsFixer.php @@ -5,6 +5,7 @@ namespace PedroTroller\CS\Fixer; use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; use SplFileInfo; @@ -36,18 +37,49 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void } /** - * @param array[] $elements + * @param array< + * array{ + * start: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type?: string, + * methodName?: string, + * propertyName?: string, + * end?: int + * } + * > $elements * - * @return array[] + * @return array< + * array{ + * start: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type?: string, + * methodName?: string, + * propertyName?: string, + * end?: int + * } + * > */ abstract protected function sortElements(array $elements): array; /** - * @param int $startIndex - * - * @return array[] + * @return array< + * array{ + * start: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type?: string, + * methodName?: string, + * propertyName?: string, + * end?: int + * } + * > */ - private function getElements(Tokens $tokens, $startIndex) + private function getElements(Tokens $tokens, int $startIndex) { static $elementTokenKinds = [CT::T_USE_TRAIT, T_CONST, T_VARIABLE, T_FUNCTION]; @@ -59,6 +91,7 @@ private function getElements(Tokens $tokens, $startIndex) 'start' => $startIndex, 'visibility' => 'public', 'static' => false, + 'comment' => null, ]; for ($i = $startIndex;; ++$i) { @@ -98,6 +131,7 @@ private function getElements(Tokens $tokens, $startIndex) break; } + $element['end'] = $this->findElementEnd($tokens, $i); break; @@ -107,8 +141,6 @@ private function getElements(Tokens $tokens, $startIndex) if (isset($tokens[$possibleCommentIndex]) && $tokens[$possibleCommentIndex]->isComment()) { $element['comment'] = $tokens[$possibleCommentIndex]->getContent(); - } else { - $element['comment'] = null; } $elements[] = $element; @@ -117,11 +149,9 @@ private function getElements(Tokens $tokens, $startIndex) } /** - * @param int $index - * - * @return array|string type or array of type and name + * @return array{string, string}|string */ - private function detectElementType(Tokens $tokens, $index) + private function detectElementType(Tokens $tokens, int $index) { $token = $tokens[$index]; @@ -165,12 +195,7 @@ private function detectElementType(Tokens $tokens, $index) return 'method'; } - /** - * @param int $index - * - * @return int - */ - private function findElementEnd(Tokens $tokens, $index) + private function findElementEnd(Tokens $tokens, int $index): int { $index = $tokens->getNextTokenOfKind($index, ['{', ';']); @@ -186,16 +211,28 @@ private function findElementEnd(Tokens $tokens, $index) } /** - * @param int $startIndex - * @param int $endIndex - * @param array[] $elements + * @param array< + * array{ + * start: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type?: string, + * methodName?: string, + * propertyName?: string, + * end?: int + * } + * > $elements */ private function sortTokens( Tokens $tokens, - $startIndex, - $endIndex, + int $startIndex, + int $endIndex, array $elements ): void { + /** + * @var Token[] + */ $replaceTokens = []; foreach ($elements as $element) { diff --git a/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php b/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php index ea44517..f3ee0b4 100644 --- a/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php +++ b/src/PedroTroller/CS/Fixer/Behat/OrderBehatStepsFixer.php @@ -144,7 +144,7 @@ protected function sortElements(array $elements): array } foreach ($elements as $index => $element) { - if ('method' !== $element['type']) { + if (false === isset($element['type']) || 'method' !== $element['type']) { continue; } diff --git a/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php b/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php index 487f44e..2ea939f 100644 --- a/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php +++ b/src/PedroTroller/CS/Fixer/ClassNotation/OrderedWithGetterAndSetterFirstFixer.php @@ -147,6 +147,22 @@ protected function sortElements(array $elements): array return $result; } + /** + * @param array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > $elements + * + * @return string[] + */ private function getMethodsNames(array $elements): array { $methods = []; @@ -162,6 +178,22 @@ private function getMethodsNames(array $elements): array return $methods; } + /** + * @param array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > $elements + * + * @return string[] + */ private function getPropertiesNames(array $elements): array { $properties = array_filter($elements, fn ($element) => 'property' === $element['type']); diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php index c2a0add..ef36974 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/ExceptionsPunctuationFixer.php @@ -132,7 +132,15 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void $keys = array_keys($case); array_pop($keys); array_pop($case); - $tokens[end($keys)] = $this->cleanupMessage(end($case)); + + $key = end($keys); + $token = end($case); + + if (false === $key || false === $token || false === \is_int($key)) { + continue; + } + + $tokens[$key] = $this->cleanupMessage($token); } } diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php index 208ef3c..ccc1f74 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenMethodArgumentsFixer.php @@ -148,7 +148,7 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void } } - private function splitArgs(Tokens $tokens, $index): void + private function splitArgs(Tokens $tokens, int $index): void { $this->mergeArgs($tokens, $index); @@ -211,7 +211,7 @@ private function splitArgs(Tokens $tokens, $index): void } } - private function mergeArgs(Tokens $tokens, $index): void + private function mergeArgs(Tokens $tokens, int $index): void { $openBraceIndex = $tokens->getNextTokenOfKind($index, ['(']); $closeBraceIndex = $this->analyze($tokens)->getClosingParenthesis($openBraceIndex); @@ -231,7 +231,7 @@ private function mergeArgs(Tokens $tokens, $index): void } } - private function localizeNextCloseBrace(Tokens $tokens, $index) + private function localizeNextCloseBrace(Tokens $tokens, int $index): int { $opening = 0; @@ -252,7 +252,7 @@ private function localizeNextCloseBrace(Tokens $tokens, $index) return 0; } - private function localizeNextCloseBracket(Tokens $tokens, $index) + private function localizeNextCloseBracket(Tokens $tokens, int $index): int { $opening = 0; @@ -273,7 +273,7 @@ private function localizeNextCloseBracket(Tokens $tokens, $index) return 0; } - private function getNumberOfArguments(Tokens $tokens, $index) + private function getNumberOfArguments(Tokens $tokens, int $index): int { if (T_FUNCTION !== $tokens[$index]->getId()) { return 0; diff --git a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenStatementsFixer.php b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenStatementsFixer.php index 699e7e0..dd40b4a 100644 --- a/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenStatementsFixer.php +++ b/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenStatementsFixer.php @@ -67,6 +67,9 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void } } + /** + * @param array $matchedTokens + */ private function handleDo(array $matchedTokens, Tokens $tokens): void { foreach ($matchedTokens as $index => $token) { @@ -77,6 +80,9 @@ private function handleDo(array $matchedTokens, Tokens $tokens): void } } + /** + * @param array $matchedTokens + */ private function handleCommon(array $matchedTokens, Tokens $tokens): void { foreach ($matchedTokens as $index => $token) { @@ -88,12 +94,7 @@ private function handleCommon(array $matchedTokens, Tokens $tokens): void continue; } - $openCurlyBracket = current(array_keys($curlyBracket)); - - if (false === $openCurlyBracket) { - continue; - } - + $openCurlyBracket = current(array_keys($curlyBracket)); $closeCurlyBracket = $this->analyze($tokens)->getClosingCurlyBracket($openCurlyBracket); if (null === $closeCurlyBracket) { @@ -107,7 +108,7 @@ private function handleCommon(array $matchedTokens, Tokens $tokens): void } } - private function fixSpaces($index, Tokens $tokens): void + private function fixSpaces(int $index, Tokens $tokens): void { $space = $index + 1; @@ -128,7 +129,7 @@ private function fixSpaces($index, Tokens $tokens): void $tokens[$space] = new Token([T_WHITESPACE, $this->ensureNumberOfBreaks($tokens[$space]->getContent())]); } - private function ensureNumberOfBreaks($whitespace) + private function ensureNumberOfBreaks(string $whitespace): string { $parts = explode("\n", $whitespace); diff --git a/src/PedroTroller/CS/Fixer/Fixers.php b/src/PedroTroller/CS/Fixer/Fixers.php index 3f16380..1bc295b 100644 --- a/src/PedroTroller/CS/Fixer/Fixers.php +++ b/src/PedroTroller/CS/Fixer/Fixers.php @@ -4,18 +4,18 @@ namespace PedroTroller\CS\Fixer; -use Generator; use IteratorAggregate; use PhpCsFixer\Fixer\FixerInterface; use ReflectionClass; use Symfony\Component\Finder\Finder; +use Traversable; +/** + * @implements IteratorAggregate + */ final class Fixers implements IteratorAggregate { - /** - * {@inheritdoc} - */ - public function getIterator(): Generator + public function getIterator(): Traversable { $finder = Finder::create() ->in(__DIR__) @@ -30,23 +30,26 @@ public function getIterator(): Generator sort($files); foreach ($files as $file) { - $class = str_replace('/', '\\', mb_substr($file, mb_strlen(__DIR__) - 21, -4)); + /** + * @var class-string + */ + $className = str_replace('/', '\\', mb_substr($file, mb_strlen(__DIR__) - 21, -4)); - if (false === class_exists($class)) { + if (false === class_exists($className)) { continue; } - $rfl = new ReflectionClass($class); + $reflection = new ReflectionClass($className); - if (false === $rfl->implementsInterface(FixerInterface::class)) { + if (false === $reflection->implementsInterface(FixerInterface::class)) { continue; } - if ($rfl->isAbstract()) { + if ($reflection->isAbstract()) { continue; } - yield new $class(); + yield new $className(); } } } diff --git a/src/PedroTroller/CS/Fixer/PhpspecFixer.php b/src/PedroTroller/CS/Fixer/PhpspecFixer.php index 40e5fbc..ab0a298 100644 --- a/src/PedroTroller/CS/Fixer/PhpspecFixer.php +++ b/src/PedroTroller/CS/Fixer/PhpspecFixer.php @@ -214,7 +214,7 @@ private function removeReturn(SplFileInfo $file, Tokens $tokens): void $tokens->clearRange($closeBraceIndex + 1, $openCurlyBracket - 1); - if ($tokens[$closeBraceIndex - 1]->isWhitespace() && false !== strpos($tokens[$closeBraceIndex - 1]->getContent(), "\n")) { + if ($tokens[$closeBraceIndex - 1]->isWhitespace() && str_contains($tokens[$closeBraceIndex - 1]->getContent(), "\n")) { $tokens->ensureWhitespaceAtIndex($openCurlyBracket, 0, ' '); } else { $tokens->ensureWhitespaceAtIndex($openCurlyBracket, 0, "\n".$this->analyze($tokens)->getLineIndentation($openBraceIndex)); @@ -222,12 +222,39 @@ private function removeReturn(SplFileInfo $file, Tokens $tokens): void } } + /** + * @param array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > $elements + * + * @return array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > + */ private function filterElementsByMethodName(string $regex, array $elements): array { $filter = []; foreach ($this->filterElementsByType('method', $elements) as $index => $method) { - if (0 !== preg_match(sprintf('/^%s$/', $regex), $method['methodName'])) { + if (\array_key_exists('methodName', $method) && 0 !== preg_match(sprintf('/^%s$/', $regex), $method['methodName'])) { $filter[$index] = $method; } } @@ -235,6 +262,33 @@ private function filterElementsByMethodName(string $regex, array $elements): arr return $filter; } + /** + * @param array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > $elements + * + * @return array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * comment: ?string, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > + */ private function filterElementsByType(string $type, array $elements): array { $filter = []; diff --git a/src/PedroTroller/CS/Fixer/Priority.php b/src/PedroTroller/CS/Fixer/Priority.php index 6d6d5ae..bea415a 100644 --- a/src/PedroTroller/CS/Fixer/Priority.php +++ b/src/PedroTroller/CS/Fixer/Priority.php @@ -4,6 +4,8 @@ namespace PedroTroller\CS\Fixer; +use PhpCsFixer\Fixer\FixerInterface; + final class Priority { private function __construct() @@ -11,11 +13,9 @@ private function __construct() } /** - * @param array $classes - * - * @return int + * @param class-string $classes */ - public static function before(...$classes) + public static function before(string ...$classes): int { $priorities = array_map( fn ($class) => (new $class())->getPriority(), @@ -26,11 +26,9 @@ public static function before(...$classes) } /** - * @param array $classes - * - * @return int + * @param class-string $classes */ - public static function after(...$classes) + public static function after(string ...$classes): int { $priorities = array_map( fn ($class) => (new $class())->getPriority(), diff --git a/src/PedroTroller/CS/Fixer/RuleSetFactory.php b/src/PedroTroller/CS/Fixer/RuleSetFactory.php index 5631a1f..d3eaf29 100644 --- a/src/PedroTroller/CS/Fixer/RuleSetFactory.php +++ b/src/PedroTroller/CS/Fixer/RuleSetFactory.php @@ -4,44 +4,54 @@ namespace PedroTroller\CS\Fixer; +use IteratorAggregate; use PhpCsFixer\RuleSet\RuleSets; +use Traversable; -final class RuleSetFactory +/** + * @implements IteratorAggregate> + */ +final class RuleSetFactory implements IteratorAggregate { /** - * @var array[] + * @var array|bool> */ - private $rules; + private array $rules; + /** + * @param array|bool> $rules + */ public function __construct(array $rules = []) { $this->rules = $rules; } /** - * @return array + * @return array|bool> */ - public function getRules() + public function getRules(): array + { + return [...$this]; + } + + public function getIterator(): Traversable { $rules = $this->rules; ksort($rules); - return $rules; + yield from $rules; } /** - * @return RuleSetFactory + * @param array|bool> $rules */ - public static function create(array $rules = []) + public static function create(array $rules = []): self { return new self($rules); } - /** - * @return RuleSetFactory - */ - public function psr0() + public function psr0(): self { return self::create(array_merge( $this->rules, @@ -49,10 +59,7 @@ public function psr0() )); } - /** - * @return RuleSetFactory - */ - public function psr1() + public function psr1(): self { return self::create(array_merge( $this->rules, @@ -60,10 +67,7 @@ public function psr1() )); } - /** - * @return RuleSetFactory - */ - public function psr2() + public function psr2(): self { return self::create(array_merge( $this->rules, @@ -71,10 +75,7 @@ public function psr2() )); } - /** - * @return RuleSetFactory - */ - public function psr4() + public function psr4(): self { return self::create(array_merge( $this->rules, @@ -82,12 +83,7 @@ public function psr4() )); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function symfony($risky = false) + public function symfony(bool $risky = false): self { $rules = ['@Symfony' => true]; @@ -101,12 +97,7 @@ public function symfony($risky = false) )); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function phpCsFixer($risky = false) + public function phpCsFixer(bool $risky = false): self { $rules = ['@PhpCsFixer' => true]; @@ -120,10 +111,7 @@ public function phpCsFixer($risky = false) )); } - /** - * @return RuleSetFactory - */ - public function doctrineAnnotation() + public function doctrineAnnotation(): self { return self::create(array_merge( $this->rules, @@ -131,13 +119,7 @@ public function doctrineAnnotation() )); } - /** - * @param float|string $version - * @param bool $risky - * - * @return RuleSetFactory - */ - public function php($version, $risky = false) + public function php(float $version, bool $risky = false): self { $config = $this->migration('php', $version, $risky)->getRules(); @@ -158,28 +140,17 @@ public function php($version, $risky = false) )); } - /** - * @param float $version - * @param bool $risky - * - * @return RuleSetFactory - */ - public function phpUnit($version, $risky = false) + public function phpUnit(float $version, bool $risky = false): self { return $this->migration('phpunit', $version, $risky); } - /** - * @param bool $risky - * - * @return RuleSetFactory - */ - public function pedrotroller($risky = false) + public function pedrotroller(bool $risky = false): self { $rules = []; foreach (new Fixers() as $fixer) { - if ($fixer->isDeprecated()) { + if ($fixer instanceof AbstractFixer && $fixer->isDeprecated()) { continue; } @@ -195,11 +166,9 @@ public function pedrotroller($risky = false) } /** - * @param string $name - * - * @return RuleSetFactory + * @param array> $config */ - public function enable($name, array $config = null) + public function enable(string $name, array $config = null): self { return self::create(array_merge( $this->rules, @@ -207,12 +176,7 @@ public function enable($name, array $config = null) )); } - /** - * @param string $name - * - * @return RuleSetFactory - */ - public function disable($name) + public function disable(string $name): self { return self::create(array_merge( $this->rules, @@ -220,14 +184,7 @@ public function disable($name) )); } - /** - * @param string $package - * @param float $version - * @param bool $risky - * - * @return RuleSetFactory - */ - private function migration($package, $version, $risky) + private function migration(string $package, float $version, bool $risky): self { $rules = (new RuleSets())->getSetDefinitionNames(); $rules = array_combine($rules, $rules); diff --git a/src/PedroTroller/CS/Fixer/TokenSignatures.php b/src/PedroTroller/CS/Fixer/TokenSignatures.php deleted file mode 100644 index 06ad2b6..0000000 --- a/src/PedroTroller/CS/Fixer/TokenSignatures.php +++ /dev/null @@ -1,15 +0,0 @@ -analyzer = new PhpCsFixerTokensAnalyzer($tokens); } - public function __call($name, $arguments) + /** + * @param array $arguments + */ + public function __call(string $name, array $arguments) { return \call_user_func_array([$this->analyzer, $name], $arguments); } /** - * @param int $index - * - * @return array + * @return array */ - public function getMethodArguments($index) + public function getMethodArguments(int $index): array { $methodName = $this->tokens->getNextMeaningfulToken($index); $openParenthesis = $this->tokens->getNextMeaningfulToken($methodName); @@ -95,22 +93,12 @@ public function getMethodArguments($index) return $arguments; } - /** - * @param int $index - * - * @return int - */ - public function getNumberOfArguments($index) + public function getNumberOfArguments(int $index): int { return \count($this->getMethodArguments($index)); } - /** - * @param int $index - * - * @return null|int - */ - public function getNextComma($index) + public function getNextComma(int $index): ?int { do { $index = $this->tokens->getNextMeaningfulToken($index); @@ -143,12 +131,7 @@ public function getNextComma($index) return $index; } - /** - * @param int $index - * - * @return null|int - */ - public function getNextSemiColon($index) + public function getNextSemiColon(int $index): ?int { do { $index = $this->tokens->getNextMeaningfulToken($index); @@ -179,11 +162,9 @@ public function getNextSemiColon($index) } /** - * @param int $index - * - * @return null|array|string + * @return null|string|array{string, null} */ - public function getReturnedType($index) + public function getReturnedType(int $index) { if (false === $this->tokens[$index]->isGivenKind(T_FUNCTION)) { throw new Exception(sprintf('Expected token: T_FUNCTION Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); @@ -199,7 +180,7 @@ public function getReturnedType($index) return null; } - if (false === $this->tokens[$next]->isGivenKind(TokenSignatures::TYPINT_DOUBLE_DOTS)) { + if (false === $this->tokens[$next]->isGivenKind(CT::T_TYPE_COLON)) { return null; } @@ -209,7 +190,7 @@ public function getReturnedType($index) return null; } - $optionnal = $this->tokens[$next]->isGivenKind(TokenSignatures::TYPINT_OPTIONAL); + $optionnal = $this->tokens[$next]->isGivenKind(CT::T_NULLABLE_TYPE); $next = $optionnal ? $this->tokens->getNextMeaningfulToken($next) @@ -226,34 +207,30 @@ public function getReturnedType($index) : $return; } } while (false === $this->tokens[$index]->equals(['{', ';'])); + + return null; } - /** - * @param int $index - * - * @return null|int - */ - public function getBeginningOfTheLine($index) + public function getBeginningOfTheLine(int $index): ?int { for ($i = $index; $i >= 0; --$i) { if (false !== mb_strpos($this->tokens[$i]->getContent(), "\n")) { return $i; } } + + return null; } - /** - * @param int $index - * - * @return null|int - */ - public function getEndOfTheLine($index) + public function getEndOfTheLine(int $index): ?int { for ($i = $index; $i < $this->tokens->count(); ++$i) { if (false !== mb_strpos($this->tokens[$i]->getContent(), "\n")) { return $i; } } + + return null; } /** @@ -310,12 +287,7 @@ public function endOfTheStatement(int $index): ?int return $index; } - /** - * @param int $index - * - * @return null|int - */ - public function getClosingParenthesis($index) + public function getClosingParenthesis(int $index): ?int { if (false === $this->tokens[$index]->equals('(')) { throw new Exception(sprintf('Expected token: (. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); @@ -336,14 +308,11 @@ public function getClosingParenthesis($index) return $i; } } + + return null; } - /** - * @param int $index - * - * @return null|int - */ - public function getClosingBracket($index) + public function getClosingBracket(int $index): ?int { if (false === $this->tokens[$index]->equals('[')) { throw new Exception(sprintf('Expected token: [. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); @@ -364,14 +333,11 @@ public function getClosingBracket($index) return $i; } } + + return null; } - /** - * @param int $index - * - * @return null|int - */ - public function getClosingCurlyBracket($index) + public function getClosingCurlyBracket(int $index): ?int { if (false === $this->tokens[$index]->equals('{')) { throw new Exception(sprintf('Expected token: {. Token %d id contains %s.', $index, $this->tokens[$index]->getContent())); @@ -392,6 +358,8 @@ public function getClosingCurlyBracket($index) return $i; } } + + return null; } /** @@ -440,40 +408,49 @@ public function getLineIndentation($index) } /** - * @param null|mixed $start - * @param null|mixed $end + * @param array|string>|string|Token> $sequences * - * @return array + * @return array> */ - public function findAllSequences(array $seqs, $start = null, $end = null) + public function findAllSequences(array $sequences, int $start = null, int $end = null): array { - $sequences = []; + $result = []; - foreach ($seqs as $seq) { + foreach ($sequences as $sequence) { $index = $start ?: 0; do { - $extract = $this->tokens->findSequence($seq, (int) $index, $end); + $extract = $this->tokens->findSequence($sequence, (int) $index, $end); if (null !== $extract) { - $keys = array_keys($extract); - $index = end($keys) + 1; - $sequences[reset($keys)] = $extract; + $keys = array_keys($extract); + $index = end($keys) + 1; + $result[reset($keys)] = $extract; } } while (null !== $extract); } - ksort($sequences); + ksort($result); - return $sequences; + return $result; } /** * @param int $startIndex * - * @return array[] + * @return array< + * array{ + * start: int, + * end: int, + * visibility: string, + * static: bool, + * type: string, + * methodName?: string, + * propertyName?: string + * } + * > */ - public function getElements($startIndex = null) + public function getElements(int $startIndex = null): array { static $elementTokenKinds = [CT::T_USE_TRAIT, T_CONST, T_VARIABLE, T_FUNCTION]; @@ -547,11 +524,9 @@ public function getElements($startIndex = null) } /** - * @param int $index - * - * @return array|string type or array of type and name + * @return array{string, string}|string type or array of type and name */ - private function detectElementType(Tokens $tokens, $index) + private function detectElementType(Tokens $tokens, int $index) { $token = $tokens[$index]; diff --git a/tests/Runner.php b/tests/Runner.php index 24c9a85..59eec3c 100644 --- a/tests/Runner.php +++ b/tests/Runner.php @@ -18,11 +18,13 @@ public static function run(): void $deprecations = []; set_error_handler( - function ($type, $message, $file, $line) use (&$deprecations): void { + function ($type, $message, $file, $line) use (&$deprecations): bool { $deprecations[$message][] = sprintf('%s at line %d', $file, $line); $deprecations[$message] = array_unique($deprecations[$message]); sort($deprecations[$message]); + + return true; }, E_USER_DEPRECATED ); diff --git a/tests/TokensAnalyzerIntegration.php b/tests/TokensAnalyzerIntegration.php index 0423e15..c7a965c 100644 --- a/tests/TokensAnalyzerIntegration.php +++ b/tests/TokensAnalyzerIntegration.php @@ -10,39 +10,26 @@ abstract class TokensAnalyzerIntegration { - /** - * @return string - */ - abstract public function getCode(); + abstract public function getCode(): string; - abstract public function assertions(TokensAnalyzer $analyzer, Tokens $tokens); + abstract public function assertions(TokensAnalyzer $analyzer, Tokens $tokens): void; - /** - * @return int - */ - public function getMinSupportedPhpVersion() + public function getMinSupportedPhpVersion(): int { return 0; } - /** - * @param string $content - * - * @return int - */ - protected function tokenContaining(Tokens $tokens, $content) + protected function tokenContaining(Tokens $tokens, string $content): int { $indexes = $this->tokensContaining($tokens, $content); - return current($indexes); + return (int) current($indexes); } /** - * @param string $content - * * @return int[] */ - protected function tokensContaining(Tokens $tokens, $content) + protected function tokensContaining(Tokens $tokens, string $content): array { $indexes = []; diff --git a/tests/TokensAnalyzerIntegration/InSwitch.php b/tests/TokensAnalyzerIntegration/InSwitch.php index a4a480f..4747833 100644 --- a/tests/TokensAnalyzerIntegration/InSwitch.php +++ b/tests/TokensAnalyzerIntegration/InSwitch.php @@ -11,10 +11,7 @@ final class InSwitch extends TokensAnalyzerIntegration { - /** - * {@inheritdoc} - */ - public function getCode() + public function getCode(): string { return <<<'PHP'