Skip to content

Commit bc2e06a

Browse files
Add ParamOut attribute
1 parent fada1e1 commit bc2e06a

6 files changed

+183
-21
lines changed

README.md

+20-19
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,26 @@ This extension works by interacting with the parser that PHPStan uses to parse t
9494

9595
These are the available attributes and their corresponding PHPDoc annotations:
9696

97-
| Attribute | PHPDoc Annotations |
98-
|-------------------------------------------------------------------------------------------------------------------|--------------------------------|
99-
| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` |
100-
| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` |
101-
| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` |
102-
| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` |
103-
| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` |
104-
| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` |
105-
| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` |
106-
| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` |
107-
| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` |
108-
| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` |
109-
| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` |
110-
| [TemplateContravariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateContravariant.md) | `@template-contravariant` |
111-
| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` |
112-
| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` |
113-
| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` |
114-
| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` |
115-
| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` |
97+
| Attribute | PHPDoc Annotations |
98+
|-------------------------------------------------------------------------------------------------------------------|--------------------------------------|
99+
| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` |
100+
| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` |
101+
| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` |
102+
| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` |
103+
| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` |
104+
| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` |
105+
| [ParamOut](https://github.com/php-static-analysis/attributes/blob/main/doc/ParamOut.md) | `@param-out` |
106+
| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` |
107+
| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` |
108+
| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` |
109+
| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` |
110+
| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` |
111+
| [TemplateContravariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateContravariant.md) | `@template-contravariant` |
112+
| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` |
113+
| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` |
114+
| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` |
115+
| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` |
116+
| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` |
116117

117118

118119

composer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
"prefer-stable": true,
2525
"require": {
2626
"php": ">=8.0",
27-
"php-static-analysis/attributes": "^0.1.11 || dev-main",
28-
"php-static-analysis/node-visitor": "^0.1.11 || dev-main",
27+
"php-static-analysis/attributes": "^0.1.12 || dev-main",
28+
"php-static-analysis/node-visitor": "^0.1.12 || dev-main",
2929
"phpstan/phpstan": "^1.8"
3030
},
3131
"require-dev": {

tests/ParamOutAttributeTest.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PHPStanExtension;
4+
5+
class ParamOutAttributeTest extends BaseAttributeTestCase
6+
{
7+
public function testMethodParamOutAttribute(): void
8+
{
9+
$errors = $this->analyse(__DIR__ . '/data/ParamOut/MethodParamOutAttribute.php');
10+
$this->assertCount(0, $errors);
11+
}
12+
13+
public function testFunctionParamOutAttribute(): void
14+
{
15+
$errors = $this->analyse(__DIR__ . '/data/ParamOut/FunctionParamOutAttribute.php');
16+
$this->assertCount(0, $errors);
17+
}
18+
19+
public function testInvalidMethodParamOutAttribute(): void
20+
{
21+
$errors = $this->analyse(__DIR__ . '/data/ParamOut/InvalidMethodParamOutAttribute.php');
22+
23+
$expectedErrors = [
24+
'PHPDoc tag @param-out has invalid value (): Unexpected token "\n ", expected type at offset 17' => 9,
25+
'Parameter #1 ...$params of attribute class PhpStaticAnalysis\Attributes\ParamOut constructor expects string, int given.' => 9,
26+
'PHPDoc tag @param-out has invalid value (string): Unexpected token "\n ", expected variable at offset 24' => 15,
27+
'PHPDoc tag @param-out has invalid value (count($a) $name): Unexpected token "(", expected variable at offset 23' => 21,
28+
'Attribute class PhpStaticAnalysis\Attributes\ParamOut does not have the property target.' => 27,
29+
];
30+
31+
$this->checkExpectedErrors($errors, $expectedErrors);
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PHPStanExtension\data\ParamOut;
4+
5+
use PhpStaticAnalysis\Attributes\ParamOut;
6+
7+
#[ParamOut(names: 'int')]
8+
function setNames(mixed &$names): void
9+
{
10+
$names = 1;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PHPStanExtension\data\ParamOut;
4+
5+
use PhpStaticAnalysis\Attributes\ParamOut;
6+
7+
class InvalidMethodParamOutAttribute
8+
{
9+
#[ParamOut(0)]
10+
public function setName(mixed &$name): void
11+
{
12+
$name = 1;
13+
}
14+
15+
#[ParamOut('string')]
16+
public function setOtherName(mixed &$name): void
17+
{
18+
$name = 1;
19+
}
20+
21+
#[ParamOut(name: 'count($a)')]
22+
public function setAnotherName(mixed &$name): void
23+
{
24+
$name = 1;
25+
}
26+
27+
#[ParamOut(property: 'string')]
28+
public string $property;
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PHPStanExtension\data\ParamOut;
4+
5+
use PhpStaticAnalysis\Attributes\ParamOut;
6+
7+
class MethodParamOutAttribute
8+
{
9+
#[ParamOut(names: 'int')] // we specify the type of the reference parameter after running the function
10+
public function setNames(mixed &$names): void
11+
{
12+
$names = 1;
13+
}
14+
15+
#[ParamOut('int $names')]
16+
public function setUnnamedNames(mixed &$names): void
17+
{
18+
$names = 1;
19+
}
20+
21+
/**
22+
* @deprecated
23+
*/
24+
#[ParamOut(names: 'int')]
25+
public function setMoreNames(mixed &$names): void
26+
{
27+
$names = 1;
28+
}
29+
30+
/**
31+
* @param-out string $names
32+
*/
33+
#[ParamOut(names: 'int')]
34+
public function setEvenMoreNames(mixed &$names): void
35+
{
36+
$names = 1;
37+
}
38+
39+
#[ParamOut(
40+
names1: 'int',
41+
names2: 'int'
42+
)]
43+
public function setTwoNames(mixed &$names1, mixed &$names2): void
44+
{
45+
$names1 = 1;
46+
$names2 = 2;
47+
}
48+
49+
#[ParamOut(names1: 'int')]
50+
#[ParamOut(names2: 'int')]
51+
public function setTwoMoreNames(mixed &$names1, mixed &$names2): void
52+
{
53+
$names1 = 1;
54+
$names2 = 2;
55+
}
56+
57+
/**
58+
* @param-out int $names
59+
*/
60+
public function setNamesAndNames(mixed &$names): void
61+
{
62+
$names = 1;
63+
}
64+
65+
public function setNamesInParamOut(
66+
#[ParamOut('int')]
67+
mixed &$names
68+
): void {
69+
$names = 1;
70+
}
71+
72+
public function setNamesInParamOutWithName(
73+
#[ParamOut(names: 'int')]
74+
mixed &$names
75+
): void {
76+
$names = 1;
77+
}
78+
79+
public function setNamesInTwoParamOuts(
80+
#[ParamOut('int')]
81+
mixed &$names1,
82+
#[ParamOut('int')]
83+
mixed &$names2
84+
): void {
85+
$names1 = 1;
86+
$names2 = 2;
87+
}
88+
}

0 commit comments

Comments
 (0)