1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\PhpDocParser\Ast\PhpDoc;
4:
5: use PHPStan\PhpDocParser\Ast\Node;
6: use PHPStan\PhpDocParser\Ast\NodeAttributes;
7: use function array_column;
8: use function array_filter;
9: use function array_map;
10: use function implode;
11:
12: class PhpDocNode implements Node
13: {
14:
15: use NodeAttributes;
16:
17: /** @var PhpDocChildNode[] */
18: public $children;
19:
20: /**
21: * @param PhpDocChildNode[] $children
22: */
23: public function __construct(array $children)
24: {
25: $this->children = $children;
26: }
27:
28:
29: /**
30: * @return PhpDocTagNode[]
31: */
32: public function getTags(): array
33: {
34: return array_filter($this->children, static function (PhpDocChildNode $child): bool {
35: return $child instanceof PhpDocTagNode;
36: });
37: }
38:
39:
40: /**
41: * @return PhpDocTagNode[]
42: */
43: public function getTagsByName(string $tagName): array
44: {
45: return array_filter($this->getTags(), static function (PhpDocTagNode $tag) use ($tagName): bool {
46: return $tag->name === $tagName;
47: });
48: }
49:
50:
51: /**
52: * @return VarTagValueNode[]
53: */
54: public function getVarTagValues(string $tagName = '@var'): array
55: {
56: return array_filter(
57: array_column($this->getTagsByName($tagName), 'value'),
58: static function (PhpDocTagValueNode $value): bool {
59: return $value instanceof VarTagValueNode;
60: }
61: );
62: }
63:
64:
65: /**
66: * @return ParamTagValueNode[]
67: */
68: public function getParamTagValues(string $tagName = '@param'): array
69: {
70: return array_filter(
71: array_column($this->getTagsByName($tagName), 'value'),
72: static function (PhpDocTagValueNode $value): bool {
73: return $value instanceof ParamTagValueNode;
74: }
75: );
76: }
77:
78:
79: /**
80: * @return TypelessParamTagValueNode[]
81: */
82: public function getTypelessParamTagValues(string $tagName = '@param'): array
83: {
84: return array_filter(
85: array_column($this->getTagsByName($tagName), 'value'),
86: static function (PhpDocTagValueNode $value): bool {
87: return $value instanceof TypelessParamTagValueNode;
88: }
89: );
90: }
91:
92:
93: /**
94: * @return ParamImmediatelyInvokedCallableTagValueNode[]
95: */
96: public function getParamImmediatelyInvokedCallableTagValues(string $tagName = '@param-immediately-invoked-callable'): array
97: {
98: return array_filter(
99: array_column($this->getTagsByName($tagName), 'value'),
100: static function (PhpDocTagValueNode $value): bool {
101: return $value instanceof ParamImmediatelyInvokedCallableTagValueNode;
102: }
103: );
104: }
105:
106:
107: /**
108: * @return ParamLaterInvokedCallableTagValueNode[]
109: */
110: public function getParamLaterInvokedCallableTagValues(string $tagName = '@param-later-invoked-callable'): array
111: {
112: return array_filter(
113: array_column($this->getTagsByName($tagName), 'value'),
114: static function (PhpDocTagValueNode $value): bool {
115: return $value instanceof ParamLaterInvokedCallableTagValueNode;
116: }
117: );
118: }
119:
120:
121: /**
122: * @return ParamClosureThisTagValueNode[]
123: */
124: public function getParamClosureThisTagValues(string $tagName = '@param-closure-this'): array
125: {
126: return array_filter(
127: array_column($this->getTagsByName($tagName), 'value'),
128: static function (PhpDocTagValueNode $value): bool {
129: return $value instanceof ParamClosureThisTagValueNode;
130: }
131: );
132: }
133:
134: /**
135: * @return PureUnlessCallableIsImpureTagValueNode[]
136: */
137: public function getPureUnlessCallableIsImpureTagValues(string $tagName = '@pure-unless-callable-is-impure'): array
138: {
139: return array_filter(
140: array_column($this->getTagsByName($tagName), 'value'),
141: static function (PhpDocTagValueNode $value): bool {
142: return $value instanceof PureUnlessCallableIsImpureTagValueNode;
143: }
144: );
145: }
146:
147: /**
148: * @return TemplateTagValueNode[]
149: */
150: public function getTemplateTagValues(string $tagName = '@template'): array
151: {
152: return array_filter(
153: array_column($this->getTagsByName($tagName), 'value'),
154: static function (PhpDocTagValueNode $value): bool {
155: return $value instanceof TemplateTagValueNode;
156: }
157: );
158: }
159:
160:
161: /**
162: * @return ExtendsTagValueNode[]
163: */
164: public function getExtendsTagValues(string $tagName = '@extends'): array
165: {
166: return array_filter(
167: array_column($this->getTagsByName($tagName), 'value'),
168: static function (PhpDocTagValueNode $value): bool {
169: return $value instanceof ExtendsTagValueNode;
170: }
171: );
172: }
173:
174:
175: /**
176: * @return ImplementsTagValueNode[]
177: */
178: public function getImplementsTagValues(string $tagName = '@implements'): array
179: {
180: return array_filter(
181: array_column($this->getTagsByName($tagName), 'value'),
182: static function (PhpDocTagValueNode $value): bool {
183: return $value instanceof ImplementsTagValueNode;
184: }
185: );
186: }
187:
188:
189: /**
190: * @return UsesTagValueNode[]
191: */
192: public function getUsesTagValues(string $tagName = '@use'): array
193: {
194: return array_filter(
195: array_column($this->getTagsByName($tagName), 'value'),
196: static function (PhpDocTagValueNode $value): bool {
197: return $value instanceof UsesTagValueNode;
198: }
199: );
200: }
201:
202:
203: /**
204: * @return ReturnTagValueNode[]
205: */
206: public function getReturnTagValues(string $tagName = '@return'): array
207: {
208: return array_filter(
209: array_column($this->getTagsByName($tagName), 'value'),
210: static function (PhpDocTagValueNode $value): bool {
211: return $value instanceof ReturnTagValueNode;
212: }
213: );
214: }
215:
216:
217: /**
218: * @return ThrowsTagValueNode[]
219: */
220: public function getThrowsTagValues(string $tagName = '@throws'): array
221: {
222: return array_filter(
223: array_column($this->getTagsByName($tagName), 'value'),
224: static function (PhpDocTagValueNode $value): bool {
225: return $value instanceof ThrowsTagValueNode;
226: }
227: );
228: }
229:
230:
231: /**
232: * @return MixinTagValueNode[]
233: */
234: public function getMixinTagValues(string $tagName = '@mixin'): array
235: {
236: return array_filter(
237: array_column($this->getTagsByName($tagName), 'value'),
238: static function (PhpDocTagValueNode $value): bool {
239: return $value instanceof MixinTagValueNode;
240: }
241: );
242: }
243:
244: /**
245: * @return RequireExtendsTagValueNode[]
246: */
247: public function getRequireExtendsTagValues(string $tagName = '@phpstan-require-extends'): array
248: {
249: return array_filter(
250: array_column($this->getTagsByName($tagName), 'value'),
251: static function (PhpDocTagValueNode $value): bool {
252: return $value instanceof RequireExtendsTagValueNode;
253: }
254: );
255: }
256:
257: /**
258: * @return RequireImplementsTagValueNode[]
259: */
260: public function getRequireImplementsTagValues(string $tagName = '@phpstan-require-implements'): array
261: {
262: return array_filter(
263: array_column($this->getTagsByName($tagName), 'value'),
264: static function (PhpDocTagValueNode $value): bool {
265: return $value instanceof RequireImplementsTagValueNode;
266: }
267: );
268: }
269:
270: /**
271: * @return DeprecatedTagValueNode[]
272: */
273: public function getDeprecatedTagValues(): array
274: {
275: return array_filter(
276: array_column($this->getTagsByName('@deprecated'), 'value'),
277: static function (PhpDocTagValueNode $value): bool {
278: return $value instanceof DeprecatedTagValueNode;
279: }
280: );
281: }
282:
283:
284: /**
285: * @return PropertyTagValueNode[]
286: */
287: public function getPropertyTagValues(string $tagName = '@property'): array
288: {
289: return array_filter(
290: array_column($this->getTagsByName($tagName), 'value'),
291: static function (PhpDocTagValueNode $value): bool {
292: return $value instanceof PropertyTagValueNode;
293: }
294: );
295: }
296:
297:
298: /**
299: * @return PropertyTagValueNode[]
300: */
301: public function getPropertyReadTagValues(string $tagName = '@property-read'): array
302: {
303: return array_filter(
304: array_column($this->getTagsByName($tagName), 'value'),
305: static function (PhpDocTagValueNode $value): bool {
306: return $value instanceof PropertyTagValueNode;
307: }
308: );
309: }
310:
311:
312: /**
313: * @return PropertyTagValueNode[]
314: */
315: public function getPropertyWriteTagValues(string $tagName = '@property-write'): array
316: {
317: return array_filter(
318: array_column($this->getTagsByName($tagName), 'value'),
319: static function (PhpDocTagValueNode $value): bool {
320: return $value instanceof PropertyTagValueNode;
321: }
322: );
323: }
324:
325:
326: /**
327: * @return MethodTagValueNode[]
328: */
329: public function getMethodTagValues(string $tagName = '@method'): array
330: {
331: return array_filter(
332: array_column($this->getTagsByName($tagName), 'value'),
333: static function (PhpDocTagValueNode $value): bool {
334: return $value instanceof MethodTagValueNode;
335: }
336: );
337: }
338:
339:
340: /**
341: * @return TypeAliasTagValueNode[]
342: */
343: public function getTypeAliasTagValues(string $tagName = '@phpstan-type'): array
344: {
345: return array_filter(
346: array_column($this->getTagsByName($tagName), 'value'),
347: static function (PhpDocTagValueNode $value): bool {
348: return $value instanceof TypeAliasTagValueNode;
349: }
350: );
351: }
352:
353:
354: /**
355: * @return TypeAliasImportTagValueNode[]
356: */
357: public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type'): array
358: {
359: return array_filter(
360: array_column($this->getTagsByName($tagName), 'value'),
361: static function (PhpDocTagValueNode $value): bool {
362: return $value instanceof TypeAliasImportTagValueNode;
363: }
364: );
365: }
366:
367:
368: /**
369: * @return AssertTagValueNode[]
370: */
371: public function getAssertTagValues(string $tagName = '@phpstan-assert'): array
372: {
373: return array_filter(
374: array_column($this->getTagsByName($tagName), 'value'),
375: static function (PhpDocTagValueNode $value): bool {
376: return $value instanceof AssertTagValueNode;
377: }
378: );
379: }
380:
381:
382: /**
383: * @return AssertTagPropertyValueNode[]
384: */
385: public function getAssertPropertyTagValues(string $tagName = '@phpstan-assert'): array
386: {
387: return array_filter(
388: array_column($this->getTagsByName($tagName), 'value'),
389: static function (PhpDocTagValueNode $value): bool {
390: return $value instanceof AssertTagPropertyValueNode;
391: }
392: );
393: }
394:
395:
396: /**
397: * @return AssertTagMethodValueNode[]
398: */
399: public function getAssertMethodTagValues(string $tagName = '@phpstan-assert'): array
400: {
401: return array_filter(
402: array_column($this->getTagsByName($tagName), 'value'),
403: static function (PhpDocTagValueNode $value): bool {
404: return $value instanceof AssertTagMethodValueNode;
405: }
406: );
407: }
408:
409:
410: /**
411: * @return SelfOutTagValueNode[]
412: */
413: public function getSelfOutTypeTagValues(string $tagName = '@phpstan-this-out'): array
414: {
415: return array_filter(
416: array_column($this->getTagsByName($tagName), 'value'),
417: static function (PhpDocTagValueNode $value): bool {
418: return $value instanceof SelfOutTagValueNode;
419: }
420: );
421: }
422:
423:
424: /**
425: * @return ParamOutTagValueNode[]
426: */
427: public function getParamOutTypeTagValues(string $tagName = '@param-out'): array
428: {
429: return array_filter(
430: array_column($this->getTagsByName($tagName), 'value'),
431: static function (PhpDocTagValueNode $value): bool {
432: return $value instanceof ParamOutTagValueNode;
433: }
434: );
435: }
436:
437:
438: public function __toString(): string
439: {
440: $children = array_map(
441: static function (PhpDocChildNode $child): string {
442: $s = (string) $child;
443: return $s === '' ? '' : ' ' . $s;
444: },
445: $this->children
446: );
447: return "/**\n *" . implode("\n *", $children) . "\n */";
448: }
449:
450: }
451: