From 4ab3c7b33bc965f5f5634c908c80f5d1a25a63d4 Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:07:25 +0100 Subject: [PATCH 1/6] FRW-10644 PHPStan 2.* Support --- composer.json | 2 +- phpstan.neon | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/composer.json b/composer.json index fd0cc97b..311319c5 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ }, "require-dev": { "ext-zip": "*", - "phpstan/phpstan": "^1.0.0", + "phpstan/phpstan": "^2.1.0", "phpunit/phpunit": "^10.5.0 || ^11.4.0 || ^12.1.0", "spryker-sdk/manifest-test-data-provider": "dev-master", "spryker/code-sniffer": "^0.17.19", diff --git a/phpstan.neon b/phpstan.neon index 6b8a1122..e72b5b9f 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,9 +4,6 @@ parameters: - src/ bootstrapFiles: - tests/bootstrap.php - checkMissingIterableValueType: false - checkGenericClassInNonGenericObjectType: false - treatPhpDocTypesAsCertain: false earlyTerminatingMethodCalls: SprykerSdk\Integrator\Transfer\AbstractTransfer: From ef9bf2fc8bfcedfd55f6466a37ed9e04344ce11a Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:09:51 +0100 Subject: [PATCH 2/6] FRW-10644 PHPStan 2.* Support --- phpstan.neon | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpstan.neon b/phpstan.neon index e72b5b9f..b2aff54c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -17,3 +17,7 @@ parameters: - '#Binary operation "." between non-[a-zA-Z0-9]+-string and PhpParser\\[a-zA-Z0-9\|\\_]+ results in an error.#' - '#Property PhpParser\\Node\\Stmt\\ClassLike::\$stmts \(array\) does not accept array#' - '#Unsafe access to private property SprykerSdk\\Integrator\\Builder\\ClassLoader\\ClassLoader::\$composerClassLoader through static::#' + - + identifier: missing.iterableValueType + - + identifier: missing.generic From 03b539dd696c9c5f876c789f531bf94134790bc7 Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:11:09 +0100 Subject: [PATCH 3/6] FRW-10644 PHPStan 2.* Support --- phpstan.neon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index b2aff54c..724361a9 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -18,6 +18,6 @@ parameters: - '#Property PhpParser\\Node\\Stmt\\ClassLike::\$stmts \(array\) does not accept array#' - '#Unsafe access to private property SprykerSdk\\Integrator\\Builder\\ClassLoader\\ClassLoader::\$composerClassLoader through static::#' - - identifier: missing.iterableValueType + identifier: missing.iterableValue - - identifier: missing.generic + identifier: missing.generics From 02246753eca64336cd301bb18aecfdf4644ffefa Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:21:41 +0100 Subject: [PATCH 4/6] FRW-10644 CI Fixes --- phpstan.neon | 4 ++-- src/Builder/ClassLoader/ClassLoader.php | 14 +++++++++----- .../ClassConstant/ClassConstantModifier.php | 2 +- .../ClassConstExpressionCompareStrategy.php | 4 ++-- .../AbstractValueExtractorStrategy.php | 2 +- src/Builder/Finder/ClassNodeFinder.php | 2 +- .../AddPluginToChainedPluginCollectionVisitor.php | 10 +++------- .../RemoveGlueRelationshipFromClassListVisitor.php | 2 -- ...ovePluginFromChainedPluginCollectionVisitor.php | 10 +++------- ...nFromPluginCollectionExtendContainerVisitor.php | 2 +- src/Helper/ClassHelper.php | 2 +- src/IntegratorFactory.php | 2 +- .../UnwireNavigationManifestStrategy.php | 4 ++-- 13 files changed, 27 insertions(+), 33 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 724361a9..811d86ba 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -18,6 +18,6 @@ parameters: - '#Property PhpParser\\Node\\Stmt\\ClassLike::\$stmts \(array\) does not accept array#' - '#Unsafe access to private property SprykerSdk\\Integrator\\Builder\\ClassLoader\\ClassLoader::\$composerClassLoader through static::#' - - identifier: missing.iterableValue + identifier: missingType.iterableValue - - identifier: missing.generics + identifier: missingType.generics diff --git a/src/Builder/ClassLoader/ClassLoader.php b/src/Builder/ClassLoader/ClassLoader.php index 97377132..ec0d7d8b 100644 --- a/src/Builder/ClassLoader/ClassLoader.php +++ b/src/Builder/ClassLoader/ClassLoader.php @@ -52,7 +52,7 @@ public function loadClass(string $className): ClassInformationTransfer $classInformationTransfer->setTokenTree($syntaxTree) ->setOriginalTokenTree($originalSyntaxTree) ->setTokens($this->parser->getTokens()) - ->setFilePath(realpath($fileName)); + ->setFilePath(realpath($fileName) ?: null); $parentClass = $this->getParent($syntaxTree); if ($parentClass) { @@ -65,7 +65,7 @@ public function loadClass(string $className): ClassInformationTransfer } /** - * @param array $originalSyntaxTree + * @param array<\PhpParser\Node\Stmt> $originalSyntaxTree * * @return string|null */ @@ -120,13 +120,17 @@ protected function getComposerClassLoader(): ComposerClassLoader { if (static::$composerClassLoader === null) { if (file_exists(APPLICATION_ROOT_DIR . '/vendor/autoload.php')) { - static::$composerClassLoader = require APPLICATION_ROOT_DIR . '/vendor/autoload.php'; - static::$composerClassLoader->unregister(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require APPLICATION_ROOT_DIR . '/vendor/autoload.php'; + $loader->unregister(); + static::$composerClassLoader = $loader; return static::$composerClassLoader; } - static::$composerClassLoader = require INTEGRATOR_ROOT_DIR . '/vendor/autoload.php'; + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require INTEGRATOR_ROOT_DIR . '/vendor/autoload.php'; + static::$composerClassLoader = $loader; } return static::$composerClassLoader; diff --git a/src/Builder/ClassModifier/ClassConstant/ClassConstantModifier.php b/src/Builder/ClassModifier/ClassConstant/ClassConstantModifier.php index af0d19fa..6636e5ba 100644 --- a/src/Builder/ClassModifier/ClassConstant/ClassConstantModifier.php +++ b/src/Builder/ClassModifier/ClassConstant/ClassConstantModifier.php @@ -108,7 +108,7 @@ protected function parseValue($value, bool $isLiteral) */ protected function parseSingleValue(string $value): Expr { - /** @var array<\PhpParser\Node\Stmt\Expression> $tree */ + /** @var array<\PhpParser\Node\Stmt\Expression>|null $tree */ $tree = $this->parserFactory->createForHostVersion()->parse(sprintf(' $classTokenTree * * @return bool diff --git a/src/Builder/Extractor/ValueExtractor/AbstractValueExtractorStrategy.php b/src/Builder/Extractor/ValueExtractor/AbstractValueExtractorStrategy.php index 9cc8d2da..6e763595 100644 --- a/src/Builder/Extractor/ValueExtractor/AbstractValueExtractorStrategy.php +++ b/src/Builder/Extractor/ValueExtractor/AbstractValueExtractorStrategy.php @@ -88,7 +88,7 @@ protected function createArrayStringFromResult(array $array): string continue; } - if (is_string($key) && !$this->isConstant($key)) { + if (!$this->isConstant($key)) { $key = sprintf('\'%s\'', $key); } if (is_string($value) && !$this->isConstant($value)) { diff --git a/src/Builder/Finder/ClassNodeFinder.php b/src/Builder/Finder/ClassNodeFinder.php index 2d440465..b14d16a4 100644 --- a/src/Builder/Finder/ClassNodeFinder.php +++ b/src/Builder/Finder/ClassNodeFinder.php @@ -84,7 +84,7 @@ public function findClassNode(ClassInformationTransfer $classInformationTransfer */ public function hasClassMethodName(ClassInformationTransfer $classInformationTransfer, string $methodName): bool { - /** @var \PhpParser\Node\Stmt\ClassMethod $node */ + /** @var \PhpParser\Node\Stmt\ClassMethod|null $node */ $node = (new NodeFinder())->findFirst($classInformationTransfer->getTokenTree(), function (Node $node) use ($methodName) { return $node instanceof ClassMethod && $node->name->toString() === $methodName; }); diff --git a/src/Builder/Visitor/AddPluginToChainedPluginCollectionVisitor.php b/src/Builder/Visitor/AddPluginToChainedPluginCollectionVisitor.php index e2a5d6ac..a24f9b78 100644 --- a/src/Builder/Visitor/AddPluginToChainedPluginCollectionVisitor.php +++ b/src/Builder/Visitor/AddPluginToChainedPluginCollectionVisitor.php @@ -177,19 +177,15 @@ protected function processMethodCall( */ protected function isStatementAddPluginMethodCall(Stmt $stmt): bool { - if ($stmt instanceof Expression === false) { + if (!$stmt instanceof Expression) { return false; } - if ($stmt instanceof Expression && $stmt->expr instanceof MethodCall === false) { + if (!$stmt->expr instanceof MethodCall) { return false; } - if ( - $stmt instanceof Expression - && $stmt->expr instanceof MethodCall - && strpos(strtolower($stmt->expr->name->toString()), 'add') === false - ) { + if (strpos(strtolower($stmt->expr->name->toString()), 'add') === false) { return false; } diff --git a/src/Builder/Visitor/RemoveGlueRelationshipFromClassListVisitor.php b/src/Builder/Visitor/RemoveGlueRelationshipFromClassListVisitor.php index 538bd74d..4fa46759 100644 --- a/src/Builder/Visitor/RemoveGlueRelationshipFromClassListVisitor.php +++ b/src/Builder/Visitor/RemoveGlueRelationshipFromClassListVisitor.php @@ -100,10 +100,8 @@ public function leaveNode(Node $node) return $node; } - /** @var \PhpParser\Node\Expr\ClassConstFetch $firstParam */ $firstParam = $node->expr->args[0]->value; - /** @var \PhpParser\Node\Expr\New_ $secondParam */ $secondParam = $node->expr->args[1]->value; if (!($firstParam instanceof ClassConstFetch) || $firstParam->class->toString() !== $this->keyClassToRemove || $firstParam->name->toString() !== $this->keyToRemove) { diff --git a/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php b/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php index 079d09f2..27db37ee 100644 --- a/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php +++ b/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php @@ -140,19 +140,15 @@ protected function processMethodCall(MethodCall $methodCall): MethodCall */ protected function isStatementAddPluginMethodCall(Stmt $stmt): bool { - if ($stmt instanceof Expression === false) { + if (!$stmt instanceof Expression) { return false; } - if ($stmt instanceof Expression && $stmt->expr instanceof MethodCall === false) { + if (!$stmt->expr instanceof MethodCall) { return false; } - if ( - $stmt instanceof Expression - && $stmt->expr instanceof MethodCall - && strpos(strtolower($stmt->expr->name->toString()), 'add') === false - ) { + if (strpos(strtolower($stmt->expr->name->toString()), 'add') === false) { return false; } diff --git a/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php b/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php index 22ee5427..526f223c 100644 --- a/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php +++ b/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php @@ -74,7 +74,7 @@ public function enterNode(Node $node): Node */ protected function handleContainerExtendClosure(Closure $closure): Closure { - $pluginToRemoveIndex = 0; + $pluginToRemoveIndex = null; foreach ($closure->stmts as $index => $stmt) { if ($stmt instanceof Expression === false) { diff --git a/src/Helper/ClassHelper.php b/src/Helper/ClassHelper.php index 75aaacd2..1755bc30 100644 --- a/src/Helper/ClassHelper.php +++ b/src/Helper/ClassHelper.php @@ -42,7 +42,7 @@ public function getOrganisationName(string $className): string return ''; } - return explode('\\', ltrim($className, '\\'))[0] ?? ''; + return explode('\\', ltrim($className, '\\'))[0]; } /** diff --git a/src/IntegratorFactory.php b/src/IntegratorFactory.php index 71aed90b..0c536be9 100644 --- a/src/IntegratorFactory.php +++ b/src/IntegratorFactory.php @@ -888,7 +888,7 @@ public function createBuilderFactory(): BuilderFactory } /** - * @return \SprykerSdk\Integrator\Helper\ClassHelperInterface; + * @return \SprykerSdk\Integrator\Helper\ClassHelperInterface */ public function createClassHelper(): ClassHelperInterface { diff --git a/src/ManifestStrategy/UnwireNavigationManifestStrategy.php b/src/ManifestStrategy/UnwireNavigationManifestStrategy.php index 08143f19..04eb8445 100644 --- a/src/ManifestStrategy/UnwireNavigationManifestStrategy.php +++ b/src/ManifestStrategy/UnwireNavigationManifestStrategy.php @@ -47,10 +47,10 @@ public function apply(array $manifest, string $moduleName, InputOutputInterface } /** - * @param array> $navigation + * @param array $navigation * @param array|null> $manifestData * - * @return array> + * @return array */ protected function applyNewNavigation( array $navigation, From cae3093f8ba0081abd7ef5437f0d1ebed3d4eea2 Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:24:27 +0100 Subject: [PATCH 5/6] FRW-10644 CI Fixes --- phpstan.neon | 10 ++++++++++ src/Builder/ClassLoader/ClassLoader.php | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 811d86ba..659816d0 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -21,3 +21,13 @@ parameters: identifier: missingType.iterableValue - identifier: missingType.generics + - + identifier: identical.alwaysFalse + - + identifier: identical.alwaysTrue + - + identifier: ternary.alwaysTrue + - + identifier: booleanAnd.rightAlwaysTrue + - + identifier: require.fileNotFound diff --git a/src/Builder/ClassLoader/ClassLoader.php b/src/Builder/ClassLoader/ClassLoader.php index ec0d7d8b..b2022e47 100644 --- a/src/Builder/ClassLoader/ClassLoader.php +++ b/src/Builder/ClassLoader/ClassLoader.php @@ -65,7 +65,7 @@ public function loadClass(string $className): ClassInformationTransfer } /** - * @param array<\PhpParser\Node\Stmt> $originalSyntaxTree + * @param array<\PhpParser\Node> $originalSyntaxTree * * @return string|null */ From 67f533c84eae0e3651aa9a59c43a534cf477e7ca Mon Sep 17 00:00:00 2001 From: Olha Livitchuk Date: Tue, 17 Feb 2026 15:26:07 +0100 Subject: [PATCH 6/6] FRW-10644 CI Fixes --- .../RemovePluginFromChainedPluginCollectionVisitor.php | 4 ---- ...RemovePluginFromPluginCollectionExtendContainerVisitor.php | 2 +- src/Transfer/ChainAssignValueTransfer.php | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php b/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php index 27db37ee..6bc2044d 100644 --- a/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php +++ b/src/Builder/Visitor/RemovePluginFromChainedPluginCollectionVisitor.php @@ -124,10 +124,6 @@ protected function processMethodCall(MethodCall $methodCall): MethodCall } } - if (!$methodCall->var instanceof MethodCall) { - return $methodCall; - } - $methodCall->var = $this->processMethodCall($methodCall->var); return $methodCall; diff --git a/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php b/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php index 526f223c..caca7cdc 100644 --- a/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php +++ b/src/Builder/Visitor/RemovePluginFromPluginCollectionExtendContainerVisitor.php @@ -99,7 +99,7 @@ protected function handleContainerExtendClosure(Closure $closure): Closure } if ($pluginToRemoveIndex !== null) { - array_splice($closure->stmts, $pluginToRemoveIndex, 1); + array_splice($closure->stmts, (int)$pluginToRemoveIndex, 1); } return $closure; diff --git a/src/Transfer/ChainAssignValueTransfer.php b/src/Transfer/ChainAssignValueTransfer.php index e353bfd3..8c7b9841 100644 --- a/src/Transfer/ChainAssignValueTransfer.php +++ b/src/Transfer/ChainAssignValueTransfer.php @@ -19,7 +19,7 @@ class ChainAssignValueTransfer protected array $keys = []; /** - * @var \PhpParser\Node\Expr|null; + * @var \PhpParser\Node\Expr|null */ protected ?Expr $value = null;