Skip to content

Commit a3b0eb2

Browse files
committed
new: ImportResolver trait to resolve use statements.
1 parent c5bbf65 commit a3b0eb2

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

Src/Traits/ImportResolver.php

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
declare( strict_types = 1 );
3+
4+
namespace TheWebSolver\Codegarage\Generator\Traits;
5+
6+
use Nette\PhpGenerator\Helpers;
7+
use Nette\PhpGenerator\PhpNamespace;
8+
9+
trait ImportResolver {
10+
private PhpNamespace $namespace;
11+
12+
public function setNamespace( PhpNamespace $namespace = null ): static {
13+
$this->namespace ??= $namespace ?? new PhpNamespace( '' );
14+
15+
return $this;
16+
}
17+
18+
public function getNamespace(): PhpNamespace {
19+
return $this->namespace;
20+
}
21+
22+
/**
23+
* @param string $item
24+
* @return string The alias of the $item that is being imported. Mostly the classname only without the
25+
* namespace part. If already has alias, alias is prefixed with last part of namespace.
26+
*/
27+
public function addUseStatementOf( string $item ): string {
28+
$classnameOnly = $alias = Helpers::extractShortName( $item );
29+
30+
if ( $this->hasAlreadyImported( $item ) ) {
31+
return $classnameOnly;
32+
}
33+
34+
$lastPartOfNamespace = $this->hasAlreadyAliasedImportedItemAs( $classnameOnly )
35+
? Helpers::extractShortName( Helpers::extractNamespace( $item ) )
36+
: '';
37+
38+
$this->getNamespace()->addUse( $item, $alias = $lastPartOfNamespace . $classnameOnly );
39+
40+
return $alias;
41+
}
42+
43+
private function hasAlreadyImported( string $item ): bool {
44+
return in_array( $item, haystack: $this->getNamespace()->getUses(), strict: true );
45+
}
46+
47+
private function hasAlreadyAliasedImportedItemAs( string $classnameOnly ): bool {
48+
return ! empty( $uses = $this->getNamespace()->getUses() ) && array_filter(
49+
array: $uses,
50+
callback: static fn( string $alias ): bool => $alias === $classnameOnly,
51+
mode: ARRAY_FILTER_USE_KEY
52+
);
53+
}
54+
}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
declare( strict_types = 1 );
3+
4+
namespace TheWebSolver\Codegarage\Integration;
5+
6+
use PHPUnit\Framework\TestCase;
7+
use Nette\PhpGenerator\PhpNamespace;
8+
use PHPUnit\Framework\Attributes\Test;
9+
use TheWebSolver\Codegarage\Generator\Traits\ImportResolver;
10+
11+
class ImportResolverTest extends TestCase {
12+
#[Test]
13+
public function itEnsuresSetterGetterWorks(): void {
14+
$import = new class() {
15+
use ImportResolver;
16+
};
17+
18+
$import->setNamespace( $namespace = new PhpNamespace( '' ) );
19+
20+
$this->assertSame( $namespace, $import->getNamespace() );
21+
}
22+
23+
#[Test]
24+
public function itEnsuresAliasesAreCreatedWhenImporting(): void {
25+
$import = new class() {
26+
use ImportResolver;
27+
};
28+
29+
$import->setNamespace( new PhpNamespace( '' ) );
30+
31+
$import->addUseStatementOf( ImportResolver::class );
32+
$import->addUseStatementOf( TestCase::class );
33+
34+
$this->assertCount( 2, $imports = $import->getNamespace()->getUses() );
35+
36+
foreach ( array( ImportResolver::class, TestCase::class ) as $item ) {
37+
$this->assertContains( $item, $imports );
38+
}
39+
40+
$import->addUseStatementOf( ImportResolver::class );
41+
42+
$this->assertCount( 2, $import->getNamespace()->getUses(), 'Must not add same import again.' );
43+
44+
$import->addUseStatementOf( 'DifferentNamespaced\\' . ImportResolver::class );
45+
46+
$this->assertCount( 3, $uses = $import->getNamespace()->getUses() );
47+
$this->assertContains( 'DifferentNamespaced\\' . ImportResolver::class, $uses );
48+
$this->assertArrayHasKey(
49+
'TraitsImportResolver',
50+
$uses,
51+
'Must alias if already imported same classname that exists in another namespace.'
52+
);
53+
}
54+
}

0 commit comments

Comments
 (0)