@@ -24,16 +24,16 @@ |
||
24 | 24 | */ |
25 | 25 | final class NonEmptyString extends String_ implements PseudoType |
26 | 26 | { |
27 | - public function underlyingType(): Type |
|
28 | - { |
|
29 | - return new String_(); |
|
30 | - } |
|
27 | + public function underlyingType(): Type |
|
28 | + { |
|
29 | + return new String_(); |
|
30 | + } |
|
31 | 31 | |
32 | - /** |
|
33 | - * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
34 | - */ |
|
35 | - public function __toString(): string |
|
36 | - { |
|
37 | - return 'non-empty-string'; |
|
38 | - } |
|
32 | + /** |
|
33 | + * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
34 | + */ |
|
35 | + public function __toString(): string |
|
36 | + { |
|
37 | + return 'non-empty-string'; |
|
38 | + } |
|
39 | 39 | } |
@@ -26,15 +26,15 @@ |
||
26 | 26 | */ |
27 | 27 | final class False_ extends Boolean implements PseudoType |
28 | 28 | { |
29 | - public function underlyingType(): Type |
|
30 | - { |
|
31 | - return new Boolean(); |
|
32 | - } |
|
33 | - |
|
34 | - public function __toString(): string |
|
35 | - { |
|
36 | - return 'false'; |
|
37 | - } |
|
29 | + public function underlyingType(): Type |
|
30 | + { |
|
31 | + return new Boolean(); |
|
32 | + } |
|
33 | + |
|
34 | + public function __toString(): string |
|
35 | + { |
|
36 | + return 'false'; |
|
37 | + } |
|
38 | 38 | } |
39 | 39 | |
40 | 40 | class_alias('\phpDocumentor\Reflection\PseudoTypes\False_', 'phpDocumentor\Reflection\Types\False_', false); |
@@ -24,16 +24,16 @@ |
||
24 | 24 | */ |
25 | 25 | final class LiteralString extends String_ implements PseudoType |
26 | 26 | { |
27 | - public function underlyingType(): Type |
|
28 | - { |
|
29 | - return new String_(); |
|
30 | - } |
|
27 | + public function underlyingType(): Type |
|
28 | + { |
|
29 | + return new String_(); |
|
30 | + } |
|
31 | 31 | |
32 | - /** |
|
33 | - * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
34 | - */ |
|
35 | - public function __toString(): string |
|
36 | - { |
|
37 | - return 'literal-string'; |
|
38 | - } |
|
32 | + /** |
|
33 | + * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
34 | + */ |
|
35 | + public function __toString(): string |
|
36 | + { |
|
37 | + return 'literal-string'; |
|
38 | + } |
|
39 | 39 | } |
@@ -15,5 +15,5 @@ |
||
15 | 15 | |
16 | 16 | interface PseudoType extends Type |
17 | 17 | { |
18 | - public function underlyingType(): Type; |
|
18 | + public function underlyingType(): Type; |
|
19 | 19 | } |
@@ -18,8 +18,8 @@ |
||
18 | 18 | */ |
19 | 19 | interface Type |
20 | 20 | { |
21 | - /** |
|
22 | - * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
23 | - */ |
|
24 | - public function __toString(): string; |
|
21 | + /** |
|
22 | + * Returns a rendered output of the Type as it would be used in a DocBlock. |
|
23 | + */ |
|
24 | + public function __toString(): string; |
|
25 | 25 | } |
@@ -27,54 +27,54 @@ |
||
27 | 27 | */ |
28 | 28 | class FqsenResolver |
29 | 29 | { |
30 | - /** @var string Definition of the NAMESPACE operator in PHP */ |
|
31 | - private const OPERATOR_NAMESPACE = '\\'; |
|
32 | - |
|
33 | - public function resolve(string $fqsen, ?Context $context = null): Fqsen |
|
34 | - { |
|
35 | - if ($context === null) { |
|
36 | - $context = new Context(''); |
|
37 | - } |
|
38 | - |
|
39 | - if ($this->isFqsen($fqsen)) { |
|
40 | - return new Fqsen($fqsen); |
|
41 | - } |
|
42 | - |
|
43 | - return $this->resolvePartialStructuralElementName($fqsen, $context); |
|
44 | - } |
|
45 | - |
|
46 | - /** |
|
47 | - * Tests whether the given type is a Fully Qualified Structural Element Name. |
|
48 | - */ |
|
49 | - private function isFqsen(string $type): bool |
|
50 | - { |
|
51 | - return strpos($type, self::OPERATOR_NAMESPACE) === 0; |
|
52 | - } |
|
53 | - |
|
54 | - /** |
|
55 | - * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation |
|
56 | - * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context. |
|
57 | - * |
|
58 | - * @throws InvalidArgumentException When type is not a valid FQSEN. |
|
59 | - */ |
|
60 | - private function resolvePartialStructuralElementName(string $type, Context $context): Fqsen |
|
61 | - { |
|
62 | - $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2); |
|
63 | - |
|
64 | - $namespaceAliases = $context->getNamespaceAliases(); |
|
65 | - |
|
66 | - // if the first segment is not an alias; prepend namespace name and return |
|
67 | - if (!isset($namespaceAliases[$typeParts[0]])) { |
|
68 | - $namespace = $context->getNamespace(); |
|
69 | - if ($namespace !== '') { |
|
70 | - $namespace .= self::OPERATOR_NAMESPACE; |
|
71 | - } |
|
72 | - |
|
73 | - return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type); |
|
74 | - } |
|
75 | - |
|
76 | - $typeParts[0] = $namespaceAliases[$typeParts[0]]; |
|
77 | - |
|
78 | - return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts)); |
|
79 | - } |
|
30 | + /** @var string Definition of the NAMESPACE operator in PHP */ |
|
31 | + private const OPERATOR_NAMESPACE = '\\'; |
|
32 | + |
|
33 | + public function resolve(string $fqsen, ?Context $context = null): Fqsen |
|
34 | + { |
|
35 | + if ($context === null) { |
|
36 | + $context = new Context(''); |
|
37 | + } |
|
38 | + |
|
39 | + if ($this->isFqsen($fqsen)) { |
|
40 | + return new Fqsen($fqsen); |
|
41 | + } |
|
42 | + |
|
43 | + return $this->resolvePartialStructuralElementName($fqsen, $context); |
|
44 | + } |
|
45 | + |
|
46 | + /** |
|
47 | + * Tests whether the given type is a Fully Qualified Structural Element Name. |
|
48 | + */ |
|
49 | + private function isFqsen(string $type): bool |
|
50 | + { |
|
51 | + return strpos($type, self::OPERATOR_NAMESPACE) === 0; |
|
52 | + } |
|
53 | + |
|
54 | + /** |
|
55 | + * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation |
|
56 | + * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context. |
|
57 | + * |
|
58 | + * @throws InvalidArgumentException When type is not a valid FQSEN. |
|
59 | + */ |
|
60 | + private function resolvePartialStructuralElementName(string $type, Context $context): Fqsen |
|
61 | + { |
|
62 | + $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2); |
|
63 | + |
|
64 | + $namespaceAliases = $context->getNamespaceAliases(); |
|
65 | + |
|
66 | + // if the first segment is not an alias; prepend namespace name and return |
|
67 | + if (!isset($namespaceAliases[$typeParts[0]])) { |
|
68 | + $namespace = $context->getNamespace(); |
|
69 | + if ($namespace !== '') { |
|
70 | + $namespace .= self::OPERATOR_NAMESPACE; |
|
71 | + } |
|
72 | + |
|
73 | + return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type); |
|
74 | + } |
|
75 | + |
|
76 | + $typeParts[0] = $namespaceAliases[$typeParts[0]]; |
|
77 | + |
|
78 | + return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts)); |
|
79 | + } |
|
80 | 80 | } |
@@ -64,17 +64,17 @@ |
||
64 | 64 | $namespaceAliases = $context->getNamespaceAliases(); |
65 | 65 | |
66 | 66 | // if the first segment is not an alias; prepend namespace name and return |
67 | - if (!isset($namespaceAliases[$typeParts[0]])) { |
|
67 | + if ( ! isset($namespaceAliases[$typeParts[0]])) { |
|
68 | 68 | $namespace = $context->getNamespace(); |
69 | 69 | if ($namespace !== '') { |
70 | 70 | $namespace .= self::OPERATOR_NAMESPACE; |
71 | 71 | } |
72 | 72 | |
73 | - return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type); |
|
73 | + return new Fqsen(self::OPERATOR_NAMESPACE.$namespace.$type); |
|
74 | 74 | } |
75 | 75 | |
76 | 76 | $typeParts[0] = $namespaceAliases[$typeParts[0]]; |
77 | 77 | |
78 | - return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts)); |
|
78 | + return new Fqsen(self::OPERATOR_NAMESPACE.implode(self::OPERATOR_NAMESPACE, $typeParts)); |
|
79 | 79 | } |
80 | 80 | } |
@@ -21,42 +21,42 @@ |
||
21 | 21 | |
22 | 22 | abstract class Utils |
23 | 23 | { |
24 | - /** |
|
25 | - * Wrapper function for phps preg_split |
|
26 | - * |
|
27 | - * This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But |
|
28 | - * since this library is all about performance we decided to strip everything we don't need. Reducing the amount |
|
29 | - * of files that have to be loaded, ect. |
|
30 | - * |
|
31 | - * @param string $pattern The pattern to search for, as a string. |
|
32 | - * @param string $subject The input string. |
|
33 | - * @param int $limit If specified, then only substrings up to limit are returned with the |
|
34 | - * rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit". |
|
35 | - * @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator): |
|
36 | - * *PREG_SPLIT_NO_EMPTY* |
|
37 | - * If this flag is set, only non-empty pieces will be returned by preg_split(). |
|
38 | - * *PREG_SPLIT_DELIM_CAPTURE* |
|
39 | - * If this flag is set, parenthesized expression in the delimiter pattern will be captured |
|
40 | - * and returned as well. |
|
41 | - * *PREG_SPLIT_OFFSET_CAPTURE* |
|
42 | - * If this flag is set, for every occurring match the appendant string offset will also be returned. |
|
43 | - * Note that this changes the return value in an array where every element is an array consisting of the |
|
44 | - * matched string at offset 0 and its string offset into subject at offset 1. |
|
45 | - * |
|
46 | - * @return string[] Returns an array containing substrings of subject |
|
47 | - * split along boundaries matched by pattern |
|
48 | - * |
|
49 | - * @throws PcreException |
|
50 | - */ |
|
51 | - public static function pregSplit(string $pattern, string $subject, int $limit = -1, int $flags = 0): array |
|
52 | - { |
|
53 | - $parts = php_preg_split($pattern, $subject, $limit, $flags); |
|
54 | - if ($parts === false) { |
|
55 | - throw PcreException::createFromPhpError(preg_last_error()); |
|
56 | - } |
|
57 | - |
|
58 | - Assert::allString($parts); |
|
59 | - |
|
60 | - return $parts; |
|
61 | - } |
|
24 | + /** |
|
25 | + * Wrapper function for phps preg_split |
|
26 | + * |
|
27 | + * This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But |
|
28 | + * since this library is all about performance we decided to strip everything we don't need. Reducing the amount |
|
29 | + * of files that have to be loaded, ect. |
|
30 | + * |
|
31 | + * @param string $pattern The pattern to search for, as a string. |
|
32 | + * @param string $subject The input string. |
|
33 | + * @param int $limit If specified, then only substrings up to limit are returned with the |
|
34 | + * rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit". |
|
35 | + * @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator): |
|
36 | + * *PREG_SPLIT_NO_EMPTY* |
|
37 | + * If this flag is set, only non-empty pieces will be returned by preg_split(). |
|
38 | + * *PREG_SPLIT_DELIM_CAPTURE* |
|
39 | + * If this flag is set, parenthesized expression in the delimiter pattern will be captured |
|
40 | + * and returned as well. |
|
41 | + * *PREG_SPLIT_OFFSET_CAPTURE* |
|
42 | + * If this flag is set, for every occurring match the appendant string offset will also be returned. |
|
43 | + * Note that this changes the return value in an array where every element is an array consisting of the |
|
44 | + * matched string at offset 0 and its string offset into subject at offset 1. |
|
45 | + * |
|
46 | + * @return string[] Returns an array containing substrings of subject |
|
47 | + * split along boundaries matched by pattern |
|
48 | + * |
|
49 | + * @throws PcreException |
|
50 | + */ |
|
51 | + public static function pregSplit(string $pattern, string $subject, int $limit = -1, int $flags = 0): array |
|
52 | + { |
|
53 | + $parts = php_preg_split($pattern, $subject, $limit, $flags); |
|
54 | + if ($parts === false) { |
|
55 | + throw PcreException::createFromPhpError(preg_last_error()); |
|
56 | + } |
|
57 | + |
|
58 | + Assert::allString($parts); |
|
59 | + |
|
60 | + return $parts; |
|
61 | + } |
|
62 | 62 | } |
@@ -35,134 +35,134 @@ discard block |
||
35 | 35 | |
36 | 36 | final class DocBlockFactory implements DocBlockFactoryInterface |
37 | 37 | { |
38 | - /** @var DocBlock\DescriptionFactory */ |
|
39 | - private $descriptionFactory; |
|
40 | - |
|
41 | - /** @var DocBlock\TagFactory */ |
|
42 | - private $tagFactory; |
|
43 | - |
|
44 | - /** |
|
45 | - * Initializes this factory with the required subcontractors. |
|
46 | - */ |
|
47 | - public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory) |
|
48 | - { |
|
49 | - $this->descriptionFactory = $descriptionFactory; |
|
50 | - $this->tagFactory = $tagFactory; |
|
51 | - } |
|
52 | - |
|
53 | - /** |
|
54 | - * Factory method for easy instantiation. |
|
55 | - * |
|
56 | - * @param array<string, class-string<Tag>> $additionalTags |
|
57 | - */ |
|
58 | - public static function createInstance(array $additionalTags = []): self |
|
59 | - { |
|
60 | - $fqsenResolver = new FqsenResolver(); |
|
61 | - $tagFactory = new StandardTagFactory($fqsenResolver); |
|
62 | - $descriptionFactory = new DescriptionFactory($tagFactory); |
|
63 | - |
|
64 | - $tagFactory->addService($descriptionFactory); |
|
65 | - $tagFactory->addService(new TypeResolver($fqsenResolver)); |
|
66 | - |
|
67 | - $docBlockFactory = new self($descriptionFactory, $tagFactory); |
|
68 | - foreach ($additionalTags as $tagName => $tagHandler) { |
|
69 | - $docBlockFactory->registerTagHandler($tagName, $tagHandler); |
|
70 | - } |
|
71 | - |
|
72 | - return $docBlockFactory; |
|
73 | - } |
|
74 | - |
|
75 | - /** |
|
76 | - * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the |
|
77 | - * getDocComment method (such as a ReflectionClass object). |
|
78 | - */ |
|
79 | - public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock |
|
80 | - { |
|
81 | - if (is_object($docblock)) { |
|
82 | - if (!method_exists($docblock, 'getDocComment')) { |
|
83 | - $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; |
|
84 | - |
|
85 | - throw new InvalidArgumentException($exceptionMessage); |
|
86 | - } |
|
87 | - |
|
88 | - $docblock = $docblock->getDocComment(); |
|
89 | - Assert::string($docblock); |
|
90 | - } |
|
91 | - |
|
92 | - Assert::stringNotEmpty($docblock); |
|
93 | - |
|
94 | - if ($context === null) { |
|
95 | - $context = new Types\Context(''); |
|
96 | - } |
|
97 | - |
|
98 | - $parts = $this->splitDocBlock($this->stripDocComment($docblock)); |
|
99 | - |
|
100 | - [$templateMarker, $summary, $description, $tags] = $parts; |
|
101 | - |
|
102 | - return new DocBlock( |
|
103 | - $summary, |
|
104 | - $description ? $this->descriptionFactory->create($description, $context) : null, |
|
105 | - $this->parseTagBlock($tags, $context), |
|
106 | - $context, |
|
107 | - $location, |
|
108 | - $templateMarker === '#@+', |
|
109 | - $templateMarker === '#@-' |
|
110 | - ); |
|
111 | - } |
|
112 | - |
|
113 | - /** |
|
114 | - * @param class-string<Tag> $handler |
|
115 | - */ |
|
116 | - public function registerTagHandler(string $tagName, string $handler): void |
|
117 | - { |
|
118 | - $this->tagFactory->registerTagHandler($tagName, $handler); |
|
119 | - } |
|
120 | - |
|
121 | - /** |
|
122 | - * Strips the asterisks from the DocBlock comment. |
|
123 | - * |
|
124 | - * @param string $comment String containing the comment text. |
|
125 | - */ |
|
126 | - private function stripDocComment(string $comment): string |
|
127 | - { |
|
128 | - $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment); |
|
129 | - Assert::string($comment); |
|
130 | - $comment = trim($comment); |
|
131 | - |
|
132 | - // reg ex above is not able to remove */ from a single line docblock |
|
133 | - if (substr($comment, -2) === '*/') { |
|
134 | - $comment = trim(substr($comment, 0, -2)); |
|
135 | - } |
|
136 | - |
|
137 | - return str_replace(["\r\n", "\r"], "\n", $comment); |
|
138 | - } |
|
139 | - |
|
140 | - // phpcs:disable |
|
141 | - /** |
|
142 | - * Splits the DocBlock into a template marker, summary, description and block of tags. |
|
143 | - * |
|
144 | - * @param string $comment Comment to split into the sub-parts. |
|
145 | - * |
|
146 | - * @return string[] containing the template marker (if any), summary, description and a string containing the tags. |
|
147 | - * |
|
148 | - * @author Mike van Riel <[email protected]> for extending the regex with template marker support. |
|
149 | - * |
|
150 | - * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. |
|
151 | - */ |
|
152 | - private function splitDocBlock(string $comment) : array |
|
153 | - { |
|
154 | - // phpcs:enable |
|
155 | - // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This |
|
156 | - // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the |
|
157 | - // performance impact of running a regular expression |
|
158 | - if (strpos($comment, '@') === 0) { |
|
159 | - return ['', '', '', $comment]; |
|
160 | - } |
|
161 | - |
|
162 | - // clears all extra horizontal whitespace from the line endings to prevent parsing issues |
|
163 | - $comment = preg_replace('/\h*$/Sum', '', $comment); |
|
164 | - Assert::string($comment); |
|
165 | - /* |
|
38 | + /** @var DocBlock\DescriptionFactory */ |
|
39 | + private $descriptionFactory; |
|
40 | + |
|
41 | + /** @var DocBlock\TagFactory */ |
|
42 | + private $tagFactory; |
|
43 | + |
|
44 | + /** |
|
45 | + * Initializes this factory with the required subcontractors. |
|
46 | + */ |
|
47 | + public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory) |
|
48 | + { |
|
49 | + $this->descriptionFactory = $descriptionFactory; |
|
50 | + $this->tagFactory = $tagFactory; |
|
51 | + } |
|
52 | + |
|
53 | + /** |
|
54 | + * Factory method for easy instantiation. |
|
55 | + * |
|
56 | + * @param array<string, class-string<Tag>> $additionalTags |
|
57 | + */ |
|
58 | + public static function createInstance(array $additionalTags = []): self |
|
59 | + { |
|
60 | + $fqsenResolver = new FqsenResolver(); |
|
61 | + $tagFactory = new StandardTagFactory($fqsenResolver); |
|
62 | + $descriptionFactory = new DescriptionFactory($tagFactory); |
|
63 | + |
|
64 | + $tagFactory->addService($descriptionFactory); |
|
65 | + $tagFactory->addService(new TypeResolver($fqsenResolver)); |
|
66 | + |
|
67 | + $docBlockFactory = new self($descriptionFactory, $tagFactory); |
|
68 | + foreach ($additionalTags as $tagName => $tagHandler) { |
|
69 | + $docBlockFactory->registerTagHandler($tagName, $tagHandler); |
|
70 | + } |
|
71 | + |
|
72 | + return $docBlockFactory; |
|
73 | + } |
|
74 | + |
|
75 | + /** |
|
76 | + * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the |
|
77 | + * getDocComment method (such as a ReflectionClass object). |
|
78 | + */ |
|
79 | + public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock |
|
80 | + { |
|
81 | + if (is_object($docblock)) { |
|
82 | + if (!method_exists($docblock, 'getDocComment')) { |
|
83 | + $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; |
|
84 | + |
|
85 | + throw new InvalidArgumentException($exceptionMessage); |
|
86 | + } |
|
87 | + |
|
88 | + $docblock = $docblock->getDocComment(); |
|
89 | + Assert::string($docblock); |
|
90 | + } |
|
91 | + |
|
92 | + Assert::stringNotEmpty($docblock); |
|
93 | + |
|
94 | + if ($context === null) { |
|
95 | + $context = new Types\Context(''); |
|
96 | + } |
|
97 | + |
|
98 | + $parts = $this->splitDocBlock($this->stripDocComment($docblock)); |
|
99 | + |
|
100 | + [$templateMarker, $summary, $description, $tags] = $parts; |
|
101 | + |
|
102 | + return new DocBlock( |
|
103 | + $summary, |
|
104 | + $description ? $this->descriptionFactory->create($description, $context) : null, |
|
105 | + $this->parseTagBlock($tags, $context), |
|
106 | + $context, |
|
107 | + $location, |
|
108 | + $templateMarker === '#@+', |
|
109 | + $templateMarker === '#@-' |
|
110 | + ); |
|
111 | + } |
|
112 | + |
|
113 | + /** |
|
114 | + * @param class-string<Tag> $handler |
|
115 | + */ |
|
116 | + public function registerTagHandler(string $tagName, string $handler): void |
|
117 | + { |
|
118 | + $this->tagFactory->registerTagHandler($tagName, $handler); |
|
119 | + } |
|
120 | + |
|
121 | + /** |
|
122 | + * Strips the asterisks from the DocBlock comment. |
|
123 | + * |
|
124 | + * @param string $comment String containing the comment text. |
|
125 | + */ |
|
126 | + private function stripDocComment(string $comment): string |
|
127 | + { |
|
128 | + $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment); |
|
129 | + Assert::string($comment); |
|
130 | + $comment = trim($comment); |
|
131 | + |
|
132 | + // reg ex above is not able to remove */ from a single line docblock |
|
133 | + if (substr($comment, -2) === '*/') { |
|
134 | + $comment = trim(substr($comment, 0, -2)); |
|
135 | + } |
|
136 | + |
|
137 | + return str_replace(["\r\n", "\r"], "\n", $comment); |
|
138 | + } |
|
139 | + |
|
140 | + // phpcs:disable |
|
141 | + /** |
|
142 | + * Splits the DocBlock into a template marker, summary, description and block of tags. |
|
143 | + * |
|
144 | + * @param string $comment Comment to split into the sub-parts. |
|
145 | + * |
|
146 | + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. |
|
147 | + * |
|
148 | + * @author Mike van Riel <[email protected]> for extending the regex with template marker support. |
|
149 | + * |
|
150 | + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. |
|
151 | + */ |
|
152 | + private function splitDocBlock(string $comment) : array |
|
153 | + { |
|
154 | + // phpcs:enable |
|
155 | + // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This |
|
156 | + // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the |
|
157 | + // performance impact of running a regular expression |
|
158 | + if (strpos($comment, '@') === 0) { |
|
159 | + return ['', '', '', $comment]; |
|
160 | + } |
|
161 | + |
|
162 | + // clears all extra horizontal whitespace from the line endings to prevent parsing issues |
|
163 | + $comment = preg_replace('/\h*$/Sum', '', $comment); |
|
164 | + Assert::string($comment); |
|
165 | + /* |
|
166 | 166 | * Splits the docblock into a template marker, summary, description and tags section. |
167 | 167 | * |
168 | 168 | * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may |
@@ -176,8 +176,8 @@ discard block |
||
176 | 176 | * |
177 | 177 | * Big thanks to RichardJ for contributing this Regular Expression |
178 | 178 | */ |
179 | - preg_match( |
|
180 | - '/ |
|
179 | + preg_match( |
|
180 | + '/ |
|
181 | 181 | \A |
182 | 182 | # 1. Extract the template marker |
183 | 183 | (?:(\#\@\+|\#\@\-)\n?)? |
@@ -212,76 +212,76 @@ discard block |
||
212 | 212 | # 4. Extract the tags (anything that follows) |
213 | 213 | (\s+ [\s\S]*)? # everything that follows |
214 | 214 | /ux', |
215 | - $comment, |
|
216 | - $matches |
|
217 | - ); |
|
218 | - array_shift($matches); |
|
219 | - |
|
220 | - while (count($matches) < 4) { |
|
221 | - $matches[] = ''; |
|
222 | - } |
|
223 | - |
|
224 | - return $matches; |
|
225 | - } |
|
226 | - |
|
227 | - /** |
|
228 | - * Creates the tag objects. |
|
229 | - * |
|
230 | - * @param string $tags Tag block to parse. |
|
231 | - * @param Types\Context $context Context of the parsed Tag |
|
232 | - * |
|
233 | - * @return DocBlock\Tag[] |
|
234 | - */ |
|
235 | - private function parseTagBlock(string $tags, Types\Context $context): array |
|
236 | - { |
|
237 | - $tags = $this->filterTagBlock($tags); |
|
238 | - if ($tags === null) { |
|
239 | - return []; |
|
240 | - } |
|
241 | - |
|
242 | - $result = []; |
|
243 | - $lines = $this->splitTagBlockIntoTagLines($tags); |
|
244 | - foreach ($lines as $key => $tagLine) { |
|
245 | - $result[$key] = $this->tagFactory->create(trim($tagLine), $context); |
|
246 | - } |
|
247 | - |
|
248 | - return $result; |
|
249 | - } |
|
250 | - |
|
251 | - /** |
|
252 | - * @return string[] |
|
253 | - */ |
|
254 | - private function splitTagBlockIntoTagLines(string $tags): array |
|
255 | - { |
|
256 | - $result = []; |
|
257 | - foreach (explode("\n", $tags) as $tagLine) { |
|
258 | - if ($tagLine !== '' && strpos($tagLine, '@') === 0) { |
|
259 | - $result[] = $tagLine; |
|
260 | - } else { |
|
261 | - $result[count($result) - 1] .= "\n" . $tagLine; |
|
262 | - } |
|
263 | - } |
|
264 | - |
|
265 | - return $result; |
|
266 | - } |
|
267 | - |
|
268 | - private function filterTagBlock(string $tags): ?string |
|
269 | - { |
|
270 | - $tags = trim($tags); |
|
271 | - if (!$tags) { |
|
272 | - return null; |
|
273 | - } |
|
274 | - |
|
275 | - if ($tags[0] !== '@') { |
|
276 | - // @codeCoverageIgnoreStart |
|
277 | - // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that |
|
278 | - // we didn't foresee. |
|
279 | - |
|
280 | - throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); |
|
281 | - |
|
282 | - // @codeCoverageIgnoreEnd |
|
283 | - } |
|
284 | - |
|
285 | - return $tags; |
|
286 | - } |
|
215 | + $comment, |
|
216 | + $matches |
|
217 | + ); |
|
218 | + array_shift($matches); |
|
219 | + |
|
220 | + while (count($matches) < 4) { |
|
221 | + $matches[] = ''; |
|
222 | + } |
|
223 | + |
|
224 | + return $matches; |
|
225 | + } |
|
226 | + |
|
227 | + /** |
|
228 | + * Creates the tag objects. |
|
229 | + * |
|
230 | + * @param string $tags Tag block to parse. |
|
231 | + * @param Types\Context $context Context of the parsed Tag |
|
232 | + * |
|
233 | + * @return DocBlock\Tag[] |
|
234 | + */ |
|
235 | + private function parseTagBlock(string $tags, Types\Context $context): array |
|
236 | + { |
|
237 | + $tags = $this->filterTagBlock($tags); |
|
238 | + if ($tags === null) { |
|
239 | + return []; |
|
240 | + } |
|
241 | + |
|
242 | + $result = []; |
|
243 | + $lines = $this->splitTagBlockIntoTagLines($tags); |
|
244 | + foreach ($lines as $key => $tagLine) { |
|
245 | + $result[$key] = $this->tagFactory->create(trim($tagLine), $context); |
|
246 | + } |
|
247 | + |
|
248 | + return $result; |
|
249 | + } |
|
250 | + |
|
251 | + /** |
|
252 | + * @return string[] |
|
253 | + */ |
|
254 | + private function splitTagBlockIntoTagLines(string $tags): array |
|
255 | + { |
|
256 | + $result = []; |
|
257 | + foreach (explode("\n", $tags) as $tagLine) { |
|
258 | + if ($tagLine !== '' && strpos($tagLine, '@') === 0) { |
|
259 | + $result[] = $tagLine; |
|
260 | + } else { |
|
261 | + $result[count($result) - 1] .= "\n" . $tagLine; |
|
262 | + } |
|
263 | + } |
|
264 | + |
|
265 | + return $result; |
|
266 | + } |
|
267 | + |
|
268 | + private function filterTagBlock(string $tags): ?string |
|
269 | + { |
|
270 | + $tags = trim($tags); |
|
271 | + if (!$tags) { |
|
272 | + return null; |
|
273 | + } |
|
274 | + |
|
275 | + if ($tags[0] !== '@') { |
|
276 | + // @codeCoverageIgnoreStart |
|
277 | + // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that |
|
278 | + // we didn't foresee. |
|
279 | + |
|
280 | + throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); |
|
281 | + |
|
282 | + // @codeCoverageIgnoreEnd |
|
283 | + } |
|
284 | + |
|
285 | + return $tags; |
|
286 | + } |
|
287 | 287 | } |
@@ -79,7 +79,7 @@ discard block |
||
79 | 79 | public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock |
80 | 80 | { |
81 | 81 | if (is_object($docblock)) { |
82 | - if (!method_exists($docblock, 'getDocComment')) { |
|
82 | + if ( ! method_exists($docblock, 'getDocComment')) { |
|
83 | 83 | $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; |
84 | 84 | |
85 | 85 | throw new InvalidArgumentException($exceptionMessage); |
@@ -258,7 +258,7 @@ discard block |
||
258 | 258 | if ($tagLine !== '' && strpos($tagLine, '@') === 0) { |
259 | 259 | $result[] = $tagLine; |
260 | 260 | } else { |
261 | - $result[count($result) - 1] .= "\n" . $tagLine; |
|
261 | + $result[count($result) - 1] .= "\n".$tagLine; |
|
262 | 262 | } |
263 | 263 | } |
264 | 264 | |
@@ -268,7 +268,7 @@ discard block |
||
268 | 268 | private function filterTagBlock(string $tags): ?string |
269 | 269 | { |
270 | 270 | $tags = trim($tags); |
271 | - if (!$tags) { |
|
271 | + if ( ! $tags) { |
|
272 | 272 | return null; |
273 | 273 | } |
274 | 274 | |
@@ -277,7 +277,7 @@ discard block |
||
277 | 277 | // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that |
278 | 278 | // we didn't foresee. |
279 | 279 | |
280 | - throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); |
|
280 | + throw new LogicException('A tag block started with text instead of an at-sign(@): '.$tags); |
|
281 | 281 | |
282 | 282 | // @codeCoverageIgnoreEnd |
283 | 283 | } |
@@ -19,210 +19,210 @@ |
||
19 | 19 | |
20 | 20 | final class DocBlock |
21 | 21 | { |
22 | - /** @var string The opening line for this docblock. */ |
|
23 | - private $summary; |
|
24 | - |
|
25 | - /** @var DocBlock\Description The actual description for this docblock. */ |
|
26 | - private $description; |
|
27 | - |
|
28 | - /** @var Tag[] An array containing all the tags in this docblock; except inline. */ |
|
29 | - private $tags = []; |
|
30 | - |
|
31 | - /** @var Types\Context|null Information about the context of this DocBlock. */ |
|
32 | - private $context; |
|
33 | - |
|
34 | - /** @var Location|null Information about the location of this DocBlock. */ |
|
35 | - private $location; |
|
36 | - |
|
37 | - /** @var bool Is this DocBlock (the start of) a template? */ |
|
38 | - private $isTemplateStart; |
|
39 | - |
|
40 | - /** @var bool Does this DocBlock signify the end of a DocBlock template? */ |
|
41 | - private $isTemplateEnd; |
|
42 | - |
|
43 | - /** |
|
44 | - * @param DocBlock\Tag[] $tags |
|
45 | - * @param Types\Context $context The context in which the DocBlock occurs. |
|
46 | - * @param Location $location The location within the file that this DocBlock occurs in. |
|
47 | - */ |
|
48 | - public function __construct( |
|
49 | - string $summary = '', |
|
50 | - ?DocBlock\Description $description = null, |
|
51 | - array $tags = [], |
|
52 | - ?Types\Context $context = null, |
|
53 | - ?Location $location = null, |
|
54 | - bool $isTemplateStart = false, |
|
55 | - bool $isTemplateEnd = false |
|
56 | - ) { |
|
57 | - Assert::allIsInstanceOf($tags, Tag::class); |
|
58 | - |
|
59 | - $this->summary = $summary; |
|
60 | - $this->description = $description ?: new DocBlock\Description(''); |
|
61 | - foreach ($tags as $tag) { |
|
62 | - $this->addTag($tag); |
|
63 | - } |
|
64 | - |
|
65 | - $this->context = $context; |
|
66 | - $this->location = $location; |
|
67 | - |
|
68 | - $this->isTemplateEnd = $isTemplateEnd; |
|
69 | - $this->isTemplateStart = $isTemplateStart; |
|
70 | - } |
|
71 | - |
|
72 | - public function getSummary(): string |
|
73 | - { |
|
74 | - return $this->summary; |
|
75 | - } |
|
76 | - |
|
77 | - public function getDescription(): DocBlock\Description |
|
78 | - { |
|
79 | - return $this->description; |
|
80 | - } |
|
81 | - |
|
82 | - /** |
|
83 | - * Returns the current context. |
|
84 | - */ |
|
85 | - public function getContext(): ?Types\Context |
|
86 | - { |
|
87 | - return $this->context; |
|
88 | - } |
|
89 | - |
|
90 | - /** |
|
91 | - * Returns the current location. |
|
92 | - */ |
|
93 | - public function getLocation(): ?Location |
|
94 | - { |
|
95 | - return $this->location; |
|
96 | - } |
|
97 | - |
|
98 | - /** |
|
99 | - * Returns whether this DocBlock is the start of a Template section. |
|
100 | - * |
|
101 | - * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker |
|
102 | - * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. |
|
103 | - * |
|
104 | - * An example of such an opening is: |
|
105 | - * |
|
106 | - * ``` |
|
107 | - * /**#@+ |
|
108 | - * * My DocBlock |
|
109 | - * * / |
|
110 | - * ``` |
|
111 | - * |
|
112 | - * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all |
|
113 | - * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). |
|
114 | - * |
|
115 | - * @see self::isTemplateEnd() for the check whether a closing marker was provided. |
|
116 | - */ |
|
117 | - public function isTemplateStart(): bool |
|
118 | - { |
|
119 | - return $this->isTemplateStart; |
|
120 | - } |
|
121 | - |
|
122 | - /** |
|
123 | - * Returns whether this DocBlock is the end of a Template section. |
|
124 | - * |
|
125 | - * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. |
|
126 | - */ |
|
127 | - public function isTemplateEnd(): bool |
|
128 | - { |
|
129 | - return $this->isTemplateEnd; |
|
130 | - } |
|
131 | - |
|
132 | - /** |
|
133 | - * Returns the tags for this DocBlock. |
|
134 | - * |
|
135 | - * @return Tag[] |
|
136 | - */ |
|
137 | - public function getTags(): array |
|
138 | - { |
|
139 | - return $this->tags; |
|
140 | - } |
|
141 | - |
|
142 | - /** |
|
143 | - * Returns an array of tags matching the given name. If no tags are found |
|
144 | - * an empty array is returned. |
|
145 | - * |
|
146 | - * @param string $name String to search by. |
|
147 | - * |
|
148 | - * @return Tag[] |
|
149 | - */ |
|
150 | - public function getTagsByName(string $name): array |
|
151 | - { |
|
152 | - $result = []; |
|
153 | - |
|
154 | - foreach ($this->getTags() as $tag) { |
|
155 | - if ($tag->getName() !== $name) { |
|
156 | - continue; |
|
157 | - } |
|
158 | - |
|
159 | - $result[] = $tag; |
|
160 | - } |
|
161 | - |
|
162 | - return $result; |
|
163 | - } |
|
164 | - |
|
165 | - /** |
|
166 | - * Returns an array of tags with type matching the given name. If no tags are found |
|
167 | - * an empty array is returned. |
|
168 | - * |
|
169 | - * @param string $name String to search by. |
|
170 | - * |
|
171 | - * @return TagWithType[] |
|
172 | - */ |
|
173 | - public function getTagsWithTypeByName(string $name): array |
|
174 | - { |
|
175 | - $result = []; |
|
176 | - |
|
177 | - foreach ($this->getTagsByName($name) as $tag) { |
|
178 | - if (!$tag instanceof TagWithType) { |
|
179 | - continue; |
|
180 | - } |
|
181 | - |
|
182 | - $result[] = $tag; |
|
183 | - } |
|
184 | - |
|
185 | - return $result; |
|
186 | - } |
|
187 | - |
|
188 | - /** |
|
189 | - * Checks if a tag of a certain type is present in this DocBlock. |
|
190 | - * |
|
191 | - * @param string $name Tag name to check for. |
|
192 | - */ |
|
193 | - public function hasTag(string $name): bool |
|
194 | - { |
|
195 | - foreach ($this->getTags() as $tag) { |
|
196 | - if ($tag->getName() === $name) { |
|
197 | - return true; |
|
198 | - } |
|
199 | - } |
|
200 | - |
|
201 | - return false; |
|
202 | - } |
|
203 | - |
|
204 | - /** |
|
205 | - * Remove a tag from this DocBlock. |
|
206 | - * |
|
207 | - * @param Tag $tagToRemove The tag to remove. |
|
208 | - */ |
|
209 | - public function removeTag(Tag $tagToRemove): void |
|
210 | - { |
|
211 | - foreach ($this->tags as $key => $tag) { |
|
212 | - if ($tag === $tagToRemove) { |
|
213 | - unset($this->tags[$key]); |
|
214 | - break; |
|
215 | - } |
|
216 | - } |
|
217 | - } |
|
218 | - |
|
219 | - /** |
|
220 | - * Adds a tag to this DocBlock. |
|
221 | - * |
|
222 | - * @param Tag $tag The tag to add. |
|
223 | - */ |
|
224 | - private function addTag(Tag $tag): void |
|
225 | - { |
|
226 | - $this->tags[] = $tag; |
|
227 | - } |
|
22 | + /** @var string The opening line for this docblock. */ |
|
23 | + private $summary; |
|
24 | + |
|
25 | + /** @var DocBlock\Description The actual description for this docblock. */ |
|
26 | + private $description; |
|
27 | + |
|
28 | + /** @var Tag[] An array containing all the tags in this docblock; except inline. */ |
|
29 | + private $tags = []; |
|
30 | + |
|
31 | + /** @var Types\Context|null Information about the context of this DocBlock. */ |
|
32 | + private $context; |
|
33 | + |
|
34 | + /** @var Location|null Information about the location of this DocBlock. */ |
|
35 | + private $location; |
|
36 | + |
|
37 | + /** @var bool Is this DocBlock (the start of) a template? */ |
|
38 | + private $isTemplateStart; |
|
39 | + |
|
40 | + /** @var bool Does this DocBlock signify the end of a DocBlock template? */ |
|
41 | + private $isTemplateEnd; |
|
42 | + |
|
43 | + /** |
|
44 | + * @param DocBlock\Tag[] $tags |
|
45 | + * @param Types\Context $context The context in which the DocBlock occurs. |
|
46 | + * @param Location $location The location within the file that this DocBlock occurs in. |
|
47 | + */ |
|
48 | + public function __construct( |
|
49 | + string $summary = '', |
|
50 | + ?DocBlock\Description $description = null, |
|
51 | + array $tags = [], |
|
52 | + ?Types\Context $context = null, |
|
53 | + ?Location $location = null, |
|
54 | + bool $isTemplateStart = false, |
|
55 | + bool $isTemplateEnd = false |
|
56 | + ) { |
|
57 | + Assert::allIsInstanceOf($tags, Tag::class); |
|
58 | + |
|
59 | + $this->summary = $summary; |
|
60 | + $this->description = $description ?: new DocBlock\Description(''); |
|
61 | + foreach ($tags as $tag) { |
|
62 | + $this->addTag($tag); |
|
63 | + } |
|
64 | + |
|
65 | + $this->context = $context; |
|
66 | + $this->location = $location; |
|
67 | + |
|
68 | + $this->isTemplateEnd = $isTemplateEnd; |
|
69 | + $this->isTemplateStart = $isTemplateStart; |
|
70 | + } |
|
71 | + |
|
72 | + public function getSummary(): string |
|
73 | + { |
|
74 | + return $this->summary; |
|
75 | + } |
|
76 | + |
|
77 | + public function getDescription(): DocBlock\Description |
|
78 | + { |
|
79 | + return $this->description; |
|
80 | + } |
|
81 | + |
|
82 | + /** |
|
83 | + * Returns the current context. |
|
84 | + */ |
|
85 | + public function getContext(): ?Types\Context |
|
86 | + { |
|
87 | + return $this->context; |
|
88 | + } |
|
89 | + |
|
90 | + /** |
|
91 | + * Returns the current location. |
|
92 | + */ |
|
93 | + public function getLocation(): ?Location |
|
94 | + { |
|
95 | + return $this->location; |
|
96 | + } |
|
97 | + |
|
98 | + /** |
|
99 | + * Returns whether this DocBlock is the start of a Template section. |
|
100 | + * |
|
101 | + * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker |
|
102 | + * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. |
|
103 | + * |
|
104 | + * An example of such an opening is: |
|
105 | + * |
|
106 | + * ``` |
|
107 | + * /**#@+ |
|
108 | + * * My DocBlock |
|
109 | + * * / |
|
110 | + * ``` |
|
111 | + * |
|
112 | + * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all |
|
113 | + * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). |
|
114 | + * |
|
115 | + * @see self::isTemplateEnd() for the check whether a closing marker was provided. |
|
116 | + */ |
|
117 | + public function isTemplateStart(): bool |
|
118 | + { |
|
119 | + return $this->isTemplateStart; |
|
120 | + } |
|
121 | + |
|
122 | + /** |
|
123 | + * Returns whether this DocBlock is the end of a Template section. |
|
124 | + * |
|
125 | + * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. |
|
126 | + */ |
|
127 | + public function isTemplateEnd(): bool |
|
128 | + { |
|
129 | + return $this->isTemplateEnd; |
|
130 | + } |
|
131 | + |
|
132 | + /** |
|
133 | + * Returns the tags for this DocBlock. |
|
134 | + * |
|
135 | + * @return Tag[] |
|
136 | + */ |
|
137 | + public function getTags(): array |
|
138 | + { |
|
139 | + return $this->tags; |
|
140 | + } |
|
141 | + |
|
142 | + /** |
|
143 | + * Returns an array of tags matching the given name. If no tags are found |
|
144 | + * an empty array is returned. |
|
145 | + * |
|
146 | + * @param string $name String to search by. |
|
147 | + * |
|
148 | + * @return Tag[] |
|
149 | + */ |
|
150 | + public function getTagsByName(string $name): array |
|
151 | + { |
|
152 | + $result = []; |
|
153 | + |
|
154 | + foreach ($this->getTags() as $tag) { |
|
155 | + if ($tag->getName() !== $name) { |
|
156 | + continue; |
|
157 | + } |
|
158 | + |
|
159 | + $result[] = $tag; |
|
160 | + } |
|
161 | + |
|
162 | + return $result; |
|
163 | + } |
|
164 | + |
|
165 | + /** |
|
166 | + * Returns an array of tags with type matching the given name. If no tags are found |
|
167 | + * an empty array is returned. |
|
168 | + * |
|
169 | + * @param string $name String to search by. |
|
170 | + * |
|
171 | + * @return TagWithType[] |
|
172 | + */ |
|
173 | + public function getTagsWithTypeByName(string $name): array |
|
174 | + { |
|
175 | + $result = []; |
|
176 | + |
|
177 | + foreach ($this->getTagsByName($name) as $tag) { |
|
178 | + if (!$tag instanceof TagWithType) { |
|
179 | + continue; |
|
180 | + } |
|
181 | + |
|
182 | + $result[] = $tag; |
|
183 | + } |
|
184 | + |
|
185 | + return $result; |
|
186 | + } |
|
187 | + |
|
188 | + /** |
|
189 | + * Checks if a tag of a certain type is present in this DocBlock. |
|
190 | + * |
|
191 | + * @param string $name Tag name to check for. |
|
192 | + */ |
|
193 | + public function hasTag(string $name): bool |
|
194 | + { |
|
195 | + foreach ($this->getTags() as $tag) { |
|
196 | + if ($tag->getName() === $name) { |
|
197 | + return true; |
|
198 | + } |
|
199 | + } |
|
200 | + |
|
201 | + return false; |
|
202 | + } |
|
203 | + |
|
204 | + /** |
|
205 | + * Remove a tag from this DocBlock. |
|
206 | + * |
|
207 | + * @param Tag $tagToRemove The tag to remove. |
|
208 | + */ |
|
209 | + public function removeTag(Tag $tagToRemove): void |
|
210 | + { |
|
211 | + foreach ($this->tags as $key => $tag) { |
|
212 | + if ($tag === $tagToRemove) { |
|
213 | + unset($this->tags[$key]); |
|
214 | + break; |
|
215 | + } |
|
216 | + } |
|
217 | + } |
|
218 | + |
|
219 | + /** |
|
220 | + * Adds a tag to this DocBlock. |
|
221 | + * |
|
222 | + * @param Tag $tag The tag to add. |
|
223 | + */ |
|
224 | + private function addTag(Tag $tag): void |
|
225 | + { |
|
226 | + $this->tags[] = $tag; |
|
227 | + } |
|
228 | 228 | } |
@@ -175,7 +175,7 @@ |
||
175 | 175 | $result = []; |
176 | 176 | |
177 | 177 | foreach ($this->getTagsByName($name) as $tag) { |
178 | - if (!$tag instanceof TagWithType) { |
|
178 | + if ( ! $tag instanceof TagWithType) { |
|
179 | 179 | continue; |
180 | 180 | } |
181 | 181 |