Browse Source

chore: PHPStan 11 array rules (#8011)

Dariusz Rumiński 8 months ago
parent
commit
f0a95a7778

+ 6 - 0
phpstan.dist.neon

@@ -13,6 +13,8 @@ parameters:
         - tests/Fixtures
     polluteScopeWithLoopInitialAssignments: true # Do not enforce assignments outside of the loops
     reportUnmatchedIgnoredErrors: true # Do not allow outdated errors in the baseline
+    reportPossiblyNonexistentGeneralArrayOffset: true # enabled, but huge exceptions count; example fix: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/pull/8089
+    reportPossiblyNonexistentConstantArrayOffset: true
     treatPhpDocTypesAsCertain: false
     ignoreErrors:
         - '/^Class [a-zA-Z\\]+ extends @final class PhpCsFixer\\(ConfigurationException\\InvalidConfigurationException|ConfigurationException\\InvalidFixerConfigurationException|Tokenizer\\Tokens|Console\\Command\\FixCommand)\.$/'
@@ -52,5 +54,9 @@ parameters:
             message: '#^Method PhpCsFixer\\Tests\\.+::provide.+Cases\(\) return type has no value type specified in iterable type iterable\.$#'
             path: tests
             count: 1013
+        -
+            identifier: offsetAccess.notFound
+            path: .
+            count: 559
     tipsOfTheDay: false
     tmpDir: dev-tools/phpstan/cache

+ 4 - 0
src/Fixer/Alias/NoAliasFunctionsFixer.php

@@ -247,6 +247,10 @@ mbereg_search_getregs();
                 break;
             }
 
+            if (!isset(self::SETS[$set])) {
+                throw new \LogicException(sprintf('Set %s passed option validation, but not part of ::SETS.', $set));
+            }
+
             $this->aliases = array_merge($this->aliases, self::SETS[$set]);
         }
     }

+ 1 - 0
src/Fixer/Alias/SetTypeToCastFixer.php

@@ -149,6 +149,7 @@ settype($bar, "null");
             if ('null' === $type) {
                 $this->fixSettypeNullCall($tokens, $functionNameIndex, $argumentToken);
             } else {
+                \assert(isset($map[$type]));
                 $this->fixSettypeCall($tokens, $functionNameIndex, $argumentToken, new Token($map[$type]));
             }
         }

+ 4 - 0
src/Fixer/PhpUnit/PhpUnitExpectationFixer.php

@@ -230,6 +230,10 @@ final class MyTest extends \PHPUnit_Framework_TestCase
                 $argStart = array_keys($arguments)[$cnt];
                 $argBefore = $tokens->getPrevMeaningfulToken($argStart);
 
+                if (!isset($argumentsReplacements[$cnt])) {
+                    throw new \LogicException(sprintf('Unexpected index %d to find replacement method.', $cnt));
+                }
+
                 if ('expectExceptionMessage' === $argumentsReplacements[$cnt]) {
                     $paramIndicatorIndex = $tokens->getNextMeaningfulToken($argBefore);
                     $afterParamIndicatorIndex = $tokens->getNextMeaningfulToken($paramIndicatorIndex);

+ 5 - 0
src/Tokenizer/Analyzer/AlternativeSyntaxAnalyzer.php

@@ -74,6 +74,11 @@ final class AlternativeSyntaxAnalyzer
         }
 
         $startTokenKind = $tokens[$index]->getId();
+
+        if (!isset(self::ALTERNATIVE_SYNTAX_BLOCK_EDGES[$startTokenKind])) {
+            throw new \LogicException(sprintf('Unknown startTokenKind: %s', $tokens[$index]->toJson()));
+        }
+
         $endTokenKinds = self::ALTERNATIVE_SYNTAX_BLOCK_EDGES[$startTokenKind];
 
         $findKinds = [[$startTokenKind]];

+ 4 - 2
tests/Tokenizer/TokensAnalyzerTest.php

@@ -2491,10 +2491,12 @@ class TestClass {
                 continue;
             }
 
+            $isExpected = $expected[$index] ?? null;
+
             self::assertSame(
-                $expected[$index],
+                $isExpected,
                 $tokensAnalyzer->isWhilePartOfDoWhile($index),
-                sprintf('Expected token at index "%d" to be detected as %sa "do-while"-loop.', $index, true === $expected[$index] ? '' : 'not ')
+                sprintf('Expected token at index "%d" to be detected as %sa "do-while"-loop.', $index, true === $isExpected ? '' : 'not ')
             );
         }
     }