From 9f95af1eb48c11feeea8ade4fd7ae96104e336c6 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Sat, 18 Apr 2026 19:39:58 +0200 Subject: [PATCH] Reserve same-namespace short names during import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a class is imported with the same namespace as the current file, its short name is now recorded as a reserved alias rather than silently returned. Without the reservation, a later import from a different namespace with the same short name was also returned unaliased, so the generated file ended up with `use X\Y\Foo;` alongside a `class Foo` declaration — which PHP rejects as a redeclaration. `findAvailableAlias` already bumps colliding entries to `Foo2`, so recording the reservation is enough to make conflicting external imports flow through that path automatically. --- src/CodeGenerator.php | 10 ++++++++-- tests/CodeGeneratorTest.php | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/CodeGenerator.php b/src/CodeGenerator.php index b844277..465238d 100644 --- a/src/CodeGenerator.php +++ b/src/CodeGenerator.php @@ -214,8 +214,14 @@ public function import(Importable | string $name) : string // Check if the class is in the same namespace as the current namespace if ($this->namespace !== null && $fqcn->namespace !== null && $this->namespace->equals($fqcn->namespace)) { - // No import needed, just return the class name - return (string) $fqcn->className; + // No import needed, but reserve the short name so later imports from + // other namespaces are aliased instead of colliding with the local + // declaration (PHP would reject `use X\Y\Foo;` in a file that also + // declares `class Foo`). + $alias = (string) $fqcn->className; + $this->imports[$alias] ??= $fqcn; + + return $alias; } $alias = $this->findAvailableAlias($fqcn, $fqcn->className->name); diff --git a/tests/CodeGeneratorTest.php b/tests/CodeGeneratorTest.php index 03038de..4c94219 100644 --- a/tests/CodeGeneratorTest.php +++ b/tests/CodeGeneratorTest.php @@ -170,6 +170,31 @@ public function testImportClassWithConflict() : void ); } + public function testImportClassConflictsWithSameNamespaceDeclaration() : void + { + $this->generator = new CodeGenerator('App\\Models'); + + $local = $this->generator->import('App\\Models\\User'); + $external = $this->generator->import('App\\Domain\\User'); + + self::assertSame('User', $local); + self::assertSame('User2', $external); + + $this->assertDumpFile( + <<<'PHP' + generator->import(new FunctionName('array_map'));