Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

require __DIR__ . '/../Source/src/ClassWithFunction.php';

$classWithFunction = new \App\ClassWithFunction();

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

require __DIR__ . '/../Source/src/ClassWithInit.php';

$classWithInit = new \App\ClassWithInit();

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace App;

final class ClassWithFunction
{
}

function some_helper(): void
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace App;

final class ClassWithInit
{
public static function init(): void
{
}
}

ClassWithInit::init();
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
use PhpParser\Node\Expr\Include_;
use PhpParser\Node\Scalar\MagicConst\Dir;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Declare_;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\Use_;
use PhpParser\NodeVisitor;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\FileSystem\JsonFileSystem;
Expand Down Expand Up @@ -164,6 +170,11 @@ private function resolveSingleDeclaredClassName(string $filePath): ?string
{
$stmts = $this->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
Expand All @@ -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<array{string, string}> list of [namespace prefix, absolute directory] pairs
*/
Expand Down
Loading