Skip to content

Commit 75d8995

Browse files
Add ParamOut attribute
1 parent d0538e5 commit 75d8995

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"require": {
2626
"php": ">=8.0",
2727
"nikic/php-parser": "^4 || ^5",
28-
"php-static-analysis/attributes": "^0.1.11 || dev-main"
28+
"php-static-analysis/attributes": "^0.1.12 || dev-main"
2929
},
3030
"require-dev": {
3131
"php-static-analysis/phpstan-extension": "dev-main",

src/AttributeNodeVisitor.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PhpStaticAnalysis\Attributes\Method;
1818
use PhpStaticAnalysis\Attributes\Mixin;
1919
use PhpStaticAnalysis\Attributes\Param;
20+
use PhpStaticAnalysis\Attributes\ParamOut;
2021
use PhpStaticAnalysis\Attributes\Property;
2122
use PhpStaticAnalysis\Attributes\PropertyRead;
2223
use PhpStaticAnalysis\Attributes\PropertyWrite;
@@ -74,6 +75,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
7475
Deprecated::class,
7576
Internal::class,
7677
Param::class,
78+
ParamOut::class,
7779
Returns::class,
7880
Template::class,
7981
Type::class,
@@ -82,6 +84,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
8284
Deprecated::class,
8385
Internal::class,
8486
Param::class,
87+
ParamOut::class,
8588
Returns::class,
8689
Template::class,
8790
Type::class,
@@ -126,6 +129,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
126129
'Method' => Method::class,
127130
'Mixin' => Mixin::class,
128131
'Param' => Param::class,
132+
'ParamOut' => ParamOut::class,
129133
'Property' => Property::class,
130134
'PropertyRead' => PropertyRead::class,
131135
'PropertyWrite' => PropertyWrite::class,
@@ -158,6 +162,9 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
158162
Param::class => [
159163
'all' => 'param',
160164
],
165+
ParamOut::class => [
166+
'all' => 'param-out',
167+
],
161168
Property::class => [
162169
Stmt\Class_::class => 'property',
163170
Stmt\Property::class => 'var',
@@ -216,6 +223,9 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
216223
Param::class => [
217224
'all' => self::ARGS_MANY_WITH_NAME,
218225
],
226+
ParamOut::class => [
227+
'all' => self::ARGS_MANY_WITH_NAME,
228+
],
219229
Property::class => [
220230
Stmt\Class_::class => self::ARGS_MANY_WITH_NAME,
221231
Stmt\Property::class => self::ARGS_ONE,
@@ -430,7 +440,7 @@ private function getParamTagsFromParams(Stmt\ClassMethod|Stmt\Function_ $node):
430440
foreach ($attributes as $attribute) {
431441
$attributeName = $attribute->name->toString();
432442
$attributeName = self::SHORT_NAME_TO_FQN[$attributeName] ?? $attributeName;
433-
if ($attributeName === Param::class) {
443+
if ($attributeName === Param::class || $attributeName === ParamOut::class) {
434444
$args = $attribute->args;
435445
$tagCreated = false;
436446
if (isset($args[0])) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\NodeVisitor;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Attribute;
7+
use PhpParser\Node\AttributeGroup;
8+
use PhpParser\Node\Identifier;
9+
use PhpParser\Node\Name\FullyQualified;
10+
use PhpStaticAnalysis\Attributes\ParamOut;
11+
12+
class ParamOutAttributeNodeVisitorTest extends AttributeNodeVisitorTestBase
13+
{
14+
public function testAddsParamOutPHPDoc(): void
15+
{
16+
$node = new Node\Stmt\ClassMethod('Test');
17+
$this->addParamOutAttributesToNode($node);
18+
$this->nodeVisitor->enterNode($node);
19+
$docText = $this->getDocText($node);
20+
$this->assertEquals("/**\n * @param-out string \$param\n */", $docText);
21+
}
22+
23+
public function testAddsSeveralParamOutPHPDocs(): void
24+
{
25+
$node = new Node\Stmt\ClassMethod('Test');
26+
$this->addParamOutAttributesToNode($node, 2);
27+
$this->nodeVisitor->enterNode($node);
28+
$docText = $this->getDocText($node);
29+
$this->assertEquals("/**\n * @param-out string \$param\n * @param-out string \$param\n */", $docText);
30+
}
31+
32+
public function testAddsMultipleParamOutPHPDocs(): void
33+
{
34+
$node = new Node\Stmt\ClassMethod('Test');
35+
$this->addParamOutAttributesToNode($node);
36+
$this->addParamOutAttributesToNode($node);
37+
$this->nodeVisitor->enterNode($node);
38+
$docText = $this->getDocText($node);
39+
$this->assertEquals("/**\n * @param-out string \$param\n * @param-out string \$param\n */", $docText);
40+
}
41+
42+
public function testAddsParamOutPHPDocToParam(): void
43+
{
44+
$node = new Node\Stmt\ClassMethod('Test');
45+
$this->addParamOutAttributeToParamNode($node);
46+
$this->nodeVisitor->enterNode($node);
47+
$docText = $this->getDocText($node);
48+
$this->assertEquals("/**\n * @param-out string \$param\n */", $docText);
49+
}
50+
51+
private function addParamOutAttributesToNode(Node\Stmt\ClassMethod $node, int $num = 1): void
52+
{
53+
$name = new Identifier('param');
54+
$value = new Node\Scalar\String_('string');
55+
$args = [];
56+
for ($i = 0; $i < $num; $i++) {
57+
$args[] = new Node\Arg($value, name: $name);
58+
}
59+
$attributeName = new FullyQualified(ParamOut::class);
60+
$attribute = new Attribute($attributeName, $args);
61+
$node->attrGroups = array_merge($node->attrGroups, [new AttributeGroup([$attribute])]);
62+
}
63+
64+
private function addParamOutAttributeToParamNode(Node\Stmt\ClassMethod $node): void
65+
{
66+
$var = new Node\Expr\Variable('param');
67+
$parameter = new Node\Param($var);
68+
$value = new Node\Scalar\String_('string');
69+
$args = [new Node\Arg($value)];
70+
$attributeName = new FullyQualified(ParamOut::class);
71+
$attribute = new Attribute($attributeName, $args);
72+
$parameter->attrGroups = array_merge($node->attrGroups, [new AttributeGroup([$attribute])]);
73+
$node->params = [$parameter];
74+
}
75+
}

0 commit comments

Comments
 (0)