From fafc9d14f851de1c7e88a2f5619180ff67a6c890 Mon Sep 17 00:00:00 2001 From: lll-lll-lll-lll Date: Sun, 12 Jul 2026 17:41:14 +0900 Subject: [PATCH] Skip require of files with top-level side effects, functions or constants in RemovePsr4AutoloadedIncludeRector --- .../Fixture/skip_class_with_function.php.inc | 7 ++++ .../skip_class_with_side_effect.php.inc | 7 ++++ .../Source/src/ClassWithFunction.php | 13 ++++++ .../Source/src/ClassWithInit.php | 14 +++++++ .../RemovePsr4AutoloadedIncludeRector.php | 40 +++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_function.php.inc create mode 100644 rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_side_effect.php.inc create mode 100644 rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Source/src/ClassWithFunction.php create mode 100644 rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Source/src/ClassWithInit.php diff --git a/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_function.php.inc b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_function.php.inc new file mode 100644 index 00000000000..736d78bdfee --- /dev/null +++ b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_function.php.inc @@ -0,0 +1,7 @@ + diff --git a/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_side_effect.php.inc b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_side_effect.php.inc new file mode 100644 index 00000000000..761a82e8b6d --- /dev/null +++ b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Fixture/skip_class_with_side_effect.php.inc @@ -0,0 +1,7 @@ + diff --git a/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Source/src/ClassWithFunction.php b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Source/src/ClassWithFunction.php new file mode 100644 index 00000000000..1737cb3b73d --- /dev/null +++ b/rules-tests/DeadCode/Rector/Expression/RemovePsr4AutoloadedIncludeRector/Source/src/ClassWithFunction.php @@ -0,0 +1,13 @@ +rectorParser->parseFile($filePath); + // the autoloader replays only type declarations, so top-level side effects, functions or constants keep the require load-bearing + if (! $this->containsOnlyTypeDeclarations($stmts)) { + return null; + } + $classLikes = $this->betterNodeFinder->findInstanceOf($stmts, ClassLike::class); // require must define exactly one class, or removing it would drop the other definitions @@ -175,6 +186,35 @@ private function resolveSingleDeclaredClassName(string $filePath): ?string return $this->getName($classLikes[0]); } + /** + * @param Stmt[] $stmts + */ + private function containsOnlyTypeDeclarations(array $stmts): bool + { + foreach ($stmts as $stmt) { + if ($stmt instanceof ClassLike || $stmt instanceof Use_ || $stmt instanceof GroupUse || $stmt instanceof Nop) { + continue; + } + + // declare(strict_types=1); is fine, but the block form declare(...) { ... } executes its body + if ($stmt instanceof Declare_ && $stmt->stmts === null) { + continue; + } + + if ($stmt instanceof Namespace_) { + if (! $this->containsOnlyTypeDeclarations($stmt->stmts)) { + return false; + } + + continue; + } + + return false; + } + + return true; + } + /** * @return array list of [namespace prefix, absolute directory] pairs */