Repository: phpDocumentor/phpDocumentor (language: php)

Issue:
Fatal error while generting documentation
Hi, when generating my documentation, I get this fatal error:

```
CRITICAL  [console] Error thrown while running command "-d './repos/joomla-cms/libraries/src' -t './build/cms-/' --template './' --title 'Joomla! CMS 4.1.x API' --setting='graphs.enabled=true'". Message: "phpDocumentor\Descriptor\Tag\SinceDescriptor::setVersion(): Argument #1 ($version) must be of type string, null given, called in /opt/phpdoc/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php on line 37" ["exception" => TypeError { …},"command" => "-d './repos/joomla-cms/libraries/src' -t './build/cms-/' --template './' --title 'Joomla! CMS 4.1.x API' --setting='graphs.enabled=true'","message" => "phpDocumentor\Descriptor\Tag\SinceDescriptor::setVersion(): Argument #1 ($version) must be of type string, null given, called in /opt/phpdoc/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php on line 37"]
```

In another issue it was said that phpDocumentor would give better debug output, but I can't get it to work properly. Interestingly, we have a very old setup where this worked, but I can't get this to run on our new setup (and can't find out the old version of phpdocumentor) I tried both phpDocumentor 3.3.1, 3.0 and 2.9 and even on different PHP versions, but it always fails with the above error.


Discussion / hints:
I just checked the code and I _think_ that you have a malformed `@since` tag (or one missing the version). I can see in our code that that may result in a null value being passed into a string; for this I will create a PR to fix that in the upcoming release

Fix patch:
diff --git a/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php b/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php
index b9441e3a37..a3dbc36924 100644
--- a/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php
+++ b/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php
@@ -34,7 +34,7 @@ class SinceAssembler extends BaseTagAssembler
     public function buildDescriptor(object $data): SinceDescriptor
     {
         $descriptor = new SinceDescriptor($data->getName());
-        $descriptor->setVersion($data->getVersion());
+        $descriptor->setVersion($data->getVersion() ?? '');
 
         return $descriptor;
     }


Test patch:
diff --git a/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssemblerTest.php b/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssemblerTest.php
new file mode 100644
index 0000000000..5979ae9575
--- /dev/null
+++ b/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssemblerTest.php
@@ -0,0 +1,94 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link https://phpdoc.org
+ */
+
+namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;
+
+use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
+use phpDocumentor\Descriptor\Tag\SinceDescriptor;
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Tags\Since;
+use PHPUnit\Framework\TestCase;
+use Prophecy\PhpUnit\ProphecyTrait;
+use Prophecy\Prophecy\ObjectProphecy;
+
+/**
+ * Test class for phpDocumentor\Descriptor\Builder\Reflector\Tags\SinceAssembler
+ *
+ * @coversDefaultClass \phpDocumentor\Descriptor\Builder\Reflector\Tags\SinceAssembler
+ * @covers ::<private>
+ */
+final class SinceAssemblerTest extends TestCase
+{
+    use ProphecyTrait;
+
+    private SinceAssembler $fixture;
+
+    /** @var ProjectDescriptorBuilder|ObjectProphecy */
+    private ObjectProphecy $builderMock;
+
+    protected function setUp(): void
+    {
+        $this->builderMock = $this->prophesize(ProjectDescriptorBuilder::class);
+        $this->fixture = new SinceAssembler();
+        $this->fixture->setBuilder($this->builderMock->reveal());
+    }
+
+    /**
+     * @covers ::create
+     * @covers ::buildDescriptor
+     */
+    public function testCreateSinceDescriptorFromSinceTag(): void
+    {
+        $name = 'since';
+        $description = 'a since tag';
+        $version = '1.0.0';
+
+        $sinceTagMock = $this->givenASinceTag($version, $description);
+
+        /** @var SinceDescriptor $descriptor */
+        $descriptor = $this->fixture->create($sinceTagMock);
+
+        self::assertSame($name, $descriptor->getName());
+        self::assertSame($description, (string) $descriptor->getDescription());
+        self::assertSame($version, $descriptor->getVersion());
+        self::assertSame([], $descriptor->getErrors()->getAll());
+    }
+
+    /**
+     * @covers ::create
+     * @covers ::buildDescriptor
+     */
+    public function testCreateSinceDescriptorFromSinceTagWithEmptyVersion(): void
+    {
+        $name = 'since';
+        $description = 'a since tag';
+
+        $tag = $this->givenASinceTag(null, $description);
+
+        /** @var SinceDescriptor $descriptor */
+        $descriptor = $this->fixture->create($tag);
+
+        self::assertSame($name, $descriptor->getName());
+        self::assertSame($description, (string) $descriptor->getDescription());
+        self::assertSame('', $descriptor->getVersion());
+        self::assertSame([], $descriptor->getErrors()->getAll());
+    }
+
+    private function givenASinceTag(?string $version, string $description): Since
+    {
+        return new DocBlock\Tags\Since(
+            $version,
+            new DocBlock\Description($description)
+        );
+    }
+}