Skip to content

Commit 6cafed9

Browse files
rvanvelzenondrejmirtes
authored andcommitted
Add negated assertions
1 parent 47051f5 commit 6cafed9

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

src/Ast/PhpDoc/AssertTagValueNode.php

+7-2
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,25 @@ class AssertTagValueNode implements PhpDocTagValueNode
1717
/** @var string */
1818
public $parameter;
1919

20+
/** @var bool */
21+
public $isNegated;
22+
2023
/** @var string (may be empty) */
2124
public $description;
2225

23-
public function __construct(TypeNode $type, string $parameter, string $description)
26+
public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description)
2427
{
2528
$this->type = $type;
2629
$this->parameter = $parameter;
30+
$this->isNegated = $isNegated;
2731
$this->description = $description;
2832
}
2933

3034

3135
public function __toString(): string
3236
{
33-
return trim("{$this->type} {$this->parameter} {$this->description}");
37+
$isNegated = $this->isNegated ? '!' : '';
38+
return trim("{$this->type} {$isNegated}{$this->parameter} {$this->description}");
3439
}
3540

3641
}

src/Lexer/Lexer.php

+3
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ class Lexer
4848
public const TOKEN_WILDCARD = 30;
4949
public const TOKEN_OPEN_CURLY_BRACKET = 31;
5050
public const TOKEN_CLOSE_CURLY_BRACKET = 32;
51+
public const TOKEN_NEGATED = 33;
5152

5253
public const TOKEN_LABELS = [
5354
self::TOKEN_REFERENCE => '\'&\'',
5455
self::TOKEN_UNION => '\'|\'',
5556
self::TOKEN_INTERSECTION => '\'&\'',
5657
self::TOKEN_NULLABLE => '\'?\'',
58+
self::TOKEN_NEGATED => '\'!\'',
5759
self::TOKEN_OPEN_PARENTHESES => '\'(\'',
5860
self::TOKEN_CLOSE_PARENTHESES => '\')\'',
5961
self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'',
@@ -129,6 +131,7 @@ private function initialize(): void
129131
self::TOKEN_UNION => '\\|',
130132
self::TOKEN_INTERSECTION => '&',
131133
self::TOKEN_NULLABLE => '\\?',
134+
self::TOKEN_NEGATED => '!',
132135

133136
self::TOKEN_OPEN_PARENTHESES => '\\(',
134137
self::TOKEN_CLOSE_PARENTHESES => '\\)',

src/Parser/PhpDocParser.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,11 @@ private function parseTypeAliasImportTagValue(TokenIterator $tokens): Ast\PhpDoc
431431

432432
private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\AssertTagValueNode
433433
{
434+
$isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED);
434435
$type = $this->typeParser->parse($tokens);
435436
$parameter = $this->parseRequiredVariableName($tokens);
436437
$description = $this->parseOptionalDescription($tokens);
437-
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter, $description);
438+
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter, $isNegated, $description);
438439
}
439440

440441
private function parseOptionalVariableName(TokenIterator $tokens): string

tests/PHPStan/Parser/PhpDocParserTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -3493,6 +3493,7 @@ public function provideAssertTagsData(): Iterator
34933493
new AssertTagValueNode(
34943494
new IdentifierTypeNode('Type'),
34953495
'$var',
3496+
false,
34963497
''
34973498
)
34983499
),
@@ -3508,6 +3509,7 @@ public function provideAssertTagsData(): Iterator
35083509
new AssertTagValueNode(
35093510
new IdentifierTypeNode('Type'),
35103511
'$var',
3512+
false,
35113513
''
35123514
)
35133515
),
@@ -3523,6 +3525,7 @@ public function provideAssertTagsData(): Iterator
35233525
new AssertTagValueNode(
35243526
new IdentifierTypeNode('Type'),
35253527
'$var',
3528+
false,
35263529
'assert Type to $var'
35273530
)
35283531
),
@@ -3541,6 +3544,7 @@ public function provideAssertTagsData(): Iterator
35413544
new IdentifierTypeNode('Other'),
35423545
]),
35433546
'$var',
3547+
false,
35443548
''
35453549
)
35463550
),
@@ -3575,11 +3579,13 @@ public function provideAssertTagsData(): Iterator
35753579
new AssertTagValueNode(
35763580
new IdentifierTypeNode('Type'),
35773581
'$var',
3582+
false,
35783583
''
35793584
)
35803585
),
35813586
]),
35823587
];
3588+
35833589
yield [
35843590
'OK assert-if-false',
35853591
'/** @phpstan-assert-if-false Type $var */',
@@ -3589,6 +3595,23 @@ public function provideAssertTagsData(): Iterator
35893595
new AssertTagValueNode(
35903596
new IdentifierTypeNode('Type'),
35913597
'$var',
3598+
false,
3599+
''
3600+
)
3601+
),
3602+
]),
3603+
];
3604+
3605+
yield [
3606+
'OK negated',
3607+
'/** @phpstan-assert !Type $var */',
3608+
new PhpDocNode([
3609+
new PhpDocTagNode(
3610+
'@phpstan-assert',
3611+
new AssertTagValueNode(
3612+
new IdentifierTypeNode('Type'),
3613+
'$var',
3614+
true,
35923615
''
35933616
)
35943617
),

0 commit comments

Comments
 (0)