From b27a05bd11d84b805a91e047232764313336a620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=A4u=C3=9Fler?= Date: Thu, 16 Mar 2023 12:12:24 +0100 Subject: [PATCH 1/2] Revert "Fix: Match short namespace symbols" This reverts commit 7d95ce3283e922c1ca39110197401e5812c1a13c. --- src/Symbol/NamespaceSymbol.php | 6 ++---- tests/Unit/Symbol/NamespaceSymbolTest.php | 11 ----------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/Symbol/NamespaceSymbol.php b/src/Symbol/NamespaceSymbol.php index a438504..6b3b27f 100644 --- a/src/Symbol/NamespaceSymbol.php +++ b/src/Symbol/NamespaceSymbol.php @@ -4,8 +4,6 @@ namespace ComposerUnused\SymbolParser\Symbol; -use function rtrim; - final class NamespaceSymbol implements SymbolInterface { /** @var string */ @@ -13,7 +11,7 @@ final class NamespaceSymbol implements SymbolInterface public function __construct(string $namespace) { - $this->namespace = rtrim($namespace, '\\') . '\\'; + $this->namespace = $namespace; } public static function fromClass(string $class): self @@ -28,6 +26,6 @@ public function getIdentifier(): string public function matches(SymbolInterface $symbol): bool { - return strpos(rtrim($symbol->getIdentifier(), '\\') . '\\', $this->namespace) === 0; + return strpos($symbol->getIdentifier(), $this->namespace) === 0; } } diff --git a/tests/Unit/Symbol/NamespaceSymbolTest.php b/tests/Unit/Symbol/NamespaceSymbolTest.php index 57ac073..eed3c44 100644 --- a/tests/Unit/Symbol/NamespaceSymbolTest.php +++ b/tests/Unit/Symbol/NamespaceSymbolTest.php @@ -32,15 +32,4 @@ public function itShouldMatchNameSpaceFromClass(): void self::assertTrue($namespaceSymbol->matches($namespaceSymbolFromClass)); } - - /** - * @test - */ - public function itShouldMatchShortNamespaces(): void - { - $namespaceSymbol = new NamespaceSymbol('Foo\\Baz\\'); - $symbol = new Symbol('Foo\\Baz'); - - self::assertTrue($namespaceSymbol->matches($symbol)); - } } From 3f771d4591ffb8d3f054bcad445db971ff20e4c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=A4u=C3=9Fler?= Date: Thu, 16 Mar 2023 12:21:38 +0100 Subject: [PATCH 2/2] Handle name resolving with PHP-Parser's NameResolver Name resolving of namespaced symbols (such as classes, functions and constants) is now done through PHP-Parser's NameResolver. By using it as an additional node visitor, we add a safe additional layer on top of the collection strategies provided by the symbol-parser package. This also makes the fix introduced with 13fd5e9 obsolete now, as the NameResolver is more accurate. --- src/Parser/PHP/SymbolNameParser.php | 4 +++- tests/Integration/AbstractIntegrationTestCase.php | 3 +++ tests/Integration/Parser/PHP/SymbolNameParserTest.php | 7 +++++++ tests/ParserTestCase.php | 3 +++ .../Parser/PHP/Strategy/TypedAttributeStrategyTest.php | 5 +++-- tests/Unit/Parser/PHP/SymbolNameParserTest.php | 7 ++++--- 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Parser/PHP/SymbolNameParser.php b/src/Parser/PHP/SymbolNameParser.php index 12f8b22..ad77bf5 100644 --- a/src/Parser/PHP/SymbolNameParser.php +++ b/src/Parser/PHP/SymbolNameParser.php @@ -10,6 +10,7 @@ use Generator; use PhpParser\Error; use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; use PhpParser\Parser; use SplFileInfo; @@ -21,10 +22,11 @@ final class SymbolNameParser implements SymbolNameParserInterface private ?FileIterationInterface $fileIterator = null; private ?SplFileInfo $currentFile = null; - public function __construct(Parser $parser, SymbolCollectorInterface $visitor) + public function __construct(Parser $parser, NameResolver $nameResolver, SymbolCollectorInterface $visitor) { $this->parser = $parser; $this->traverser = new NodeTraverser(); + $this->traverser->addVisitor($nameResolver); $this->traverser->addVisitor($visitor); $this->visitor = $visitor; diff --git a/tests/Integration/AbstractIntegrationTestCase.php b/tests/Integration/AbstractIntegrationTestCase.php index e98fd6d..aa1026b 100644 --- a/tests/Integration/AbstractIntegrationTestCase.php +++ b/tests/Integration/AbstractIntegrationTestCase.php @@ -23,6 +23,7 @@ use ComposerUnused\SymbolParser\Test\Stubs\Config; use ComposerUnused\SymbolParser\Test\Stubs\TestLink; use ComposerUnused\SymbolParser\Test\Stubs\TestPackage; +use PhpParser\NodeVisitor\NameResolver; use PhpParser\ParserFactory; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; @@ -67,6 +68,7 @@ protected function loadDefinedFileSymbols( new FileSymbolProvider( new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ), new FileContentProvider() @@ -96,6 +98,7 @@ protected function loadConsumedFileSymbols(string $baseDir, array $autoloadTypes new FileSymbolProvider( new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new ConsumedSymbolCollector( [ new NewStrategy(), diff --git a/tests/Integration/Parser/PHP/SymbolNameParserTest.php b/tests/Integration/Parser/PHP/SymbolNameParserTest.php index 1be88e7..397e308 100644 --- a/tests/Integration/Parser/PHP/SymbolNameParserTest.php +++ b/tests/Integration/Parser/PHP/SymbolNameParserTest.php @@ -8,6 +8,7 @@ use ComposerUnused\SymbolParser\Parser\PHP\DefinedSymbolCollector; use ComposerUnused\SymbolParser\Parser\PHP\Strategy\ConstStrategy; use ComposerUnused\SymbolParser\Parser\PHP\SymbolNameParser; +use PhpParser\NodeVisitor\NameResolver; use PhpParser\ParserFactory; use PHPUnit\Framework\TestCase; @@ -22,6 +23,7 @@ public function itShouldParseClasses(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); @@ -49,6 +51,7 @@ public function itShouldParseInterfaces(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); @@ -76,6 +79,7 @@ public function itShouldParseFunctions(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); @@ -101,6 +105,7 @@ public function itShouldParseConstants(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); @@ -127,6 +132,7 @@ public function itShouldParseDefinedConstants(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); @@ -150,6 +156,7 @@ public function itShouldFindConsumedConstants(): void { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new ConsumedSymbolCollector([new ConstStrategy()]) ); diff --git a/tests/ParserTestCase.php b/tests/ParserTestCase.php index 6e5f2c8..3dbdb1d 100644 --- a/tests/ParserTestCase.php +++ b/tests/ParserTestCase.php @@ -8,6 +8,7 @@ use ComposerUnused\SymbolParser\Parser\PHP\DefinedSymbolCollector; use ComposerUnused\SymbolParser\Parser\PHP\Strategy\StrategyInterface; use ComposerUnused\SymbolParser\Parser\PHP\SymbolNameParser; +use PhpParser\NodeVisitor\NameResolver; use PhpParser\ParserFactory; use PHPUnit\Framework\TestCase; @@ -21,6 +22,7 @@ public function parseConsumedSymbols(array $strategies, string $code): array { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new ConsumedSymbolCollector($strategies) ); @@ -34,6 +36,7 @@ public function parseDefinedSymbols(string $code): array { $symbolNameParser = new SymbolNameParser( (new ParserFactory())->create(ParserFactory::ONLY_PHP7), + new NameResolver(), new DefinedSymbolCollector() ); diff --git a/tests/Unit/Parser/PHP/Strategy/TypedAttributeStrategyTest.php b/tests/Unit/Parser/PHP/Strategy/TypedAttributeStrategyTest.php index b89d6d9..5b9744f 100644 --- a/tests/Unit/Parser/PHP/Strategy/TypedAttributeStrategyTest.php +++ b/tests/Unit/Parser/PHP/Strategy/TypedAttributeStrategyTest.php @@ -37,7 +37,8 @@ class Foo { $symbols = $this->parseConsumedSymbols([$this->stragety], $code); - self::assertCount(1, $symbols); - self::assertSame('My\Namespace\Bar', $symbols[0]); + self::assertCount(2, $symbols); + self::assertSame('Other\Fubar', $symbols[0]); + self::assertSame('My\Namespace\Bar', $symbols[1]); } } diff --git a/tests/Unit/Parser/PHP/SymbolNameParserTest.php b/tests/Unit/Parser/PHP/SymbolNameParserTest.php index f2e0c5c..e810684 100644 --- a/tests/Unit/Parser/PHP/SymbolNameParserTest.php +++ b/tests/Unit/Parser/PHP/SymbolNameParserTest.php @@ -75,9 +75,10 @@ class Foo extends MyClass implements NameSpace1\Bar, \Other\Namespace2\Baz { $code ); - self::assertCount(3, $symbols); - self::assertSame('My\NameSpace1\Bar', $symbols[0]); + self::assertCount(4, $symbols); + self::assertSame('My\NameSpace1', $symbols[0]); self::assertSame('B\NS\MyClass', $symbols[1]); - self::assertSame('Other\Namespace2\Baz', $symbols[2]); + self::assertSame('My\NameSpace1\Bar', $symbols[2]); + self::assertSame('Other\Namespace2\Baz', $symbols[3]); } }