Skip to content

Commit 9e847ae

Browse files
committed
Add tags and description interfaces
1 parent 2fc92eb commit 9e847ae

19 files changed

+193
-95
lines changed

src/DocBlock.php

+23-7
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,44 @@
55
namespace TypeLang\PHPDoc;
66

77
use TypeLang\PHPDoc\Tag\Description;
8-
use TypeLang\PHPDoc\Tag\Tag;
8+
use TypeLang\PHPDoc\Tag\DescriptionInterface;
9+
use TypeLang\PHPDoc\Tag\DescriptionProviderInterface;
10+
use TypeLang\PHPDoc\Tag\TagInterface;
911
use TypeLang\PHPDoc\Tag\TagProvider;
1012
use TypeLang\PHPDoc\Tag\TagProviderInterface;
1113

1214
/**
13-
* @template-implements \IteratorAggregate<int<0, max>, Tag>
14-
* @template-implements \ArrayAccess<int<0, max>, Tag|null>
15+
* This class represents structure containing a description and a set of tags
16+
* that describe an arbitrary DocBlock Comment in the code.
17+
*
18+
* @template-implements \IteratorAggregate<int<0, max>, TagInterface>
19+
* @template-implements \ArrayAccess<int<0, max>, TagInterface|null>
1520
*/
1621
final class DocBlock implements
22+
DescriptionProviderInterface,
1723
TagProviderInterface,
1824
\IteratorAggregate,
1925
\ArrayAccess
2026
{
2127
use TagProvider;
2228

29+
private readonly DescriptionInterface $description;
30+
2331
/**
24-
* @param iterable<array-key, Tag> $tags
32+
* @param iterable<array-key, TagInterface> $tags List of all tags contained in
33+
* a docblock object.
34+
*
35+
* Note that the constructor can receive an arbitrary iterator, like
36+
* {@see \Traversable} or {@see array}, but the object itself
37+
* contains the directly generated list ({@see array}} of
38+
* {@see TagInterface} objects.
2539
*/
2640
public function __construct(
27-
private readonly Description $description = new Description(),
41+
string|\Stringable $description = '',
2842
iterable $tags = [],
2943
) {
44+
$this->description = Description::fromStringable($description);
45+
3046
$this->bootTagProvider($tags);
3147
}
3248

@@ -35,7 +51,7 @@ public function offsetExists(mixed $offset): bool
3551
return isset($this->tags[$offset]);
3652
}
3753

38-
public function offsetGet(mixed $offset): ?Tag
54+
public function offsetGet(mixed $offset): ?TagInterface
3955
{
4056
return $this->tags[$offset] ?? null;
4157
}
@@ -50,7 +66,7 @@ public function offsetUnset(mixed $offset): void
5066
throw new \BadMethodCallException(self::class . ' objects are immutable');
5167
}
5268

53-
public function getDescription(): Description
69+
public function getDescription(): DescriptionInterface
5470
{
5571
return $this->description;
5672
}

src/Parser.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
use TypeLang\PHPDoc\Parser\SourceMap;
1616
use TypeLang\PHPDoc\Parser\Tag\TagParser;
1717
use TypeLang\PHPDoc\Parser\Tag\TagParserInterface;
18-
use TypeLang\PHPDoc\Tag\TagFactory;
19-
use TypeLang\PHPDoc\Tag\FactoryInterface;
18+
use TypeLang\PHPDoc\Tag\Factory\FactoryInterface;
19+
use TypeLang\PHPDoc\Tag\Factory\TagFactory;
2020

2121
/**
2222
* @psalm-suppress UndefinedAttributeClass : JetBrains language attribute may not be available

src/Parser/Description/DescriptionParserInterface.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace TypeLang\PHPDoc\Parser\Description;
66

7-
use TypeLang\PHPDoc\Tag\Description;
7+
use TypeLang\PHPDoc\Tag\DescriptionInterface;
88

99
interface DescriptionParserInterface
1010
{
@@ -25,5 +25,5 @@ interface DescriptionParserInterface
2525
* // }
2626
* ```
2727
*/
28-
public function parse(string $description): Description;
28+
public function parse(string $description): DescriptionInterface;
2929
}

src/Parser/Tag/TagParser.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
use TypeLang\PHPDoc\Exception\InvalidTagNameException;
88
use TypeLang\PHPDoc\Exception\RuntimeExceptionInterface;
99
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
10-
use TypeLang\PHPDoc\Tag\FactoryInterface;
10+
use TypeLang\PHPDoc\Tag\Factory\FactoryInterface;
1111
use TypeLang\PHPDoc\Tag\Tag;
12+
use TypeLang\PHPDoc\Tag\TagInterface;
1213

