Skip to content

Commit 4f5b914

Browse files
committed
Add "@license" tag support
1 parent 6e19f62 commit 4f5b914

File tree

5 files changed

+110
-1
lines changed

5 files changed

+110
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ composer require type-lang/phpdoc
4949
- [ ] `@inheritdoc` - TODO
5050
- [x] `@inherits` - An alias of `@extends` tag
5151
- [ ] `@internal` - TODO
52-
- [ ] `@license` - TODO
52+
- [x] `@license` - Used to indicate which license is applicable
5353
- [x] `@link` - Indicates a custom relation between the associated _Symbol_
5454
and a website, which is identified by an absolute URI
5555
- [x] `@method` - Allows a class to know which "_magic_" methods are callable

composer.json

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
]
2727
},
2828
"require-dev": {
29+
"composer/spdx-licenses": "^1.5",
2930
"friendsofphp/php-cs-fixer": "^3.70",
3031
"jetbrains/phpstorm-attributes": "^1.0",
3132
"phpstan/phpstan": "^2.1",
@@ -39,6 +40,9 @@
3940
"TypeLang\\PHPDoc\\Tests\\": "tests"
4041
}
4142
},
43+
"suggest": {
44+
"composer/spdx-licenses": "Provides additional licenses (@license tag) support"
45+
},
4246
"extra": {
4347
"branch-alias": {
4448
"dev-master": "2.x-dev",
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PHPDoc\DocBlock\Tag\LicenseTag;
6+
7+
use TypeLang\PHPDoc\DocBlock\Tag\Shared\Reference\UriReference;
8+
use TypeLang\PHPDoc\DocBlock\Tag\Tag;
9+
10+
/**
11+
* Used to indicate which license is applicable for the associated _Symbol_.
12+
*
13+
* The `"@license"` tag provides the user with the name and URL of the license
14+
* that is applicable to a _Symbol_ and any of its child elements.
15+
*
16+
* Whenever multiple licenses apply, there MUST be one "`@license"` tag per
17+
* applicable license.
18+
*
19+
* ```
20+
* "@license" [<url>] [name]
21+
* ```
22+
*/
23+
final class LicenseTag extends Tag
24+
{
25+
public function __construct(
26+
string $name,
27+
public readonly ?UriReference $uri = null,
28+
/**
29+
* @var non-empty-string|null
30+
*/
31+
public readonly ?string $license = null,
32+
\Stringable|string|null $description = null,
33+
) {
34+
parent::__construct($name, $description);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PHPDoc\DocBlock\Tag\LicenseTag;
6+
7+
use Composer\Spdx\SpdxLicenses;
8+
use League\Uri\Uri;
9+
use TypeLang\PHPDoc\DocBlock\Tag\Factory\TagFactoryInterface;
10+
use TypeLang\PHPDoc\DocBlock\Tag\Shared\Reference\UriReference;
11+
use TypeLang\PHPDoc\Parser\Content\Stream;
12+
use TypeLang\PHPDoc\Parser\Content\UriReferenceReader;
13+
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
14+
15+
/**
16+
* This class is responsible for creating "`@license`" tags.
17+
*
18+
* See {@see LicenseTag} for details about this tag.
19+
*/
20+
final class LicenseTagFactory implements TagFactoryInterface
21+
{
22+
private readonly ?SpdxLicenses $licenses;
23+
24+
public function __construct()
25+
{
26+
$this->licenses = $this->createSpdxLicenses();
27+
}
28+
29+
private function createSpdxLicenses(): ?SpdxLicenses
30+
{
31+
if (\class_exists(SpdxLicenses::class)) {
32+
return new SpdxLicenses();
33+
}
34+
35+
return null;
36+
}
37+
38+
public function create(string $tag, string $content, DescriptionParserInterface $descriptions): LicenseTag
39+
{
40+
$stream = new Stream($tag, $content);
41+
42+
try {
43+
$uri = $stream->apply(new UriReferenceReader());
44+
} catch (\Throwable) {
45+
$uri = null;
46+
}
47+
48+
$description = $identifier = ($suffix = \trim($stream->value)) === '' ? null : $suffix;
49+
50+
if ($this->licenses !== null && $identifier !== null) {
51+
/** @var array{0:non-empty-string, 1:bool, 2:non-empty-string, 3:bool}|null $info */
52+
$info = $this->licenses->getLicenseByIdentifier($identifier);
53+
54+
if ($info !== null) {
55+
$uri ??= new UriReference(Uri::new($info[2]));
56+
$description = $info[0];
57+
}
58+
}
59+
60+
return new LicenseTag(
61+
name: $tag,
62+
uri: $uri,
63+
license: $identifier,
64+
description: $description,
65+
);
66+
}
67+
}

src/Platform/StandardPlatform.php

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use TypeLang\PHPDoc\DocBlock\Tag\FinalTag\FinalTagFactory;
1111
use TypeLang\PHPDoc\DocBlock\Tag\IgnoreTag\IgnoreTagFactory;
1212
use TypeLang\PHPDoc\DocBlock\Tag\InheritDocTag\InheritDocTagFactory;
13+
use TypeLang\PHPDoc\DocBlock\Tag\LicenseTag\LicenseTagFactory;
1314
use TypeLang\PHPDoc\DocBlock\Tag\LinkTag\LinkTagFactory;
1415
use TypeLang\PHPDoc\DocBlock\Tag\MethodTag\MethodTagFactory;
1516
use TypeLang\PHPDoc\DocBlock\Tag\NoNamedArgumentsTag\NoNamedArgumentsTagFactory;
@@ -42,6 +43,7 @@ protected function load(TypesParserInterface $types): iterable
4243
yield 'implements' => new TemplateImplementsTagFactory($types);
4344
yield 'inheritdoc' => new InheritDocTagFactory();
4445
yield 'ignore' => new IgnoreTagFactory();
46+
yield 'license' => new LicenseTagFactory();
4547
yield 'link' => new LinkTagFactory();
4648
yield 'method' => new MethodTagFactory($types);
4749
yield 'no-named-arguments' => new NoNamedArgumentsTagFactory();

0 commit comments

Comments
 (0)