Skip to content

Commit

Permalink
Support for @pure-unless-callable-is-impure
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored and ondrejmirtes committed Sep 26, 2024
1 parent 249f15f commit 6ca22b1
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/Ast/PhpDoc/PhpDocNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ static function (PhpDocTagValueNode $value): bool {
);
}

/**
* @return PureUnlessCallableIsImpureTagValueNode[]
*/
public function getPureUnlessCallableIsImpureTagValues(string $tagName = '@pure-unless-callable-is-impure'): array
{
return array_filter(
array_column($this->getTagsByName($tagName), 'value'),
static function (PhpDocTagValueNode $value): bool {
return $value instanceof PureUnlessCallableIsImpureTagValueNode;
}
);
}

/**
* @return TemplateTagValueNode[]
Expand Down
30 changes: 30 additions & 0 deletions src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function trim;

class PureUnlessCallableIsImpureTagValueNode implements PhpDocTagValueNode
{

use NodeAttributes;

/** @var string */
public $parameterName;

/** @var string (may be empty) */
public $description;

public function __construct(string $parameterName, string $description)
{
$this->parameterName = $parameterName;
$this->description = $description;
}

public function __toString(): string
{
return trim("{$this->parameterName} {$this->description}");
}

}
12 changes: 12 additions & 0 deletions src/Parser/PhpDocParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\Ph
$tagValue = $this->parseParamClosureThisTagValue($tokens);
break;

case '@pure-unless-callable-is-impure':
case '@phpstan-pure-unless-callable-is-impure':
$tagValue = $this->parsePureUnlessCallableIsImpureTagValue($tokens);
break;

case '@var':
case '@phpstan-var':
case '@psalm-var':
Expand Down Expand Up @@ -919,6 +924,13 @@ private function parseParamClosureThisTagValue(TokenIterator $tokens): Ast\PhpDo
return new Ast\PhpDoc\ParamClosureThisTagValueNode($type, $parameterName, $description);
}

private function parsePureUnlessCallableIsImpureTagValue(TokenIterator $tokens): Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode
{
$parameterName = $this->parseRequiredVariableName($tokens);
$description = $this->parseOptionalDescription($tokens);

return new Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode($parameterName, $description);
}

private function parseVarTagValue(TokenIterator $tokens): Ast\PhpDoc\VarTagValueNode
{
Expand Down
4 changes: 4 additions & 0 deletions src/Printer/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireExtendsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireImplementsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
Expand Down Expand Up @@ -322,6 +323,9 @@ private function printTagValue(PhpDocTagValueNode $node): string
if ($node instanceof ParamClosureThisTagValueNode) {
return trim("{$node->type} {$node->parameterName} {$node->description}");
}
if ($node instanceof PureUnlessCallableIsImpureTagValueNode) {
return trim("{$node->parameterName} {$node->description}");
}
if ($node instanceof PropertyTagValueNode) {
$type = $this->printType($node->type);
return trim("{$type} {$node->propertyName} {$node->description}");
Expand Down
33 changes: 33 additions & 0 deletions tests/PHPStan/Parser/PhpDocParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireExtendsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireImplementsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
Expand Down Expand Up @@ -104,6 +105,7 @@ protected function setUp(): void
* @dataProvider provideParamLaterInvokedCallableTagsData
* @dataProvider provideTypelessParamTagsData
* @dataProvider provideParamClosureThisTagsData
* @dataProvider providePureUnlessCallableIsImpureTagsData
* @dataProvider provideVarTagsData
* @dataProvider provideReturnTagsData
* @dataProvider provideThrowsTagsData
Expand Down Expand Up @@ -736,6 +738,37 @@ public function provideParamClosureThisTagsData(): Iterator
];
}

public function providePureUnlessCallableIsImpureTagsData(): Iterator
{
yield [
'OK',
'/** @pure-unless-callable-is-impure $foo */',
new PhpDocNode([
new PhpDocTagNode(
'@pure-unless-callable-is-impure',
new PureUnlessCallableIsImpureTagValueNode(
'$foo',
''
)
),
]),
];

yield [
'OK with description',
'/** @pure-unless-callable-is-impure $foo test two three */',
new PhpDocNode([
new PhpDocTagNode(
'@pure-unless-callable-is-impure',
new PureUnlessCallableIsImpureTagValueNode(
'$foo',
'test two three'
)
),
]),
];
}

public function provideVarTagsData(): Iterator
{
yield [
Expand Down
19 changes: 19 additions & 0 deletions tests/PHPStan/Printer/PrinterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
Expand Down Expand Up @@ -1782,6 +1783,24 @@ public function enterNode(Node $node)
},
];

yield [
'/** @pure-unless-callable-is-impure $foo test */',
'/** @pure-unless-callable-is-impure $bar foo */',
new class extends AbstractNodeVisitor {

public function enterNode(Node $node)
{
if ($node instanceof PureUnlessCallableIsImpureTagValueNode) {
$node->parameterName = '$bar';
$node->description = 'foo';
}

return $node;
}

},
];

yield [
'/** @return Foo[abc] */',
'/** @return self::FOO[abc] */',
Expand Down

0 comments on commit 6ca22b1

Please sign in to comment.