1314
final class TagParser implements TagParserInterface
1415
{
@@ -63,7 +64,7 @@ private function getTagName(string $content): string
6364
* @throws \Throwable
6465
* @throws RuntimeExceptionInterface
6566
*/
66-
public function parse(string $tag, DescriptionParserInterface $parser): Tag
67+
public function parse(string $tag, DescriptionParserInterface $parser): TagInterface
6768
{
6869
$name = $this->getTagName($tag);
6970
/** @var non-empty-string $name */

src/Parser/Tag/TagParserInterface.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace TypeLang\PHPDoc\Parser\Tag;
66

77
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
8-
use TypeLang\PHPDoc\Tag\Tag;
8+
use TypeLang\PHPDoc\Tag\TagInterface;
99

1010
interface TagParserInterface
1111
{
@@ -24,5 +24,5 @@ interface TagParserInterface
2424
* // }
2525
* ```
2626
*/
27-
public function parse(string $tag, DescriptionParserInterface $parser): Tag;
27+
public function parse(string $tag, DescriptionParserInterface $parser): TagInterface;
2828
}

src/Tag/Description.php

+8-20
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,16 @@
55
namespace TypeLang\PHPDoc\Tag;
66

77
/**
8-
* @template-implements \IteratorAggregate<int<0, max>, Tag>
8+
* @template-implements \IteratorAggregate<int<0, max>, TagInterface>
99
*/
10-
class Description implements
11-
TagProviderInterface,
12-
\IteratorAggregate,
13-
\Stringable
10+
class Description implements DescriptionInterface, \IteratorAggregate
1411
{
1512
use TagProvider;
1613

17-
private readonly string $template;
14+
protected readonly string $template;
1815

1916
/**
20-
* @param iterable<array-key, Tag> $tags
17+
* @param iterable<array-key, TagInterface> $tags
2118
*/
2219
public function __construct(
2320
string|\Stringable $template = '',
@@ -28,38 +25,29 @@ public function __construct(
2825
$this->bootTagProvider($tags);
2926
}
3027

31-
public static function fromString(string|\Stringable $description): self
28+
public static function fromStringable(string|\Stringable $description): DescriptionInterface
3229
{
33-
if ($description instanceof self) {
30+
if ($description instanceof DescriptionInterface) {
3431
return $description;
3532
}
3633

3734
return new self($description);
3835
}
3936

40-
public static function fromStringOrNull(string|\Stringable|null $description): ?self
37+
public static function fromStringableOrNull(string|\Stringable|null $description): ?DescriptionInterface
4138
{
4239
if ($description === null) {
4340
return null;
4441
}
4542

46-
return self::fromString($description);
43+
return self::fromStringable($description);
4744
}
4845

49-
/**
50-
* Returns the body template.
51-
*
52-
* @api
53-
* @psalm-immutable
54-
*/
5546
public function getTemplate(): string
5647
{
5748
return $this->template;
5849
}
5950

60-
/**
61-
* @psalm-immutable
62-
*/
6351
public function __toString(): string
6452
{
6553
$tags = [];

src/Tag/DescriptionInterface.php

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PHPDoc\Tag;
6+
7+
interface DescriptionInterface extends TagProviderInterface, \Stringable
8+
{
9+
/**
10+
* Returns the body template.
11+
*
12+
* @psalm-immutable Each call to the method must return the same value.
13+
*/
14+
public function getTemplate(): string;
15+
16+
/**
17+
* Returns a plain string representation of this description.
18+
*
19+
* Magic method {@link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring}
20+
* allows a class to decide how it will react when it is treated like
21+
* a string.
22+
*
23+
* @psalm-immutable Each call to the method must return the same value.
24+
*/
25+
public function __toString(): string;
26+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PHPDoc\Tag;
6+
7+
interface DescriptionProviderInterface
8+
{
9+
/**
10+
* Returns description object which can be represented as a string and
11+
* contains additional information.
12+
*
13+
* @psalm-immutable Each call to the method must return the same value.
14+
*/
15+
public function getDescription(): ?DescriptionInterface;
16+
}

src/Tag/FactoryInterface.php renamed to src/Tag/Factory/FactoryInterface.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\PHPDoc\Tag;
5+
namespace TypeLang\PHPDoc\Tag\Factory;
66

77
use TypeLang\PHPDoc\Exception\RuntimeExceptionInterface;
88
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
9+
use TypeLang\PHPDoc\Tag\TagInterface;
910

1011
interface FactoryInterface
1112
{
@@ -17,5 +18,5 @@ interface FactoryInterface
1718
* @throws RuntimeExceptionInterface In case of parsing error occurs.
1819
* @throws \Throwable In case of internal error occurs.
1920
*/
20-
public function create(string $name, string $content, DescriptionParserInterface $descriptions): Tag;
21+
public function create(string $name, string $content, DescriptionParserInterface $descriptions): TagInterface;
2122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\PHPDoc\Tag\Factory;
6+
7+
interface MutableFactoryInterface extends FactoryInterface
8+
{
9+
/**
10+
* Registers a handler for tags.
11+
*
12+
* If you want to use your own tags then you can use this method to
13+
* instruct the {@see FactoryInterface} to register the name of a tag with
14+
* the custom {@see FactoryInterface} to which processing of this tag will
15+
* be delegated.
16+
*
17+
* @param non-empty-string|list<non-empty-string> $tags
18+
*/
19+
public function register(string|array $tags, FactoryInterface $delegate): void;
20+
}

src/Tag/PrefixedTagFactory.php renamed to src/Tag/Factory/PrefixedTagFactory.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\PHPDoc\Tag;
5+
namespace TypeLang\PHPDoc\Tag\Factory;
66

77
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
8+
use TypeLang\PHPDoc\Tag\TagInterface;
89

910
final class PrefixedTagFactory implements MutableFactoryInterface
1011
{
@@ -25,7 +26,7 @@ public function register(array|string $tags, FactoryInterface $delegate): void
2526
}
2627
}
2728

28-
public function create(string $name, string $content, DescriptionParserInterface $descriptions): Tag
29+
public function create(string $name, string $content, DescriptionParserInterface $descriptions): TagInterface
2930
{
3031
return $this->delegate->create($name, $content, $descriptions);
3132
}

src/Tag/TagFactory.php renamed to src/Tag/Factory/TagFactory.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\PHPDoc\Tag;
5+
namespace TypeLang\PHPDoc\Tag\Factory;
66

77
use TypeLang\PHPDoc\Exception\InvalidTagException;
88
use TypeLang\PHPDoc\Exception\ParsingException;
99
use TypeLang\PHPDoc\Exception\RuntimeExceptionInterface;
1010
use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface;
11+
use TypeLang\PHPDoc\Tag\Tag;
12+
use TypeLang\PHPDoc\Tag\TagInterface;
1113

1214
final class TagFactory implements MutableFactoryInterface
1315
{
@@ -25,7 +27,7 @@ public function register(array|string $tags, FactoryInterface $delegate): void
2527
}
2628
}
2729

28-
public function create(string $name, string $content, DescriptionParserInterface $descriptions): Tag
30+
public function create(string $name, string $content, DescriptionParserInterface $descriptions): TagInterface
2931
{
3032
$delegate = $this->factories[$name] ?? null;
3133

src/Tag/MutableFactoryInterface.php

-13
This file was deleted.

src/Tag/Tag.php

+4-24
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace TypeLang\PHPDoc\Tag;
66

7-
class Tag implements \Stringable
7+
class Tag implements TagInterface
88
{
9-
protected readonly ?Description $description;
9+
protected readonly ?DescriptionInterface $description;
1010

1111
/**
1212
* @param non-empty-string $name
@@ -15,39 +15,19 @@ public function __construct(
1515
protected readonly string $name,
1616
\Stringable|string|null $description = null,
1717
) {
18-
$this->description = Description::fromStringOrNull($description);
18+
$this->description = Description::fromStringableOrNull($description);
1919
}
2020

21-
/**
22-
* @return non-empty-string
23-
*
24-
* @psalm-immutable
25-
*/
2621
public function getName(): string
2722
{
2823
return $this->name;
2924
}
3025

31-
/**
32-
* Returns description of the tag.
33-
*
34-
* @psalm-immutable
35-
*/
36-
public function getDescription(): ?Description
26+
public function getDescription(): ?DescriptionInterface
3727
{
3828
return $this->description;
3929
}
4030

41-
/**
42-
* Magic method {@link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring}
43-
* allows a class to decide how it will react when it is treated like
44-
* a string.
45-
*
46-
* @psalm-immutable
47-
* @return string Returns string representation of the object that
48-
* implements this interface (and/or {@see __toString()} magic
49-
* method).
50-
*/
5131
public function __toString(): string
5232
{
5333
if ($this->description === null) {

0 commit comments

Comments
 (0)