Add negated assertions

This commit is contained in:
Richard van Velzen 2022-05-02 14:10:08 +02:00 committed by Ondřej Mirtes
parent 47051f5ca6
commit 6cafed9212
4 changed files with 35 additions and 3 deletions

View File

@ -17,20 +17,25 @@ class AssertTagValueNode implements PhpDocTagValueNode
/** @var string */
public $parameter;
/** @var bool */
public $isNegated;
/** @var string (may be empty) */
public $description;
public function __construct(TypeNode $type, string $parameter, string $description)
public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description)
{
$this->type = $type;
$this->parameter = $parameter;
$this->isNegated = $isNegated;
$this->description = $description;
}
public function __toString(): string
{
return trim("{$this->type} {$this->parameter} {$this->description}");
$isNegated = $this->isNegated ? '!' : '';
return trim("{$this->type} {$isNegated}{$this->parameter} {$this->description}");
}
}

View File

@ -48,12 +48,14 @@ class Lexer
public const TOKEN_WILDCARD = 30;
public const TOKEN_OPEN_CURLY_BRACKET = 31;
public const TOKEN_CLOSE_CURLY_BRACKET = 32;
public const TOKEN_NEGATED = 33;
public const TOKEN_LABELS = [
self::TOKEN_REFERENCE => '\'&\'',
self::TOKEN_UNION => '\'|\'',
self::TOKEN_INTERSECTION => '\'&\'',
self::TOKEN_NULLABLE => '\'?\'',
self::TOKEN_NEGATED => '\'!\'',
self::TOKEN_OPEN_PARENTHESES => '\'(\'',
self::TOKEN_CLOSE_PARENTHESES => '\')\'',
self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'',
@ -129,6 +131,7 @@ class Lexer
self::TOKEN_UNION => '\\|',
self::TOKEN_INTERSECTION => '&',
self::TOKEN_NULLABLE => '\\?',
self::TOKEN_NEGATED => '!',
self::TOKEN_OPEN_PARENTHESES => '\\(',
self::TOKEN_CLOSE_PARENTHESES => '\\)',

View File

@ -431,10 +431,11 @@ class PhpDocParser
private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\AssertTagValueNode
{
$isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED);
$type = $this->typeParser->parse($tokens);
$parameter = $this->parseRequiredVariableName($tokens);
$description = $this->parseOptionalDescription($tokens);
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter, $description);
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter, $isNegated, $description);
}
private function parseOptionalVariableName(TokenIterator $tokens): string

View File

@ -3493,6 +3493,7 @@ some text in the middle'
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
false,
''
)
),
@ -3508,6 +3509,7 @@ some text in the middle'
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
false,
''
)
),
@ -3523,6 +3525,7 @@ some text in the middle'
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
false,
'assert Type to $var'
)
),
@ -3541,6 +3544,7 @@ some text in the middle'
new IdentifierTypeNode('Other'),
]),
'$var',
false,
''
)
),
@ -3575,11 +3579,13 @@ some text in the middle'
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
false,
''
)
),
]),
];
yield [
'OK assert-if-false',
'/** @phpstan-assert-if-false Type $var */',
@ -3589,6 +3595,23 @@ some text in the middle'
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
false,
''
)
),
]),
];
yield [
'OK negated',
'/** @phpstan-assert !Type $var */',
new PhpDocNode([
new PhpDocTagNode(
'@phpstan-assert',
new AssertTagValueNode(
new IdentifierTypeNode('Type'),
'$var',
true,
''
)
),