From 066a40289ff9fda5cc3253bab090931bfa8e7dd3 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Wed, 15 Apr 2026 22:34:42 +0200 Subject: [PATCH 1/3] Register @example tag handler out of the box The Example tag handler exists and is fully functional, but was never wired into the default tag handler map of StandardTagFactory. As a result, `@example` and `{@example ...}` were always parsed as a Generic tag, which broke downstream tooling (phpDocumentor rendered the tag as a literal string instead of resolving the referenced file). Fixes #412 --- src/DocBlock/StandardTagFactory.php | 2 ++ .../unit/DocBlock/StandardTagFactoryTest.php | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/DocBlock/StandardTagFactory.php b/src/DocBlock/StandardTagFactory.php index 1d9e5fe3..de531a49 100644 --- a/src/DocBlock/StandardTagFactory.php +++ b/src/DocBlock/StandardTagFactory.php @@ -17,6 +17,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Author; use phpDocumentor\Reflection\DocBlock\Tags\Covers; use phpDocumentor\Reflection\DocBlock\Tags\Deprecated; +use phpDocumentor\Reflection\DocBlock\Tags\Example; use phpDocumentor\Reflection\DocBlock\Tags\Factory\AbstractPHPStanFactory; use phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory; use phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory; @@ -89,6 +90,7 @@ final class StandardTagFactory implements TagFactory 'author' => Author::class, 'covers' => Covers::class, 'deprecated' => Deprecated::class, + 'example' => Example::class, 'link' => LinkTag::class, 'see' => SeeTag::class, 'since' => Since::class, diff --git a/tests/unit/DocBlock/StandardTagFactoryTest.php b/tests/unit/DocBlock/StandardTagFactoryTest.php index 114ea9e2..f3fee890 100644 --- a/tests/unit/DocBlock/StandardTagFactoryTest.php +++ b/tests/unit/DocBlock/StandardTagFactoryTest.php @@ -22,6 +22,7 @@ use phpDocumentor\Reflection\Assets\CustomTagFactory; use phpDocumentor\Reflection\DocBlock\Tags\Author; use phpDocumentor\Reflection\DocBlock\Tags\Deprecated; +use phpDocumentor\Reflection\DocBlock\Tags\Example; use phpDocumentor\Reflection\DocBlock\Tags\Extends_; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; @@ -135,6 +136,27 @@ public function testCreatingASpecificTag(): void $this->assertSame('author', $tag->getName()); } + /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Example + * + * @covers ::__construct + * @covers ::create + */ + public function testExampleTagIsRecognisedOutOfTheBox(): void + { + $context = new Context(''); + $tagFactory = StandardTagFactory::createInstance(m::mock(FqsenResolver::class)); + + $tag = $tagFactory->create('@example "path/to/example.php" 3 10 Example description.', $context); + + $this->assertInstanceOf(Example::class, $tag); + $this->assertSame('example', $tag->getName()); + $this->assertSame('path/to/example.php', $tag->getFilePath()); + $this->assertSame(3, $tag->getStartingLine()); + $this->assertSame(10, $tag->getLineCount()); + } + /** * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService * @uses \phpDocumentor\Reflection\DocBlock\Tags\See From 82288508d5fcbf190f8de1f7d1e5ebb08e197927 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Wed, 15 Apr 2026 22:36:59 +0200 Subject: [PATCH 2/3] Add inline {@example} test coverage --- .../unit/DocBlock/StandardTagFactoryTest.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/unit/DocBlock/StandardTagFactoryTest.php b/tests/unit/DocBlock/StandardTagFactoryTest.php index f3fee890..fb83980b 100644 --- a/tests/unit/DocBlock/StandardTagFactoryTest.php +++ b/tests/unit/DocBlock/StandardTagFactoryTest.php @@ -157,6 +157,32 @@ public function testExampleTagIsRecognisedOutOfTheBox(): void $this->assertSame(10, $tag->getLineCount()); } + /** + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Example + * + * @covers ::__construct + * @covers ::create + */ + public function testExampleTagIsRecognisedInInlineForm(): void + { + $context = new Context(''); + $tagFactory = StandardTagFactory::createInstance(m::mock(FqsenResolver::class)); + $tagFactory->addService(new DescriptionFactory($tagFactory), DescriptionFactory::class); + + $tag = $tagFactory->create('@link https://phpdoc.org {@example "path/to/example.php"}', $context); + + $description = $tag->getDescription(); + $this->assertNotNull($description); + $inlineTags = $description->getTags(); + $this->assertCount(1, $inlineTags); + $this->assertInstanceOf(Example::class, $inlineTags[0]); + $this->assertSame('path/to/example.php', $inlineTags[0]->getFilePath()); + } + /** * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService * @uses \phpDocumentor\Reflection\DocBlock\Tags\See From 1fe6b43fc924b259b19879add283386b2dabb950 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Wed, 15 Apr 2026 22:38:00 +0200 Subject: [PATCH 3/3] Remove redundant DescriptionFactory registration in inline test --- tests/unit/DocBlock/StandardTagFactoryTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/DocBlock/StandardTagFactoryTest.php b/tests/unit/DocBlock/StandardTagFactoryTest.php index fb83980b..10f7552b 100644 --- a/tests/unit/DocBlock/StandardTagFactoryTest.php +++ b/tests/unit/DocBlock/StandardTagFactoryTest.php @@ -171,7 +171,6 @@ public function testExampleTagIsRecognisedInInlineForm(): void { $context = new Context(''); $tagFactory = StandardTagFactory::createInstance(m::mock(FqsenResolver::class)); - $tagFactory->addService(new DescriptionFactory($tagFactory), DescriptionFactory::class); $tag = $tagFactory->create('@link https://phpdoc.org {@example "path/to/example.php"}', $context);