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: /**
136: * @return TemplateTagValueNode[]
137: */
138: public function getTemplateTagValues(string $tagName = '@template'): array
139: {
140: return array_filter(
141: array_column($this->getTagsByName($tagName), 'value'),
142: static function (PhpDocTagValueNode $value): bool {
143: return $value instanceof TemplateTagValueNode;
144: }
145: );
146: }
147:
148:
149: /**
150: * @return ExtendsTagValueNode[]
151: */
152: public function getExtendsTagValues(string $tagName = '@extends'): array
153: {
154: return array_filter(
155: array_column($this->getTagsByName($tagName), 'value'),
156: static function (PhpDocTagValueNode $value): bool {
157: return $value instanceof ExtendsTagValueNode;
158: }
159: );
160: }
161:
162:
163: /**
164: * @return ImplementsTagValueNode[]
165: */
166: public function getImplementsTagValues(string $tagName = '@implements'): array
167: {
168: return array_filter(
169: array_column($this->getTagsByName($tagName), 'value'),
170: static function (PhpDocTagValueNode $value): bool {
171: return $value instanceof ImplementsTagValueNode;
172: }
173: );
174: }
175:
176:
177: /**
178: * @return UsesTagValueNode[]
179: */
180: public function getUsesTagValues(string $tagName = '@use'): array
181: {
182: return array_filter(
183: array_column($this->getTagsByName($tagName), 'value'),
184: static function (PhpDocTagValueNode $value): bool {
185: return $value instanceof UsesTagValueNode;
186: }
187: );
188: }
189:
190:
191: /**
192: * @return ReturnTagValueNode[]
193: */
194: public function getReturnTagValues(string $tagName = '@return'): array
195: {
196: return array_filter(
197: array_column($this->getTagsByName($tagName), 'value'),
198: static function (PhpDocTagValueNode $value): bool {
199: return $value instanceof ReturnTagValueNode;
200: }
201: );
202: }
203:
204:
205: /**
206: * @return ThrowsTagValueNode[]
207: */
208: public function getThrowsTagValues(string $tagName = '@throws'): array
209: {
210: return array_filter(
211: array_column($this->getTagsByName($tagName), 'value'),
212: static function (PhpDocTagValueNode $value): bool {
213: return $value instanceof ThrowsTagValueNode;
214: }
215: );
216: }
217:
218:
219: /**
220: * @return MixinTagValueNode[]
221: */
222: public function getMixinTagValues(string $tagName = '@mixin'): array
223: {
224: return array_filter(
225: array_column($this->getTagsByName($tagName), 'value'),
226: static function (PhpDocTagValueNode $value): bool {
227: return $value instanceof MixinTagValueNode;
228: }
229: );
230: }
231:
232: /**
233: * @return RequireExtendsTagValueNode[]
234: */
235: public function getRequireExtendsTagValues(string $tagName = '@phpstan-require-extends'): array
236: {
237: return array_filter(
238: array_column($this->getTagsByName($tagName), 'value'),
239: static function (PhpDocTagValueNode $value): bool {
240: return $value instanceof RequireExtendsTagValueNode;
241: }
242: );
243: }
244:
245: /**
246: * @return RequireImplementsTagValueNode[]
247: */
248: public function getRequireImplementsTagValues(string $tagName = '@phpstan-require-implements'): array
249: {
250: return array_filter(
251: array_column($this->getTagsByName($tagName), 'value'),
252: static function (PhpDocTagValueNode $value): bool {
253: return $value instanceof RequireImplementsTagValueNode;
254: }
255: );
256: }
257:
258: /**
259: * @return DeprecatedTagValueNode[]
260: */
261: public function getDeprecatedTagValues(): array
262: {
263: return array_filter(
264: array_column($this->getTagsByName('@deprecated'), 'value'),
265: static function (PhpDocTagValueNode $value): bool {
266: return $value instanceof DeprecatedTagValueNode;
267: }
268: );
269: }
270:
271:
272: /**
273: * @return PropertyTagValueNode[]
274: */
275: public function getPropertyTagValues(string $tagName = '@property'): array
276: {
277: return array_filter(
278: array_column($this->getTagsByName($tagName), 'value'),
279: static function (PhpDocTagValueNode $value): bool {
280: return $value instanceof PropertyTagValueNode;
281: }
282: );
283: }
284:
285:
286: /**
287: * @return PropertyTagValueNode[]
288: */
289: public function getPropertyReadTagValues(string $tagName = '@property-read'): array
290: {
291: return array_filter(
292: array_column($this->getTagsByName($tagName), 'value'),
293: static function (PhpDocTagValueNode $value): bool {
294: return $value instanceof PropertyTagValueNode;
295: }
296: );
297: }
298:
299:
300: /**
301: * @return PropertyTagValueNode[]
302: */
303: public function getPropertyWriteTagValues(string $tagName = '@property-write'): array
304: {
305: return array_filter(
306: array_column($this->getTagsByName($tagName), 'value'),
307: static function (PhpDocTagValueNode $value): bool {
308: return $value instanceof PropertyTagValueNode;
309: }
310: );
311: }
312:
313:
314: /**
315: * @return MethodTagValueNode[]
316: */
317: public function getMethodTagValues(string $tagName = '@method'): array
318: {
319: return array_filter(
320: array_column($this->getTagsByName($tagName), 'value'),
321: static function (PhpDocTagValueNode $value): bool {
322: return $value instanceof MethodTagValueNode;
323: }
324: );
325: }
326:
327:
328: /**
329: * @return TypeAliasTagValueNode[]
330: */
331: public function getTypeAliasTagValues(string $tagName = '@phpstan-type'): array
332: {
333: return array_filter(
334: array_column($this->getTagsByName($tagName), 'value'),
335: static function (PhpDocTagValueNode $value): bool {
336: return $value instanceof TypeAliasTagValueNode;
337: }
338: );
339: }
340:
341:
342: /**
343: * @return TypeAliasImportTagValueNode[]
344: */
345: public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type'): array
346: {
347: return array_filter(
348: array_column($this->getTagsByName($tagName), 'value'),
349: static function (PhpDocTagValueNode $value): bool {
350: return $value instanceof TypeAliasImportTagValueNode;
351: }
352: );
353: }
354:
355:
356: /**
357: * @return AssertTagValueNode[]
358: */
359: public function getAssertTagValues(string $tagName = '@phpstan-assert'): array
360: {
361: return array_filter(
362: array_column($this->getTagsByName($tagName), 'value'),
363: static function (PhpDocTagValueNode $value): bool {
364: return $value instanceof AssertTagValueNode;
365: }
366: );
367: }
368:
369:
370: /**
371: * @return AssertTagPropertyValueNode[]
372: */
373: public function getAssertPropertyTagValues(string $tagName = '@phpstan-assert'): array
374: {
375: return array_filter(
376: array_column($this->getTagsByName($tagName), 'value'),
377: static function (PhpDocTagValueNode $value): bool {
378: return $value instanceof AssertTagPropertyValueNode;
379: }
380: );
381: }
382:
383:
384: /**
385: * @return AssertTagMethodValueNode[]
386: */
387: public function getAssertMethodTagValues(string $tagName = '@phpstan-assert'): array
388: {
389: return array_filter(
390: array_column($this->getTagsByName($tagName), 'value'),
391: static function (PhpDocTagValueNode $value): bool {
392: return $value instanceof AssertTagMethodValueNode;
393: }
394: );
395: }
396:
397:
398: /**
399: * @return SelfOutTagValueNode[]
400: */
401: public function getSelfOutTypeTagValues(string $tagName = '@phpstan-this-out'): array
402: {
403: return array_filter(
404: array_column($this->getTagsByName($tagName), 'value'),
405: static function (PhpDocTagValueNode $value): bool {
406: return $value instanceof SelfOutTagValueNode;
407: }
408: );
409: }
410:
411:
412: /**
413: * @return ParamOutTagValueNode[]
414: */
415: public function getParamOutTypeTagValues(string $tagName = '@param-out'): array
416: {
417: return array_filter(
418: array_column($this->getTagsByName($tagName), 'value'),
419: static function (PhpDocTagValueNode $value): bool {
420: return $value instanceof ParamOutTagValueNode;
421: }
422: );
423: }
424:
425:
426: public function __toString(): string
427: {
428: $children = array_map(
429: static function (PhpDocChildNode $child): string {
430: $s = (string) $child;
431: return $s === '' ? '' : ' ' . $s;
432: },
433: $this->children
434: );
435: return "/**\n *" . implode("\n *", $children) . "\n */";
436: }
437:
438: }
439: