From 2fc92ebe12754075658e1afe370855e318aa36e8 Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 00:26:26 +0300 Subject: [PATCH 1/7] Switch constructor arguments of PrefixedTagFactory --- src/Tag/PrefixedTagFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tag/PrefixedTagFactory.php b/src/Tag/PrefixedTagFactory.php index 35c4e40..f7260cd 100644 --- a/src/Tag/PrefixedTagFactory.php +++ b/src/Tag/PrefixedTagFactory.php @@ -12,8 +12,8 @@ final class PrefixedTagFactory implements MutableFactoryInterface * @param non-empty-list $prefixes */ public function __construct( - private readonly MutableFactoryInterface $delegate, private readonly array $prefixes, + private readonly MutableFactoryInterface $delegate = new TagFactory(), ) {} public function register(array|string $tags, FactoryInterface $delegate): void From 9e847aeca8774db21d3385d6559cc0dee9a760dc Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 01:36:10 +0300 Subject: [PATCH 2/7] Add tags and description interfaces --- src/DocBlock.php | 30 ++++++++++++---- src/Parser.php | 4 +-- .../DescriptionParserInterface.php | 4 +-- src/Parser/Tag/TagParser.php | 5 +-- src/Parser/Tag/TagParserInterface.php | 4 +-- src/Tag/Description.php | 28 +++++---------- src/Tag/DescriptionInterface.php | 26 ++++++++++++++ src/Tag/DescriptionProviderInterface.php | 16 +++++++++ src/Tag/{ => Factory}/FactoryInterface.php | 5 +-- src/Tag/Factory/MutableFactoryInterface.php | 20 +++++++++++ src/Tag/{ => Factory}/PrefixedTagFactory.php | 5 +-- src/Tag/{ => Factory}/TagFactory.php | 6 ++-- src/Tag/MutableFactoryInterface.php | 13 ------- src/Tag/Tag.php | 28 +++------------ src/Tag/TagInterface.php | 34 +++++++++++++++++++ src/Tag/TagProvider.php | 12 +++---- src/Tag/TagProviderInterface.php | 12 ++++--- src/Tag/TypeProviderInterface.php | 23 +++++++++++++ src/Tag/TypedTag.php | 13 ++++--- 19 files changed, 193 insertions(+), 95 deletions(-) create mode 100644 src/Tag/DescriptionInterface.php create mode 100644 src/Tag/DescriptionProviderInterface.php rename src/Tag/{ => Factory}/FactoryInterface.php (80%) create mode 100644 src/Tag/Factory/MutableFactoryInterface.php rename src/Tag/{ => Factory}/PrefixedTagFactory.php (86%) rename src/Tag/{ => Factory}/TagFactory.php (91%) delete mode 100644 src/Tag/MutableFactoryInterface.php create mode 100644 src/Tag/TagInterface.php create mode 100644 src/Tag/TypeProviderInterface.php diff --git a/src/DocBlock.php b/src/DocBlock.php index 02ca692..3c05ad4 100644 --- a/src/DocBlock.php +++ b/src/DocBlock.php @@ -5,28 +5,44 @@ namespace TypeLang\PHPDoc; use TypeLang\PHPDoc\Tag\Description; -use TypeLang\PHPDoc\Tag\Tag; +use TypeLang\PHPDoc\Tag\DescriptionInterface; +use TypeLang\PHPDoc\Tag\DescriptionProviderInterface; +use TypeLang\PHPDoc\Tag\TagInterface; use TypeLang\PHPDoc\Tag\TagProvider; use TypeLang\PHPDoc\Tag\TagProviderInterface; /** - * @template-implements \IteratorAggregate, Tag> - * @template-implements \ArrayAccess, Tag|null> + * This class represents structure containing a description and a set of tags + * that describe an arbitrary DocBlock Comment in the code. + * + * @template-implements \IteratorAggregate, TagInterface> + * @template-implements \ArrayAccess, TagInterface|null> */ final class DocBlock implements + DescriptionProviderInterface, TagProviderInterface, \IteratorAggregate, \ArrayAccess { use TagProvider; + private readonly DescriptionInterface $description; + /** - * @param iterable $tags + * @param iterable $tags List of all tags contained in + * a docblock object. + * + * Note that the constructor can receive an arbitrary iterator, like + * {@see \Traversable} or {@see array}, but the object itself + * contains the directly generated list ({@see array}} of + * {@see TagInterface} objects. */ public function __construct( - private readonly Description $description = new Description(), + string|\Stringable $description = '', iterable $tags = [], ) { + $this->description = Description::fromStringable($description); + $this->bootTagProvider($tags); } @@ -35,7 +51,7 @@ public function offsetExists(mixed $offset): bool return isset($this->tags[$offset]); } - public function offsetGet(mixed $offset): ?Tag + public function offsetGet(mixed $offset): ?TagInterface { return $this->tags[$offset] ?? null; } @@ -50,7 +66,7 @@ public function offsetUnset(mixed $offset): void throw new \BadMethodCallException(self::class . ' objects are immutable'); } - public function getDescription(): Description + public function getDescription(): DescriptionInterface { return $this->description; } diff --git a/src/Parser.php b/src/Parser.php index e46d038..d4f4a57 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -15,8 +15,8 @@ use TypeLang\PHPDoc\Parser\SourceMap; use TypeLang\PHPDoc\Parser\Tag\TagParser; use TypeLang\PHPDoc\Parser\Tag\TagParserInterface; -use TypeLang\PHPDoc\Tag\TagFactory; -use TypeLang\PHPDoc\Tag\FactoryInterface; +use TypeLang\PHPDoc\Tag\Factory\FactoryInterface; +use TypeLang\PHPDoc\Tag\Factory\TagFactory; /** * @psalm-suppress UndefinedAttributeClass : JetBrains language attribute may not be available diff --git a/src/Parser/Description/DescriptionParserInterface.php b/src/Parser/Description/DescriptionParserInterface.php index 596d745..a123088 100644 --- a/src/Parser/Description/DescriptionParserInterface.php +++ b/src/Parser/Description/DescriptionParserInterface.php @@ -4,7 +4,7 @@ namespace TypeLang\PHPDoc\Parser\Description; -use TypeLang\PHPDoc\Tag\Description; +use TypeLang\PHPDoc\Tag\DescriptionInterface; interface DescriptionParserInterface { @@ -25,5 +25,5 @@ interface DescriptionParserInterface * // } * ``` */ - public function parse(string $description): Description; + public function parse(string $description): DescriptionInterface; } diff --git a/src/Parser/Tag/TagParser.php b/src/Parser/Tag/TagParser.php index 9d36d2b..e3822ad 100644 --- a/src/Parser/Tag/TagParser.php +++ b/src/Parser/Tag/TagParser.php @@ -7,8 +7,9 @@ use TypeLang\PHPDoc\Exception\InvalidTagNameException; use TypeLang\PHPDoc\Exception\RuntimeExceptionInterface; use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface; -use TypeLang\PHPDoc\Tag\FactoryInterface; +use TypeLang\PHPDoc\Tag\Factory\FactoryInterface; use TypeLang\PHPDoc\Tag\Tag; +use TypeLang\PHPDoc\Tag\TagInterface; final class TagParser implements TagParserInterface { @@ -63,7 +64,7 @@ private function getTagName(string $content): string * @throws \Throwable * @throws RuntimeExceptionInterface */ - public function parse(string $tag, DescriptionParserInterface $parser): Tag + public function parse(string $tag, DescriptionParserInterface $parser): TagInterface { $name = $this->getTagName($tag); /** @var non-empty-string $name */ diff --git a/src/Parser/Tag/TagParserInterface.php b/src/Parser/Tag/TagParserInterface.php index b54afb1..b8d6616 100644 --- a/src/Parser/Tag/TagParserInterface.php +++ b/src/Parser/Tag/TagParserInterface.php @@ -5,7 +5,7 @@ namespace TypeLang\PHPDoc\Parser\Tag; use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface; -use TypeLang\PHPDoc\Tag\Tag; +use TypeLang\PHPDoc\Tag\TagInterface; interface TagParserInterface { @@ -24,5 +24,5 @@ interface TagParserInterface * // } * ``` */ - public function parse(string $tag, DescriptionParserInterface $parser): Tag; + public function parse(string $tag, DescriptionParserInterface $parser): TagInterface; } diff --git a/src/Tag/Description.php b/src/Tag/Description.php index 7175d13..dc45abf 100644 --- a/src/Tag/Description.php +++ b/src/Tag/Description.php @@ -5,19 +5,16 @@ namespace TypeLang\PHPDoc\Tag; /** - * @template-implements \IteratorAggregate, Tag> + * @template-implements \IteratorAggregate, TagInterface> */ -class Description implements - TagProviderInterface, - \IteratorAggregate, - \Stringable +class Description implements DescriptionInterface, \IteratorAggregate { use TagProvider; - private readonly string $template; + protected readonly string $template; /** - * @param iterable $tags + * @param iterable $tags */ public function __construct( string|\Stringable $template = '', @@ -28,38 +25,29 @@ public function __construct( $this->bootTagProvider($tags); } - public static function fromString(string|\Stringable $description): self + public static function fromStringable(string|\Stringable $description): DescriptionInterface { - if ($description instanceof self) { + if ($description instanceof DescriptionInterface) { return $description; } return new self($description); } - public static function fromStringOrNull(string|\Stringable|null $description): ?self + public static function fromStringableOrNull(string|\Stringable|null $description): ?DescriptionInterface { if ($description === null) { return null; } - return self::fromString($description); + return self::fromStringable($description); } - /** - * Returns the body template. - * - * @api - * @psalm-immutable - */ public function getTemplate(): string { return $this->template; } - /** - * @psalm-immutable - */ public function __toString(): string { $tags = []; diff --git a/src/Tag/DescriptionInterface.php b/src/Tag/DescriptionInterface.php new file mode 100644 index 0000000..4c58c13 --- /dev/null +++ b/src/Tag/DescriptionInterface.php @@ -0,0 +1,26 @@ + $tags + */ + public function register(string|array $tags, FactoryInterface $delegate): void; +} diff --git a/src/Tag/PrefixedTagFactory.php b/src/Tag/Factory/PrefixedTagFactory.php similarity index 86% rename from src/Tag/PrefixedTagFactory.php rename to src/Tag/Factory/PrefixedTagFactory.php index f7260cd..28d3785 100644 --- a/src/Tag/PrefixedTagFactory.php +++ b/src/Tag/Factory/PrefixedTagFactory.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace TypeLang\PHPDoc\Tag; +namespace TypeLang\PHPDoc\Tag\Factory; use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface; +use TypeLang\PHPDoc\Tag\TagInterface; final class PrefixedTagFactory implements MutableFactoryInterface { @@ -25,7 +26,7 @@ public function register(array|string $tags, FactoryInterface $delegate): void } } - public function create(string $name, string $content, DescriptionParserInterface $descriptions): Tag + public function create(string $name, string $content, DescriptionParserInterface $descriptions): TagInterface { return $this->delegate->create($name, $content, $descriptions); } diff --git a/src/Tag/TagFactory.php b/src/Tag/Factory/TagFactory.php similarity index 91% rename from src/Tag/TagFactory.php rename to src/Tag/Factory/TagFactory.php index f1a8258..2aec485 100644 --- a/src/Tag/TagFactory.php +++ b/src/Tag/Factory/TagFactory.php @@ -2,12 +2,14 @@ declare(strict_types=1); -namespace TypeLang\PHPDoc\Tag; +namespace TypeLang\PHPDoc\Tag\Factory; use TypeLang\PHPDoc\Exception\InvalidTagException; use TypeLang\PHPDoc\Exception\ParsingException; use TypeLang\PHPDoc\Exception\RuntimeExceptionInterface; use TypeLang\PHPDoc\Parser\Description\DescriptionParserInterface; +use TypeLang\PHPDoc\Tag\Tag; +use TypeLang\PHPDoc\Tag\TagInterface; final class TagFactory implements MutableFactoryInterface { @@ -25,7 +27,7 @@ public function register(array|string $tags, FactoryInterface $delegate): void } } - public function create(string $name, string $content, DescriptionParserInterface $descriptions): Tag + public function create(string $name, string $content, DescriptionParserInterface $descriptions): TagInterface { $delegate = $this->factories[$name] ?? null; diff --git a/src/Tag/MutableFactoryInterface.php b/src/Tag/MutableFactoryInterface.php deleted file mode 100644 index 75aa9f9..0000000 --- a/src/Tag/MutableFactoryInterface.php +++ /dev/null @@ -1,13 +0,0 @@ - $tags - */ - public function register(string|array $tags, FactoryInterface $delegate): void; -} diff --git a/src/Tag/Tag.php b/src/Tag/Tag.php index 40fe8e7..4515f88 100644 --- a/src/Tag/Tag.php +++ b/src/Tag/Tag.php @@ -4,9 +4,9 @@ namespace TypeLang\PHPDoc\Tag; -class Tag implements \Stringable +class Tag implements TagInterface { - protected readonly ?Description $description; + protected readonly ?DescriptionInterface $description; /** * @param non-empty-string $name @@ -15,39 +15,19 @@ public function __construct( protected readonly string $name, \Stringable|string|null $description = null, ) { - $this->description = Description::fromStringOrNull($description); + $this->description = Description::fromStringableOrNull($description); } - /** - * @return non-empty-string - * - * @psalm-immutable - */ public function getName(): string { return $this->name; } - /** - * Returns description of the tag. - * - * @psalm-immutable - */ - public function getDescription(): ?Description + public function getDescription(): ?DescriptionInterface { return $this->description; } - /** - * Magic method {@link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring} - * allows a class to decide how it will react when it is treated like - * a string. - * - * @psalm-immutable - * @return string Returns string representation of the object that - * implements this interface (and/or {@see __toString()} magic - * method). - */ public function __toString(): string { if ($this->description === null) { diff --git a/src/Tag/TagInterface.php b/src/Tag/TagInterface.php new file mode 100644 index 0000000..ef6b435 --- /dev/null +++ b/src/Tag/TagInterface.php @@ -0,0 +1,34 @@ + + * @var list * @psalm-suppress PropertyNotSetInConstructor */ - private readonly array $tags; + protected readonly array $tags; /** - * @param iterable $tags + * @param iterable $tags * @psalm-suppress InaccessibleProperty */ protected function bootTagProvider(iterable $tags): void @@ -32,9 +32,7 @@ protected function bootTagProvider(iterable $tags): void } /** - * Returns the tags for this DocBlock. - * - * @return list + * {@see TagProviderInterface::getTags()} */ public function getTags(): array { @@ -42,7 +40,7 @@ public function getTags(): array } /** - * @return \Traversable, Tag> + * @return \Traversable, TagInterface> */ public function getIterator(): \Traversable { diff --git a/src/Tag/TagProviderInterface.php b/src/Tag/TagProviderInterface.php index 5b120b6..6000b07 100644 --- a/src/Tag/TagProviderInterface.php +++ b/src/Tag/TagProviderInterface.php @@ -5,7 +5,7 @@ namespace TypeLang\PHPDoc\Tag; /** - * @template-extends \Traversable, Tag> + * @template-extends \Traversable, TagInterface> * * @internal This is an internal library interface, please do not use it in your code. * @psalm-internal TypeLang\PHPDoc\Tag @@ -13,15 +13,17 @@ interface TagProviderInterface extends \Traversable, \Countable { /** - * Returns the tags for this DocBlock. + * Returns the tags for this object. * - * @psalm-immutable - * @return iterable + * @psalm-immutable Each call to the method must return the same value. + * + * @return iterable */ public function getTags(): iterable; /** - * @psalm-immutable + * @psalm-immutable Each call to the method must return the same value. + * * @return int<0, max> */ public function count(): int; diff --git a/src/Tag/TypeProviderInterface.php b/src/Tag/TypeProviderInterface.php new file mode 100644 index 0000000..e0004f9 --- /dev/null +++ b/src/Tag/TypeProviderInterface.php @@ -0,0 +1,23 @@ +type; + } } From 76a5811fef975fdcee38ad3d226de986b1f0bc88 Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 01:43:17 +0300 Subject: [PATCH 3/7] Fix psalm types --- src/Tag/TagProvider.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Tag/TagProvider.php b/src/Tag/TagProvider.php index 4605a32..fb802d6 100644 --- a/src/Tag/TagProvider.php +++ b/src/Tag/TagProvider.php @@ -32,7 +32,9 @@ protected function bootTagProvider(iterable $tags): void } /** - * {@see TagProviderInterface::getTags()} + * @see TagProviderInterface::getTags() + * + * @return list */ public function getTags(): array { From 7efc33ce8411f68a9fa4f483a3897e2652e055b0 Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 01:50:29 +0300 Subject: [PATCH 4/7] Add more common tag interfaces --- src/DocBlock.php | 11 ++++---- src/Tag/Description.php | 2 +- src/Tag/DescriptionInterface.php | 2 +- src/Tag/DescriptionProviderInterface.php | 4 +-- .../OptionalDescriptionProviderInterface.php | 16 ++++++++++++ src/Tag/OptionalTypeProviderInterface.php | 26 +++++++++++++++++++ .../OptionalVariableNameProviderInterface.php | 19 ++++++++++++++ src/Tag/TagInterface.php | 2 +- src/Tag/{TagProvider.php => TagsProvider.php} | 12 ++++----- ...nterface.php => TagsProviderInterface.php} | 2 +- src/Tag/TypeProviderInterface.php | 9 +++---- src/Tag/VariableNameProviderInterface.php | 18 +++++++++++++ 12 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 src/Tag/OptionalDescriptionProviderInterface.php create mode 100644 src/Tag/OptionalTypeProviderInterface.php create mode 100644 src/Tag/OptionalVariableNameProviderInterface.php rename src/Tag/{TagProvider.php => TagsProvider.php} (85%) rename src/Tag/{TagProviderInterface.php => TagsProviderInterface.php} (91%) create mode 100644 src/Tag/VariableNameProviderInterface.php diff --git a/src/DocBlock.php b/src/DocBlock.php index 3c05ad4..af325c2 100644 --- a/src/DocBlock.php +++ b/src/DocBlock.php @@ -7,9 +7,10 @@ use TypeLang\PHPDoc\Tag\Description; use TypeLang\PHPDoc\Tag\DescriptionInterface; use TypeLang\PHPDoc\Tag\DescriptionProviderInterface; +use TypeLang\PHPDoc\Tag\OptionalDescriptionProviderInterface; use TypeLang\PHPDoc\Tag\TagInterface; -use TypeLang\PHPDoc\Tag\TagProvider; -use TypeLang\PHPDoc\Tag\TagProviderInterface; +use TypeLang\PHPDoc\Tag\TagsProvider; +use TypeLang\PHPDoc\Tag\TagsProviderInterface; /** * This class represents structure containing a description and a set of tags @@ -19,12 +20,12 @@ * @template-implements \ArrayAccess, TagInterface|null> */ final class DocBlock implements - DescriptionProviderInterface, - TagProviderInterface, + OptionalDescriptionProviderInterface, + TagsProviderInterface, \IteratorAggregate, \ArrayAccess { - use TagProvider; + use TagsProvider; private readonly DescriptionInterface $description; diff --git a/src/Tag/Description.php b/src/Tag/Description.php index dc45abf..8b0519a 100644 --- a/src/Tag/Description.php +++ b/src/Tag/Description.php @@ -9,7 +9,7 @@ */ class Description implements DescriptionInterface, \IteratorAggregate { - use TagProvider; + use TagsProvider; protected readonly string $template; diff --git a/src/Tag/DescriptionInterface.php b/src/Tag/DescriptionInterface.php index 4c58c13..1326b5d 100644 --- a/src/Tag/DescriptionInterface.php +++ b/src/Tag/DescriptionInterface.php @@ -4,7 +4,7 @@ namespace TypeLang\PHPDoc\Tag; -interface DescriptionInterface extends TagProviderInterface, \Stringable +interface DescriptionInterface extends TagsProviderInterface, \Stringable { /** * Returns the body template. diff --git a/src/Tag/DescriptionProviderInterface.php b/src/Tag/DescriptionProviderInterface.php index 7b5513f..d585f58 100644 --- a/src/Tag/DescriptionProviderInterface.php +++ b/src/Tag/DescriptionProviderInterface.php @@ -4,7 +4,7 @@ namespace TypeLang\PHPDoc\Tag; -interface DescriptionProviderInterface +interface DescriptionProviderInterface extends OptionalDescriptionProviderInterface { /** * Returns description object which can be represented as a string and @@ -12,5 +12,5 @@ interface DescriptionProviderInterface * * @psalm-immutable Each call to the method must return the same value. */ - public function getDescription(): ?DescriptionInterface; + public function getDescription(): DescriptionInterface; } diff --git a/src/Tag/OptionalDescriptionProviderInterface.php b/src/Tag/OptionalDescriptionProviderInterface.php new file mode 100644 index 0000000..4d3dc14 --- /dev/null +++ b/src/Tag/OptionalDescriptionProviderInterface.php @@ -0,0 +1,16 @@ + @@ -32,9 +32,9 @@ protected function bootTagProvider(iterable $tags): void } /** - * @see TagProviderInterface::getTags() - * * @return list + *@see TagsProviderInterface::getTags() + * */ public function getTags(): array { @@ -51,7 +51,7 @@ public function getIterator(): \Traversable $description = $tag->getDescription(); - if ($description instanceof TagProviderInterface) { + if ($description instanceof TagsProviderInterface) { yield from $description; } } diff --git a/src/Tag/TagProviderInterface.php b/src/Tag/TagsProviderInterface.php similarity index 91% rename from src/Tag/TagProviderInterface.php rename to src/Tag/TagsProviderInterface.php index 6000b07..eb7e44a 100644 --- a/src/Tag/TagProviderInterface.php +++ b/src/Tag/TagsProviderInterface.php @@ -10,7 +10,7 @@ * @internal This is an internal library interface, please do not use it in your code. * @psalm-internal TypeLang\PHPDoc\Tag */ -interface TagProviderInterface extends \Traversable, \Countable +interface TagsProviderInterface extends \Traversable, \Countable { /** * Returns the tags for this object. diff --git a/src/Tag/TypeProviderInterface.php b/src/Tag/TypeProviderInterface.php index e0004f9..6b94571 100644 --- a/src/Tag/TypeProviderInterface.php +++ b/src/Tag/TypeProviderInterface.php @@ -7,17 +7,14 @@ use TypeLang\Parser\Node\Stmt\TypeStatement; /** - * Every class that implements a given interface is an implementation of a - * tag that contains type information (that is, an AST object). - * - * Requires a `type-lang/parser` dependency for {@see TypeStatement} support. - * * @psalm-suppress UndefinedClass : Expects optional `type-lang/parser` dependency. */ -interface TypeProviderInterface +interface TypeProviderInterface extends OptionalTypeProviderInterface { /** * Returns an AST object of the type. + * + * @psalm-immutable Each call to the method must return the same value. */ public function getType(): TypeStatement; } diff --git a/src/Tag/VariableNameProviderInterface.php b/src/Tag/VariableNameProviderInterface.php new file mode 100644 index 0000000..3c29c23 --- /dev/null +++ b/src/Tag/VariableNameProviderInterface.php @@ -0,0 +1,18 @@ + Date: Wed, 3 Apr 2024 01:52:02 +0300 Subject: [PATCH 5/7] Fix prefixed tag behaviour --- src/Tag/Factory/PrefixedTagFactory.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Tag/Factory/PrefixedTagFactory.php b/src/Tag/Factory/PrefixedTagFactory.php index 28d3785..5f6a412 100644 --- a/src/Tag/Factory/PrefixedTagFactory.php +++ b/src/Tag/Factory/PrefixedTagFactory.php @@ -19,8 +19,10 @@ public function __construct( public function register(array|string $tags, FactoryInterface $delegate): void { - foreach ($this->prefixes as $prefix) { - foreach ((array) $tags as $tag) { + foreach ((array) $tags as $tag) { + $this->delegate->register($tag, $delegate); + + foreach ($this->prefixes as $prefix) { $this->delegate->register($prefix . $tag, $delegate); } } From ee83c0c5bbca63c33508dddb7b555320fec52ff9 Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 01:52:53 +0300 Subject: [PATCH 6/7] Add PrefixedTagFactory::$allowNonPrefixedTags config parameter --- src/Tag/Factory/PrefixedTagFactory.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tag/Factory/PrefixedTagFactory.php b/src/Tag/Factory/PrefixedTagFactory.php index 5f6a412..c095457 100644 --- a/src/Tag/Factory/PrefixedTagFactory.php +++ b/src/Tag/Factory/PrefixedTagFactory.php @@ -15,12 +15,15 @@ final class PrefixedTagFactory implements MutableFactoryInterface public function __construct( private readonly array $prefixes, private readonly MutableFactoryInterface $delegate = new TagFactory(), + private readonly bool $allowNonPrefixedTags = true, ) {} public function register(array|string $tags, FactoryInterface $delegate): void { foreach ((array) $tags as $tag) { - $this->delegate->register($tag, $delegate); + if ($this->allowNonPrefixedTags) { + $this->delegate->register($tag, $delegate); + } foreach ($this->prefixes as $prefix) { $this->delegate->register($prefix . $tag, $delegate); From 91015664378c61a52c952dc7d0322133052f7a79 Mon Sep 17 00:00:00 2001 From: Kirill Nesmeyanov Date: Wed, 3 Apr 2024 01:59:37 +0300 Subject: [PATCH 7/7] Fix psalm errors --- src/Tag/OptionalTypeProviderInterface.php | 3 +-- src/Tag/TypeProviderInterface.php | 4 +--- src/Tag/TypedTag.php | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Tag/OptionalTypeProviderInterface.php b/src/Tag/OptionalTypeProviderInterface.php index 7c734f0..cc9211a 100644 --- a/src/Tag/OptionalTypeProviderInterface.php +++ b/src/Tag/OptionalTypeProviderInterface.php @@ -11,8 +11,6 @@ * tag that contains type information (that is, an AST object). * * Requires a `type-lang/parser` dependency for {@see TypeStatement} support. - * - * @psalm-suppress UndefinedClass : Expects optional `type-lang/parser` dependency. */ interface OptionalTypeProviderInterface { @@ -20,6 +18,7 @@ interface OptionalTypeProviderInterface * Returns an AST object of the type or {@see null} in case the * type is not specified. * + * @psalm-suppress UndefinedClass : Expects optional `type-lang/parser` dependency. * @psalm-immutable Each call to the method must return the same value. */ public function getType(): ?TypeStatement; diff --git a/src/Tag/TypeProviderInterface.php b/src/Tag/TypeProviderInterface.php index 6b94571..3402419 100644 --- a/src/Tag/TypeProviderInterface.php +++ b/src/Tag/TypeProviderInterface.php @@ -6,14 +6,12 @@ use TypeLang\Parser\Node\Stmt\TypeStatement; -/** - * @psalm-suppress UndefinedClass : Expects optional `type-lang/parser` dependency. - */ interface TypeProviderInterface extends OptionalTypeProviderInterface { /** * Returns an AST object of the type. * + * @psalm-suppress UndefinedClass : Expects optional `type-lang/parser` dependency. * @psalm-immutable Each call to the method must return the same value. */ public function getType(): TypeStatement; diff --git a/src/Tag/TypedTag.php b/src/Tag/TypedTag.php index eafdb63..b3aabee 100644 --- a/src/Tag/TypedTag.php +++ b/src/Tag/TypedTag.php @@ -22,6 +22,9 @@ public function __construct( parent::__construct($name, $description); } + /** + * @psalm-suppress UndefinedClass + */ public function getType(): TypeStatement { return $this->type;