diff --git a/src/DocBlock/Tags/Reference/Variable.php b/src/DocBlock/Tags/Reference/Variable.php new file mode 100644 index 00000000..0cbffd76 --- /dev/null +++ b/src/DocBlock/Tags/Reference/Variable.php @@ -0,0 +1,38 @@ +name = $name; + } + + public function __toString(): string + { + return $this->name; + } +} diff --git a/src/DocBlock/Tags/See.php b/src/DocBlock/Tags/See.php index f8242d47..edcbc160 100644 --- a/src/DocBlock/Tags/See.php +++ b/src/DocBlock/Tags/See.php @@ -18,6 +18,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url; +use phpDocumentor\Reflection\DocBlock\Tags\Reference\Variable; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; @@ -62,6 +63,11 @@ public static function create( return new static(new Url($parts[0]), $description); } + // Variables are not addressable through an FQSEN but are a valid target for {@}see, e.g. a global `$varname`. + if (preg_match('/^\$[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $parts[0])) { + return new static(new Variable($parts[0]), $description); + } + return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description); } diff --git a/tests/unit/DocBlock/Tags/SeeTest.php b/tests/unit/DocBlock/Tags/SeeTest.php index dcae48b0..6886f669 100644 --- a/tests/unit/DocBlock/Tags/SeeTest.php +++ b/tests/unit/DocBlock/Tags/SeeTest.php @@ -20,6 +20,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as TagsFqsen; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url as UrlRef; +use phpDocumentor\Reflection\DocBlock\Tags\Reference\Variable as VariableRef; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context; @@ -253,6 +254,37 @@ public function testFactoryMethodWithUrl(): void $this->assertSame($description, $fixture->getDescription()); } + /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\See:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\FqsenResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Variable + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create + */ + public function testFactoryMethodWithVariable(): void + { + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = m::mock(FqsenResolver::class); + $context = new Context(''); + + $description = new Description('My Description'); + + $descriptionFactory + ->shouldReceive('create')->with('My Description', $context)->andReturn($description); + + $resolver->shouldNotReceive('resolve'); + + $fixture = See::create('$varname My Description', $resolver, $descriptionFactory, $context); + + $this->assertSame('$varname My Description', (string) $fixture); + $this->assertInstanceOf(VariableRef::class, $fixture->getReference()); + $this->assertSame('$varname', (string) $fixture->getReference()); + $this->assertSame($description, $fixture->getDescription()); + } + /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\See:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory