diff --git a/src/Ast/PhpDoc/AssertTagMethodValueNode.php b/src/Ast/PhpDoc/AssertTagMethodValueNode.php index 067204b..cf4f556 100644 --- a/src/Ast/PhpDoc/AssertTagMethodValueNode.php +++ b/src/Ast/PhpDoc/AssertTagMethodValueNode.php @@ -23,15 +23,19 @@ class AssertTagMethodValueNode implements PhpDocTagValueNode /** @var bool */ public $isNegated; + /** @var bool */ + public $isEquality; + /** @var string (may be empty) */ public $description; - public function __construct(TypeNode $type, string $parameter, string $method, bool $isNegated, string $description) + public function __construct(TypeNode $type, string $parameter, string $method, bool $isNegated, string $description, bool $isEquality = false) { $this->type = $type; $this->parameter = $parameter; $this->method = $method; $this->isNegated = $isNegated; + $this->isEquality = $isEquality; $this->description = $description; } @@ -39,7 +43,8 @@ class AssertTagMethodValueNode implements PhpDocTagValueNode public function __toString(): string { $isNegated = $this->isNegated ? '!' : ''; - return trim("{$isNegated}{$this->type} {$this->parameter}->{$this->method}() {$this->description}"); + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->method}() {$this->description}"); } } diff --git a/src/Ast/PhpDoc/AssertTagPropertyValueNode.php b/src/Ast/PhpDoc/AssertTagPropertyValueNode.php index 4248abe..4fb3180 100644 --- a/src/Ast/PhpDoc/AssertTagPropertyValueNode.php +++ b/src/Ast/PhpDoc/AssertTagPropertyValueNode.php @@ -23,15 +23,19 @@ class AssertTagPropertyValueNode implements PhpDocTagValueNode /** @var bool */ public $isNegated; + /** @var bool */ + public $isEquality; + /** @var string (may be empty) */ public $description; - public function __construct(TypeNode $type, string $parameter, string $property, bool $isNegated, string $description) + public function __construct(TypeNode $type, string $parameter, string $property, bool $isNegated, string $description, bool $isEquality = false) { $this->type = $type; $this->parameter = $parameter; $this->property = $property; $this->isNegated = $isNegated; + $this->isEquality = $isEquality; $this->description = $description; } @@ -39,7 +43,8 @@ class AssertTagPropertyValueNode implements PhpDocTagValueNode public function __toString(): string { $isNegated = $this->isNegated ? '!' : ''; - return trim("{$isNegated}{$this->type} {$this->parameter}->{$this->property} {$this->description}"); + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->property} {$this->description}"); } } diff --git a/src/Ast/PhpDoc/AssertTagValueNode.php b/src/Ast/PhpDoc/AssertTagValueNode.php index bf75dcf..d6423f5 100644 --- a/src/Ast/PhpDoc/AssertTagValueNode.php +++ b/src/Ast/PhpDoc/AssertTagValueNode.php @@ -20,14 +20,18 @@ class AssertTagValueNode implements PhpDocTagValueNode /** @var bool */ public $isNegated; + /** @var bool */ + public $isEquality; + /** @var string (may be empty) */ public $description; - public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description) + public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description, bool $isEquality = false) { $this->type = $type; $this->parameter = $parameter; $this->isNegated = $isNegated; + $this->isEquality = $isEquality; $this->description = $description; } @@ -35,7 +39,8 @@ class AssertTagValueNode implements PhpDocTagValueNode public function __toString(): string { $isNegated = $this->isNegated ? '!' : ''; - return trim("{$isNegated}{$this->type} {$this->parameter} {$this->description}"); + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter} {$this->description}"); } } diff --git a/src/Parser/PhpDocParser.php b/src/Parser/PhpDocParser.php index 2b6b796..9badbe6 100644 --- a/src/Parser/PhpDocParser.php +++ b/src/Parser/PhpDocParser.php @@ -472,17 +472,18 @@ class PhpDocParser private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode { $isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED); + $isEquality = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); $type = $this->typeParser->parse($tokens); $parameter = $this->parseAssertParameter($tokens); $description = $this->parseOptionalDescription($tokens); if (array_key_exists('method', $parameter)) { - return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description); + return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description, $isEquality); } elseif (array_key_exists('property', $parameter)) { - return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description); + return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description, $isEquality); } - return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description); + return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description, $isEquality); } /** diff --git a/tests/PHPStan/Parser/PhpDocParserTest.php b/tests/PHPStan/Parser/PhpDocParserTest.php index c20f9d6..c81a3a4 100644 --- a/tests/PHPStan/Parser/PhpDocParserTest.php +++ b/tests/PHPStan/Parser/PhpDocParserTest.php @@ -4002,6 +4002,40 @@ some text in the middle' ), ]), ]; + + yield [ + 'OK equality', + '/** @phpstan-assert =Type $var */', + new PhpDocNode([ + new PhpDocTagNode( + '@phpstan-assert', + new AssertTagValueNode( + new IdentifierTypeNode('Type'), + '$var', + false, + '', + true + ) + ), + ]), + ]; + + yield [ + 'OK negated equality', + '/** @phpstan-assert !=Type $var */', + new PhpDocNode([ + new PhpDocTagNode( + '@phpstan-assert', + new AssertTagValueNode( + new IdentifierTypeNode('Type'), + '$var', + true, + '', + true + ) + ), + ]), + ]; } public function providerDebug(): Iterator