diff --git a/.github/workflows/docblock_check.yaml b/.github/workflows/docblock_check.yaml new file mode 100644 index 00000000000..ebefcf6b7e5 --- /dev/null +++ b/.github/workflows/docblock_check.yaml @@ -0,0 +1,65 @@ +name: Docblock Check + +on: + pull_request: null + +env: + COMPOSER_ROOT_VERSION: "dev-main" + DOCBLOCK_CHECK_LOG: "/tmp/docblock-check.log" + +jobs: + docblock_check: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v5 + + - + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + coverage: none + ini-values: zend.assertions=1 + + - uses: "ramsey/composer-install@v4" + + - + uses: actions/setup-go@v5 + with: + go-version: "1.26" + + - + name: Install honestype docblock checker + run: | + GOPROXY=direct GOSUMDB=off go install github.com/rectorphp/honestype@main + echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" + + - + name: Instrument sources + run: | + honestype instrument src + honestype instrument rules + + # Load the helper for every PHP process, including any parallel test + # workers which do not inherit a -d auto_prepend_file flag. + - + name: Enable runtime helper globally + run: | + INI="$(php -i | grep '^Loaded Configuration File' | awk '{print $NF}')" + echo "auto_prepend_file=$GITHUB_WORKSPACE/src/docblock_check.php" | sudo tee -a "$INI" + + - + name: Run tests to collect docblock type mismatches + run: vendor/bin/phpunit tests rules-tests utils/phpstan/tests || true + + - + name: Restore sources + if: always() + run: | + git checkout -- src rules + rm -f src/docblock_check.php rules/docblock_check.php + + - + name: List docblock type mismatches + run: honestype report "$DOCBLOCK_CHECK_LOG" diff --git a/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php b/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php index 9029e7b5b46..bfc2fa1e6a2 100644 --- a/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php +++ b/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php @@ -104,7 +104,7 @@ public function refactor(Node $node): ClassConstFetch|null } /** - * @param array $configuration + * @param string[] $configuration */ public function configure(array $configuration): void { diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php index 857b8fcfeaa..f315ff24203 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php +++ b/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.php @@ -35,7 +35,7 @@ public function __construct( /** * @param MethodCall[]|StaticCall[] $calls - * @return array + * @return array */ public function resolveStrictTypesFromCalls(array $calls): array { @@ -47,6 +47,11 @@ public function resolveStrictTypesFromCalls(array $calls): array return []; } + // must be int + if (! is_int($position)) { + continue; + } + /** @var Arg $arg */ $staticTypesByArgumentPosition[$position][] = $this->resolveStrictArgValueType($arg); } @@ -110,8 +115,8 @@ private function correctSelfType(Type $argValueType): Type } /** - * @param array $staticTypesByArgumentPosition - * @return array + * @param array $staticTypesByArgumentPosition + * @return array */ private function unionToSingleType(array $staticTypesByArgumentPosition, bool $removeMixedArray = false): array { diff --git a/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php b/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php index 104ac4f9695..91aeb065f16 100644 --- a/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php +++ b/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.php @@ -25,7 +25,7 @@ public function __construct( } /** - * @param array $classParameterTypes + * @param array $classParameterTypes */ public function complete(ClassMethod $classMethod, array $classParameterTypes, int $maxUnionTypes): ?ClassMethod { @@ -73,7 +73,7 @@ public function complete(ClassMethod $classMethod, array $classParameterTypes, i private function shouldSkipArgumentStaticType( ClassMethod $classMethod, Type $argumentStaticType, - int $position, + int|string $position, int $maxUnionTypes ): bool { if ($argumentStaticType instanceof MixedType) { diff --git a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php index f05f87dc7e8..bc4b6a8591f 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php +++ b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php @@ -461,6 +461,8 @@ private function nodeScopeResolverProcessNodes( MutatingScope $mutatingScope, callable $nodeCallback ): void { + Assert::allIsInstanceOf($stmts, Stmt::class); + try { $this->nodeScopeResolver->processNodes($stmts, $mutatingScope, $nodeCallback); } catch (ParserErrorsException|ParserException|ShouldNotHappenException|UndefinedVariableException) { @@ -629,7 +631,7 @@ private function processProperty(Property $property, MutatingScope $mutatingScop /** @var Stmt[] $stmts */ $stmts = $hook->body instanceof Expr ? [new Expression($hook->body)] - : [$hook->body]; + : $hook->body; $this->nodeScopeResolverProcessNodes($stmts, $mutatingScope, $nodeCallback); } } diff --git a/tests/Config/RectorConfigTest.php b/tests/Config/RectorConfigTest.php index 0f054548c7c..04123037f37 100644 --- a/tests/Config/RectorConfigTest.php +++ b/tests/Config/RectorConfigTest.php @@ -27,6 +27,11 @@ protected function setUp(): void // the registered-rule lists so the assertions hold whether this class // runs alone or batched into one warm process by a parallel runner RectorConfig::resetRecreated(); + + // the container is shared across tests, so its per-rule dedupe maps persist and would + // swallow a re-registration; reset them so REGISTERED_RECTOR_RULES fills regardless of order + self::getContainer()->resetRuleConfigurations(); + SimpleParameterProvider::setParameter(Option::REGISTERED_RECTOR_RULES, []); SimpleParameterProvider::setParameter(Option::ROOT_STANDALONE_REGISTERED_RULES, []); } diff --git a/tests/Configuration/ConfigurationFactoryTest.php b/tests/Configuration/ConfigurationFactoryTest.php index 0085c8c8ac2..adae31167c1 100644 --- a/tests/Configuration/ConfigurationFactoryTest.php +++ b/tests/Configuration/ConfigurationFactoryTest.php @@ -15,6 +15,13 @@ final class ConfigurationFactoryTest extends AbstractLazyTestCase { + protected function tearDown(): void + { + SimpleParameterProvider::setParameter(Option::IS_RUN_NARROWED, false); + SimpleParameterProvider::setParameter(Option::SOURCE, []); + SimpleParameterProvider::setParameter(Option::PATHS, []); + } + public function test(): void { $configurationFactory = $this->make(ConfigurationFactory::class);