|  | 
| 6 | 6 | use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; | 
| 7 | 7 | use PHPStan\PhpDocParser\Lexer\Lexer; | 
| 8 | 8 | use PHPStan\ShouldNotHappenException; | 
|  | 9 | +use function array_key_exists; | 
| 9 | 10 | use function array_values; | 
| 10 | 11 | use function count; | 
| 11 | 12 | use function trim; | 
| @@ -446,13 +447,56 @@ private function parseTypeAliasImportTagValue(TokenIterator $tokens): Ast\PhpDoc | 
| 446 | 447 | 		return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, new IdentifierTypeNode($importedFrom), $importedAs); | 
| 447 | 448 | 	} | 
| 448 | 449 | 
 | 
| 449 |  | -	private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\AssertTagValueNode | 
|  | 450 | +	/** | 
|  | 451 | +	 * @return Ast\PhpDoc\AssertTagValueNode|Ast\PhpDoc\AssertTagPropertyValueNode|Ast\PhpDoc\AssertTagMethodValueNode | 
|  | 452 | +	 */ | 
|  | 453 | +	private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode | 
| 450 | 454 | 	{ | 
| 451 | 455 | 		$isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED); | 
| 452 | 456 | 		$type = $this->typeParser->parse($tokens); | 
| 453 |  | -		$parameter = $this->parseRequiredVariableName($tokens); | 
|  | 457 | +		$parameter = $this->parseAssertParameter($tokens); | 
| 454 | 458 | 		$description = $this->parseOptionalDescription($tokens); | 
| 455 |  | -		return new Ast\PhpDoc\AssertTagValueNode($type, $parameter, $isNegated, $description); | 
|  | 459 | + | 
|  | 460 | +		if (array_key_exists('method', $parameter)) { | 
|  | 461 | +			return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description); | 
|  | 462 | +		} elseif (array_key_exists('property', $parameter)) { | 
|  | 463 | +			return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description); | 
|  | 464 | +		} | 
|  | 465 | + | 
|  | 466 | +		return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description); | 
|  | 467 | +	} | 
|  | 468 | + | 
|  | 469 | +	/** | 
|  | 470 | +	 * @return array{parameter: string}|array{parameter: string, property: string}|array{parameter: string, method: string} | 
|  | 471 | +	 */ | 
|  | 472 | +	private function parseAssertParameter(TokenIterator $tokens): array | 
|  | 473 | +	{ | 
|  | 474 | +		if ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) { | 
|  | 475 | +			$parameter = '$this'; | 
|  | 476 | +			$requirePropertyOrMethod = true; | 
|  | 477 | +			$tokens->next(); | 
|  | 478 | +		} else { | 
|  | 479 | +			$parameter = $tokens->currentTokenValue(); | 
|  | 480 | +			$requirePropertyOrMethod = false; | 
|  | 481 | +			$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); | 
|  | 482 | +		} | 
|  | 483 | + | 
|  | 484 | +		if ($requirePropertyOrMethod || $tokens->isCurrentTokenType(Lexer::TOKEN_ARROW)) { | 
|  | 485 | +			$tokens->consumeTokenType(Lexer::TOKEN_ARROW); | 
|  | 486 | + | 
|  | 487 | +			$propertyOrMethod = $tokens->currentTokenValue(); | 
|  | 488 | +			$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); | 
|  | 489 | + | 
|  | 490 | +			if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { | 
|  | 491 | +				$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); | 
|  | 492 | + | 
|  | 493 | +				return ['parameter' => $parameter, 'method' => $propertyOrMethod]; | 
|  | 494 | +			} | 
|  | 495 | + | 
|  | 496 | +			return ['parameter' => $parameter, 'property' => $propertyOrMethod]; | 
|  | 497 | +		} | 
|  | 498 | + | 
|  | 499 | +		return ['parameter' => $parameter]; | 
| 456 | 500 | 	} | 
| 457 | 501 | 
 | 
| 458 | 502 | 	private function parseOptionalVariableName(TokenIterator $tokens): string | 
|  | 
0 commit comments