2017-11-18 21:58:26 +01:00
|
|
|
<?php declare(strict_types = 1);
|
|
|
|
|
|
|
|
namespace PHPStan\PhpDocParser\Parser;
|
|
|
|
|
|
|
|
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprArrayNode;
|
2017-12-16 18:37:50 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
|
2020-04-30 15:03:40 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
|
2020-05-04 11:11:57 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\Node;
|
2019-03-18 22:10:28 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\DeprecatedTagValueNode;
|
2019-06-07 18:35:22 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
2019-06-07 18:35:22 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
|
2020-05-02 08:25:41 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
|
2017-12-16 16:05:37 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
2019-05-21 15:22:01 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
2017-12-16 16:05:37 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
2021-02-27 14:47:23 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
|
2020-12-30 16:13:25 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
|
2019-06-07 18:35:22 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
2020-02-26 22:57:57 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
|
2020-04-30 15:03:40 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
|
2019-06-07 18:35:22 +02:00
|
|
|
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
|
2017-11-18 21:58:26 +01:00
|
|
|
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
|
|
|
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
|
|
|
|
use PHPStan\PhpDocParser\Lexer\Lexer;
|
|
|
|
|
|
|
|
class PhpDocParserTest extends \PHPUnit\Framework\TestCase
|
|
|
|
{
|
|
|
|
|
|
|
|
/** @var Lexer */
|
|
|
|
private $lexer;
|
|
|
|
|
2018-08-09 13:08:42 +02:00
|
|
|
/** @var PhpDocParser */
|
2017-11-18 21:58:26 +01:00
|
|
|
private $phpDocParser;
|
|
|
|
|
2019-04-23 21:27:03 +02:00
|
|
|
protected function setUp(): void
|
2017-11-18 21:58:26 +01:00
|
|
|
{
|
|
|
|
parent::setUp();
|
|
|
|
$this->lexer = new Lexer();
|
2020-04-30 15:03:40 +02:00
|
|
|
$constExprParser = new ConstExprParser();
|
|
|
|
$this->phpDocParser = new PhpDocParser(new TypeParser($constExprParser), $constExprParser);
|
2017-11-18 21:58:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-02-19 12:57:27 +01:00
|
|
|
* @dataProvider provideTagsWithNumbers
|
2017-12-16 16:05:37 +01:00
|
|
|
* @dataProvider provideParamTagsData
|
|
|
|
* @dataProvider provideVarTagsData
|
|
|
|
* @dataProvider provideReturnTagsData
|
|
|
|
* @dataProvider provideThrowsTagsData
|
2020-05-02 08:25:41 +02:00
|
|
|
* @dataProvider provideMixinTagsData
|
2019-03-18 22:10:28 +01:00
|
|
|
* @dataProvider provideDeprecatedTagsData
|
2017-12-16 16:05:37 +01:00
|
|
|
* @dataProvider providePropertyTagsData
|
2017-12-16 16:32:26 +01:00
|
|
|
* @dataProvider provideMethodTagsData
|
2017-12-16 16:05:37 +01:00
|
|
|
* @dataProvider provideSingleLinePhpDocData
|
|
|
|
* @dataProvider provideMultiLinePhpDocData
|
2019-05-21 15:22:01 +02:00
|
|
|
* @dataProvider provideTemplateTagsData
|
2019-06-07 18:35:22 +02:00
|
|
|
* @dataProvider provideExtendsTagsData
|
2020-12-30 16:13:25 +01:00
|
|
|
* @dataProvider provideTypeAliasTagsData
|
2021-02-27 14:47:23 +01:00
|
|
|
* @dataProvider provideTypeAliasImportTagsData
|
2019-05-09 15:05:45 +02:00
|
|
|
* @dataProvider provideRealWorldExampleData
|
2020-06-08 23:36:09 +02:00
|
|
|
* @dataProvider provideDescriptionWithOrWithoutHtml
|
2017-12-16 16:05:37 +01:00
|
|
|
* @param string $label
|
2017-11-18 21:58:26 +01:00
|
|
|
* @param string $input
|
|
|
|
* @param PhpDocNode $expectedPhpDocNode
|
|
|
|
* @param int $nextTokenType
|
|
|
|
*/
|
2019-04-23 21:27:03 +02:00
|
|
|
public function testParse(string $label, string $input, PhpDocNode $expectedPhpDocNode, int $nextTokenType = Lexer::TOKEN_END): void
|
2017-11-18 21:58:26 +01:00
|
|
|
{
|
|
|
|
$tokens = new TokenIterator($this->lexer->tokenize($input));
|
|
|
|
$actualPhpDocNode = $this->phpDocParser->parse($tokens);
|
|
|
|
|
2017-12-16 16:05:37 +01:00
|
|
|
$this->assertEquals($expectedPhpDocNode, $actualPhpDocNode, $label);
|
2017-11-18 21:58:26 +01:00
|
|
|
$this->assertSame((string) $expectedPhpDocNode, (string) $actualPhpDocNode);
|
|
|
|
$this->assertSame($nextTokenType, $tokens->currentTokenType());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideParamTagsData(): \Iterator
|
2017-11-18 21:58:26 +01:00
|
|
|
{
|
2017-12-16 16:05:37 +01:00
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @param Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
false,
|
|
|
|
'$foo',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @param Foo $foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
false,
|
|
|
|
'$foo',
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK variadic without description',
|
|
|
|
'/** @param Foo ...$foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
true,
|
|
|
|
'$foo',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK variadic with description',
|
|
|
|
'/** @param Foo ...$foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
true,
|
|
|
|
'$foo',
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type, parameter name and description',
|
|
|
|
'/** @param */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
11,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and parameter name and with description (1)',
|
|
|
|
'/** @param #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'#desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
11,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-19 15:48:51 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and parameter name and with description (2)',
|
|
|
|
'/** @param (Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
16,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (1)',
|
|
|
|
'/** @param (Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2017-11-19 18:07:18 +01:00
|
|
|
'$foo',
|
2017-12-16 16:05:37 +01:00
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
16,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
2017-11-19 18:07:18 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (2)',
|
|
|
|
'/** @param Foo<Bar $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo<Bar $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2017-11-18 21:58:26 +01:00
|
|
|
'$foo',
|
2017-12-16 16:05:37 +01:00
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
19,
|
|
|
|
Lexer::TOKEN_CLOSE_ANGLE_BRACKET
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (3)',
|
|
|
|
'/** @param Foo| $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo| $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
16,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without parameter name and description',
|
|
|
|
'/** @param Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
15,
|
|
|
|
Lexer::TOKEN_VARIABLE
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without parameter name and with description',
|
|
|
|
'/** @param Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo optional description',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'optional',
|
|
|
|
Lexer::TOKEN_IDENTIFIER,
|
|
|
|
15,
|
|
|
|
Lexer::TOKEN_VARIABLE
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideVarTagsData(): \Iterator
|
2017-12-16 16:05:37 +01:00
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description and variable name',
|
|
|
|
'/** @var Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @var Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without description and with no space between type and variable name',
|
|
|
|
'/** @var Foo$foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without variable name',
|
|
|
|
'/** @var Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'',
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without variable name and complex description',
|
|
|
|
'/** @var callable[] function (Configurator $sender, DI\Compiler $compiler); Occurs after the compiler is created */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new ArrayTypeNode(
|
|
|
|
new IdentifierTypeNode('callable')
|
|
|
|
),
|
|
|
|
'',
|
|
|
|
'function (Configurator $sender, DI\Compiler $compiler); Occurs after the compiler is created'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without variable name and tag in the middle of description',
|
|
|
|
'/** @var Foo @inject */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'',
|
|
|
|
'@inject'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2018-04-25 09:09:25 +02:00
|
|
|
yield [
|
|
|
|
'OK without variable name and description in parentheses',
|
|
|
|
'/** @var Foo (Bar) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'',
|
|
|
|
'(Bar)'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2017-12-16 16:05:37 +01:00
|
|
|
yield [
|
|
|
|
'OK with variable name and description',
|
|
|
|
'/** @var Foo $foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2019-12-13 13:00:03 +01:00
|
|
|
yield [
|
|
|
|
'OK without description with variable $this',
|
|
|
|
'/** @var Foo $this */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$this',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without description and with no space between type and variable name with variable $this',
|
|
|
|
'/** @var Foo$this */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$this',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description with variable $this',
|
|
|
|
'/** @var Foo $this Testing */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$this',
|
|
|
|
'Testing'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description and with no space between type and variable name with variable $this',
|
|
|
|
'/** @var Foo$this Testing */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$this',
|
|
|
|
'Testing'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2017-12-16 16:05:37 +01:00
|
|
|
yield [
|
|
|
|
'OK with variable name and description and without all optional spaces',
|
|
|
|
'/** @var(Foo)$foo#desc*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
'#desc'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type, variable name and description',
|
|
|
|
'/** @var */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
9,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and variable name and with description (1)',
|
|
|
|
'/** @var #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'#desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
9,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and variable name and with description (2)',
|
|
|
|
'/** @var (Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (1)',
|
|
|
|
'/** @var (Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (2)',
|
|
|
|
'/** @var Foo<Bar $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo<Bar $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
17,
|
|
|
|
Lexer::TOKEN_CLOSE_ANGLE_BRACKET
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (3)',
|
|
|
|
'/** @var Foo| $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo| $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2021-03-22 18:24:38 +01:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid object shape',
|
|
|
|
'/** @psalm-type PARTSTRUCTURE_PARAM = object{attribute:string, value?:string} */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@psalm-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Unexpected token "{", expected \'*/\' at offset 44',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'{',
|
|
|
|
Lexer::TOKEN_OPEN_CURLY_BRACKET,
|
|
|
|
44,
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2017-12-16 16:05:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function providePropertyTagsData(): \Iterator
|
2017-12-16 16:05:37 +01:00
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @property Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new PropertyTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @property Foo $foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new PropertyTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'$foo',
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type, property name and description',
|
|
|
|
'/** @property */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-22 11:43:57 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and property name and with description (1)',
|
|
|
|
'/** @property #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'#desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
2017-11-22 11:43:57 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and property name and with description (2)',
|
|
|
|
'/** @property (Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
19,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (1)',
|
|
|
|
'/** @property (Foo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'(Foo $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2017-11-22 11:43:57 +01:00
|
|
|
'$foo',
|
2017-12-16 16:05:37 +01:00
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
19,
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES
|
2017-11-22 11:43:57 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (2)',
|
|
|
|
'/** @property Foo<Bar $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo<Bar $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2017-11-22 11:43:57 +01:00
|
|
|
'$foo',
|
2017-12-16 16:05:37 +01:00
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
22,
|
|
|
|
Lexer::TOKEN_CLOSE_ANGLE_BRACKET
|
2017-11-22 11:43:57 +01:00
|
|
|
)
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with broken type (3)',
|
|
|
|
'/** @property Foo| $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo| $foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
19,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without property name and description',
|
|
|
|
'/** @property Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_VARIABLE
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without property name and with description',
|
|
|
|
'/** @property Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@property',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo optional description',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'optional',
|
|
|
|
Lexer::TOKEN_IDENTIFIER,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_VARIABLE
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideReturnTagsData(): \Iterator
|
2017-12-16 16:05:37 +01:00
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @return Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @return Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description that starts with TOKEN_OPEN_SQUARE_BRACKET',
|
|
|
|
'/** @return Foo [Bar] */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'[Bar]'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and description',
|
|
|
|
'/** @return */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
12,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type',
|
|
|
|
'/** @return [int, string] */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'[int, string]',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'[',
|
|
|
|
Lexer::TOKEN_OPEN_SQUARE_BRACKET,
|
|
|
|
12,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token (1)',
|
|
|
|
'/** @return Foo | #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo | #desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token (2)',
|
|
|
|
'/** @return A & B | C */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'A & B | C',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'|',
|
|
|
|
Lexer::TOKEN_UNION,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_OTHER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token (3)',
|
|
|
|
'/** @return A | B & C */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'A | B & C',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'&',
|
|
|
|
Lexer::TOKEN_INTERSECTION,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_OTHER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token (4)',
|
|
|
|
'/** @return A | B < 123 */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'A | B < 123',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2020-04-30 15:03:40 +02:00
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
24,
|
|
|
|
Lexer::TOKEN_CLOSE_ANGLE_BRACKET
|
2017-12-16 16:05:37 +01:00
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2020-04-30 15:03:40 +02:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with type and const expr as generic type variable',
|
|
|
|
'/** @return A | B < 123 > */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
[
|
|
|
|
new ConstTypeNode(new ConstExprIntegerNode('123')),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2017-12-16 16:05:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideThrowsTagsData(): \Iterator
|
2017-12-16 16:05:37 +01:00
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @throws Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new ThrowsTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @throws Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new ThrowsTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description that starts with TOKEN_OPEN_SQUARE_BRACKET',
|
|
|
|
'/** @throws Foo [Bar] */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new ThrowsTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'[Bar]'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and description',
|
|
|
|
'/** @throws */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
12,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token',
|
|
|
|
'/** @throws Foo | #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo | #desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-05-02 08:25:41 +02:00
|
|
|
public function provideMixinTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @mixin Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new MixinTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @mixin Foo optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new MixinTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description that starts with TOKEN_OPEN_SQUARE_BRACKET',
|
|
|
|
'/** @mixin Foo [Bar] */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new MixinTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'[Bar]'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type and description',
|
|
|
|
'/** @mixin */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
11,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid with type and disallowed description start token',
|
|
|
|
'/** @mixin Foo | #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo | #desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
17,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'generic @mixin',
|
|
|
|
'/** @mixin Foo<Bar> */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new MixinTagValueNode(
|
|
|
|
new GenericTypeNode(new IdentifierTypeNode('Foo'), [
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2019-03-18 22:10:28 +01:00
|
|
|
public function provideDeprecatedTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK with no description',
|
|
|
|
'/** @deprecated */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
2019-04-23 21:35:00 +02:00
|
|
|
new DeprecatedTagValueNode('')
|
2019-03-18 22:10:28 +01:00
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with simple description description',
|
|
|
|
'/** @deprecated text string */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
|
|
|
new DeprecatedTagValueNode('text string')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-04-25 17:40:59 +02:00
|
|
|
yield [
|
|
|
|
'OK with two simple description with break',
|
2019-04-30 05:46:33 +02:00
|
|
|
'/** @deprecated text first
|
2019-04-25 17:40:59 +02:00
|
|
|
*
|
2019-04-30 05:46:33 +02:00
|
|
|
* @deprecated text second
|
2019-04-25 17:40:59 +02:00
|
|
|
*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
|
|
|
new DeprecatedTagValueNode('text first')
|
|
|
|
),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
|
|
|
new DeprecatedTagValueNode('text second')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with two simple description without break',
|
2019-04-30 05:46:33 +02:00
|
|
|
'/** @deprecated text first
|
|
|
|
* @deprecated text second
|
2019-04-25 17:40:59 +02:00
|
|
|
*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
|
|
|
new DeprecatedTagValueNode('text first')
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
|
|
|
new DeprecatedTagValueNode('text second')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-03-18 22:10:28 +01:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with long descriptions',
|
|
|
|
'/** @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In
|
|
|
|
* Drupal 9 there will be no way to set the status and in Drupal 8 this
|
|
|
|
* ability has been removed because mb_*() functions are supplied using
|
|
|
|
* Symfony\'s polyfill. */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
2019-05-09 14:36:02 +02:00
|
|
|
new DeprecatedTagValueNode('in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In
|
2021-03-15 09:45:44 +01:00
|
|
|
Drupal 9 there will be no way to set the status and in Drupal 8 this
|
|
|
|
ability has been removed because mb_*() functions are supplied using
|
|
|
|
Symfony\'s polyfill.')
|
2019-04-24 18:29:53 +02:00
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
yield [
|
|
|
|
'OK with multiple and long descriptions',
|
|
|
|
'/**
|
|
|
|
* Sample class
|
2019-04-30 05:46:33 +02:00
|
|
|
*
|
2019-04-24 18:29:53 +02:00
|
|
|
* @author Foo Baz <foo@baz.com>
|
2019-04-30 05:46:33 +02:00
|
|
|
*
|
2019-04-24 18:29:53 +02:00
|
|
|
* @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In
|
|
|
|
* Drupal 9 there will be no way to set the status and in Drupal 8 this
|
|
|
|
* ability has been removed because mb_*() functions are supplied using
|
2019-04-30 05:46:33 +02:00
|
|
|
* Symfony\'s polyfill.
|
2019-04-24 18:29:53 +02:00
|
|
|
*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode('Sample class'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@author',
|
|
|
|
new GenericTagValueNode('Foo Baz <foo@baz.com>')
|
|
|
|
),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@deprecated',
|
2019-05-09 14:36:02 +02:00
|
|
|
new DeprecatedTagValueNode('in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In
|
2021-03-15 09:45:44 +01:00
|
|
|
Drupal 9 there will be no way to set the status and in Drupal 8 this
|
|
|
|
ability has been removed because mb_*() functions are supplied using
|
|
|
|
Symfony\'s polyfill.')
|
2019-03-18 22:10:28 +01:00
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
2017-12-16 16:05:37 +01:00
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideMethodTagsData(): \Iterator
|
2017-12-16 16:32:26 +01:00
|
|
|
{
|
|
|
|
yield [
|
2017-12-16 18:37:50 +01:00
|
|
|
'OK non-static, without return type',
|
|
|
|
'/** @method foo() */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
null,
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type',
|
|
|
|
'/** @method Foo foo() */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return static type',
|
2017-12-16 16:32:26 +01:00
|
|
|
'/** @method static foo() */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('static'),
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2017-12-16 18:37:50 +01:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK static, with return type',
|
|
|
|
'/** @method static Foo foo() */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK static, with return static type',
|
|
|
|
'/** @method static static foo() */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('static'),
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and description',
|
|
|
|
'/** @method Foo foo() optional description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[],
|
|
|
|
'optional description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single parameter without type',
|
|
|
|
'/** @method Foo foo($a) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single parameter with type',
|
|
|
|
'/** @method Foo foo(A $a) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single parameter with type that is passed by reference',
|
|
|
|
'/** @method Foo foo(A &$a) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single variadic parameter with type',
|
|
|
|
'/** @method Foo foo(A ...$a) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single variadic parameter with type that is passed by reference',
|
|
|
|
'/** @method Foo foo(A &...$a) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single parameter with default value',
|
|
|
|
'/** @method Foo foo($a = 123) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
new ConstExprIntegerNode('123')
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and single variadic parameter with type that is passed by reference and default value',
|
|
|
|
'/** @method Foo foo(A &...$a = 123) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
'$a',
|
|
|
|
new ConstExprIntegerNode('123')
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK non-static, with return type and multiple parameters without type',
|
|
|
|
'/** @method Foo foo($a, $b, $c) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'foo',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$c',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid non-static method without parentheses',
|
|
|
|
'/** @method a b */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'a b',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
16,
|
|
|
|
Lexer::TOKEN_OPEN_PARENTHESES
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid static method without parentheses',
|
|
|
|
'/** @method static a b */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'static a b',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
23,
|
|
|
|
Lexer::TOKEN_OPEN_PARENTHESES
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid non-static method without parameter name',
|
|
|
|
'/** @method a b(x) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'a b(x)',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
')',
|
|
|
|
Lexer::TOKEN_CLOSE_PARENTHESES,
|
|
|
|
17,
|
|
|
|
Lexer::TOKEN_VARIABLE
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2017-12-16 16:32:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-16 19:32:10 +01:00
|
|
|
public function provideSingleLinePhpDocData(): \Iterator
|
2017-12-16 16:05:37 +01:00
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'empty',
|
|
|
|
'/** */',
|
|
|
|
new PhpDocNode([]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'edge-case',
|
|
|
|
'/** /**/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode(
|
|
|
|
'/*'
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single text node',
|
|
|
|
'/** text */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode(
|
|
|
|
'text'
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single text node with tag in the middle',
|
|
|
|
'/** text @foo bar */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode(
|
|
|
|
'text @foo bar'
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single tag node without value',
|
|
|
|
'/** @foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@foo',
|
|
|
|
new GenericTagValueNode('')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single tag node with value',
|
|
|
|
'/** @foo lorem ipsum */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@foo',
|
|
|
|
new GenericTagValueNode('lorem ipsum')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single tag node with tag in the middle of value',
|
|
|
|
'/** @foo lorem @bar ipsum */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@foo',
|
|
|
|
new GenericTagValueNode('lorem @bar ipsum')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'single tag node without space between tag name and its value',
|
|
|
|
'/** @varFoo $foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@varFoo',
|
|
|
|
new GenericTagValueNode(
|
|
|
|
'$foo'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2020-02-26 22:57:57 +01:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'callable with space between keyword and parameters',
|
|
|
|
'/** @var callable (int): void */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new CallableTypeNode(
|
|
|
|
new IdentifierTypeNode('callable'),
|
|
|
|
[
|
2020-02-27 03:29:44 +01:00
|
|
|
new CallableTypeParameterNode(new IdentifierTypeNode('int'), false, false, '', false),
|
2020-02-26 22:57:57 +01:00
|
|
|
],
|
|
|
|
new IdentifierTypeNode('void')
|
|
|
|
),
|
|
|
|
'',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'callable with description in parentheses',
|
|
|
|
'/** @var callable (int) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('callable'),
|
|
|
|
'',
|
|
|
|
'(int)'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'callable with incomplete signature without return type',
|
|
|
|
'/** @var callable(int) */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@var',
|
|
|
|
new VarTagValueNode(
|
|
|
|
new IdentifierTypeNode('callable'),
|
|
|
|
'',
|
|
|
|
'(int)'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2017-12-16 16:05:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function provideMultiLinePhpDocData(): array
|
|
|
|
{
|
|
|
|
return [
|
2017-11-18 21:58:26 +01:00
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with two tags',
|
2017-11-18 21:58:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
* @param Foo $foo 1st multi world description
|
|
|
|
* @param Bar $bar 2nd multi world description
|
|
|
|
*/',
|
2017-11-18 21:58:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
2017-11-19 18:07:18 +01:00
|
|
|
false,
|
2017-11-18 21:58:26 +01:00
|
|
|
'$foo',
|
|
|
|
'1st multi world description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Bar'),
|
2017-11-19 18:07:18 +01:00
|
|
|
false,
|
2017-11-18 21:58:26 +01:00
|
|
|
'$bar',
|
|
|
|
'2nd multi world description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
],
|
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with two tags and text in the middle',
|
2017-11-18 21:58:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
* @param Foo $foo 1st multi world description
|
|
|
|
* some text in the middle
|
|
|
|
* @param Bar $bar 2nd multi world description
|
|
|
|
*/',
|
2017-11-18 21:58:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
2017-11-19 18:07:18 +01:00
|
|
|
false,
|
2017-11-18 21:58:26 +01:00
|
|
|
'$foo',
|
2019-05-09 14:36:02 +02:00
|
|
|
'1st multi world description
|
|
|
|
some text in the middle'
|
2017-11-18 21:58:26 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Bar'),
|
2017-11-19 18:07:18 +01:00
|
|
|
false,
|
2017-11-18 21:58:26 +01:00
|
|
|
'$bar',
|
|
|
|
'2nd multi world description'
|
|
|
|
)
|
|
|
|
),
|
2017-12-03 14:29:26 +01:00
|
|
|
]),
|
|
|
|
],
|
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with two tags, text in the middle and some empty lines',
|
2017-12-03 14:29:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
*
|
|
|
|
*
|
2019-04-25 17:40:59 +02:00
|
|
|
* @param Foo $foo 1st multi world description with empty lines
|
2019-03-18 22:10:28 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* some text in the middle
|
|
|
|
*
|
|
|
|
*
|
2019-04-25 17:40:59 +02:00
|
|
|
* @param Bar $bar 2nd multi world description with empty lines
|
2019-03-18 22:10:28 +01:00
|
|
|
*
|
|
|
|
*
|
2019-04-25 17:40:59 +02:00
|
|
|
* test
|
2019-03-18 22:10:28 +01:00
|
|
|
*/',
|
2017-12-03 14:29:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
false,
|
|
|
|
'$foo',
|
2019-04-25 17:40:59 +02:00
|
|
|
'1st multi world description with empty lines'
|
2017-12-03 14:29:26 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('some text in the middle'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
false,
|
|
|
|
'$bar',
|
2019-04-25 17:40:59 +02:00
|
|
|
'2nd multi world description with empty lines'
|
2017-12-03 14:29:26 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode(''),
|
2019-04-25 17:40:59 +02:00
|
|
|
new PhpDocTextNode('test'),
|
2017-12-03 14:29:26 +01:00
|
|
|
]),
|
|
|
|
],
|
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with just empty lines',
|
2017-12-03 14:29:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/',
|
2017-12-03 14:29:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
]),
|
|
|
|
],
|
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with tag mentioned as part of text node',
|
2017-12-03 14:29:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
* Lets talk about @param
|
|
|
|
* @param int $foo @param string $bar
|
|
|
|
*/',
|
2017-12-03 14:29:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode('Lets talk about @param'),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
'$foo',
|
|
|
|
'@param string $bar'
|
|
|
|
)
|
|
|
|
),
|
2017-11-18 21:58:26 +01:00
|
|
|
]),
|
|
|
|
],
|
|
|
|
[
|
2017-12-16 16:05:37 +01:00
|
|
|
'multi-line with a lot of @method tags',
|
2017-11-18 21:58:26 +01:00
|
|
|
'/**
|
2019-03-18 22:10:28 +01:00
|
|
|
* @method int getInteger(int $a, int $b)
|
|
|
|
* @method void doSomething(int $a, $b)
|
|
|
|
* @method self|Bar getFooOrBar()
|
|
|
|
* @method methodWithNoReturnType()
|
|
|
|
* @method static int getIntegerStatically(int $a, int $b)
|
|
|
|
* @method static void doSomethingStatically(int $a, $b)
|
|
|
|
* @method static self|Bar getFooOrBarStatically()
|
|
|
|
* @method static methodWithNoReturnTypeStatically()
|
|
|
|
* @method int getIntegerWithDescription(int $a, int $b) Get an integer with a description.
|
|
|
|
* @method void doSomethingWithDescription(int $a, $b) Do something with a description.
|
|
|
|
* @method self|Bar getFooOrBarWithDescription() Get a Foo or a Bar with a description.
|
|
|
|
* @method methodWithNoReturnTypeWithDescription() Do something with a description but what, who knows!
|
|
|
|
* @method static int getIntegerStaticallyWithDescription(int $a, int $b) Get an integer with a description statically.
|
|
|
|
* @method static void doSomethingStaticallyWithDescription(int $a, $b) Do something with a description statically.
|
|
|
|
* @method static self|Bar getFooOrBarStaticallyWithDescription() Get a Foo or a Bar with a description statically.
|
|
|
|
* @method static methodWithNoReturnTypeStaticallyWithDescription() Do something with a description statically, but what, who knows!
|
|
|
|
* @method static bool aStaticMethodThatHasAUniqueReturnTypeInThisClass()
|
|
|
|
* @method static string aStaticMethodThatHasAUniqueReturnTypeInThisClassWithDescription() A Description.
|
|
|
|
* @method int getIntegerNoParams()
|
|
|
|
* @method void doSomethingNoParams()
|
|
|
|
* @method self|Bar getFooOrBarNoParams()
|
|
|
|
* @method methodWithNoReturnTypeNoParams()
|
|
|
|
* @method static int getIntegerStaticallyNoParams()
|
|
|
|
* @method static void doSomethingStaticallyNoParams()
|
|
|
|
* @method static self|Bar getFooOrBarStaticallyNoParams()
|
|
|
|
* @method static methodWithNoReturnTypeStaticallyNoParams()
|
|
|
|
* @method int getIntegerWithDescriptionNoParams() Get an integer with a description.
|
|
|
|
* @method void doSomethingWithDescriptionNoParams() Do something with a description.
|
|
|
|
* @method self|Bar getFooOrBarWithDescriptionNoParams() Get a Foo or a Bar with a description.
|
|
|
|
* @method static int getIntegerStaticallyWithDescriptionNoParams() Get an integer with a description statically.
|
|
|
|
* @method static void doSomethingStaticallyWithDescriptionNoParams() Do something with a description statically.
|
|
|
|
* @method static self|Bar getFooOrBarStaticallyWithDescriptionNoParams() Get a Foo or a Bar with a description statically.
|
|
|
|
* @method static bool|string aStaticMethodThatHasAUniqueReturnTypeInThisClassNoParams()
|
|
|
|
* @method static string|float aStaticMethodThatHasAUniqueReturnTypeInThisClassWithDescriptionNoParams() A Description.
|
|
|
|
* @method \Aws\Result publish(array $args)
|
|
|
|
* @method Image rotate(float & ... $angle = array(), $backgroundColor)
|
|
|
|
* @method Foo overridenMethod()
|
|
|
|
*/',
|
2017-11-18 21:58:26 +01:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getInteger',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomething',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
|
|
|
'getFooOrBar',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
null,
|
|
|
|
'methodWithNoReturnType',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerStatically',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingStatically',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
|
|
|
'getFooOrBarStatically',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
2017-12-16 16:32:26 +01:00
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('static'),
|
2017-11-18 21:58:26 +01:00
|
|
|
'methodWithNoReturnTypeStatically',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerWithDescription',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
'Get an integer with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingWithDescription',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
'Do something with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
|
|
|
'getFooOrBarWithDescription',
|
|
|
|
[],
|
|
|
|
'Get a Foo or a Bar with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
null,
|
|
|
|
'methodWithNoReturnTypeWithDescription',
|
|
|
|
[],
|
|
|
|
'Do something with a description but what, who knows!'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerStaticallyWithDescription',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
'Get an integer with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingStaticallyWithDescription',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$b',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
'Do something with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'getFooOrBarStaticallyWithDescription',
|
|
|
|
[],
|
|
|
|
'Get a Foo or a Bar with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
2017-12-16 16:32:26 +01:00
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('static'),
|
2017-11-18 21:58:26 +01:00
|
|
|
'methodWithNoReturnTypeStaticallyWithDescription',
|
|
|
|
[],
|
|
|
|
'Do something with a description statically, but what, who knows!'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('bool'),
|
|
|
|
'aStaticMethodThatHasAUniqueReturnTypeInThisClass',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('string'),
|
|
|
|
'aStaticMethodThatHasAUniqueReturnTypeInThisClassWithDescription',
|
|
|
|
[],
|
|
|
|
'A Description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'getFooOrBarNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
null,
|
|
|
|
'methodWithNoReturnTypeNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerStaticallyNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingStaticallyNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'getFooOrBarStaticallyNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
2017-12-16 16:32:26 +01:00
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('static'),
|
2017-11-18 21:58:26 +01:00
|
|
|
'methodWithNoReturnTypeStaticallyNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Get an integer with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Do something with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'getFooOrBarWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Get a Foo or a Bar with a description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
'getIntegerStaticallyWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Get an integer with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new IdentifierTypeNode('void'),
|
|
|
|
'doSomethingStaticallyWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Do something with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('self'),
|
|
|
|
new IdentifierTypeNode('Bar'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'getFooOrBarStaticallyWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'Get a Foo or a Bar with a description statically.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('bool'),
|
|
|
|
new IdentifierTypeNode('string'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'aStaticMethodThatHasAUniqueReturnTypeInThisClassNoParams',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
true,
|
|
|
|
new UnionTypeNode([
|
2019-04-23 21:27:03 +02:00
|
|
|
new IdentifierTypeNode('string'),
|
|
|
|
new IdentifierTypeNode('float'),
|
|
|
|
]),
|
2017-11-18 21:58:26 +01:00
|
|
|
'aStaticMethodThatHasAUniqueReturnTypeInThisClassWithDescriptionNoParams',
|
|
|
|
[],
|
|
|
|
'A Description.'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('\\Aws\\Result'),
|
|
|
|
'publish',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('array'),
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$args',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Image'),
|
|
|
|
'rotate',
|
|
|
|
[
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
new IdentifierTypeNode('float'),
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
'$angle',
|
|
|
|
new ConstExprArrayNode([])
|
|
|
|
),
|
|
|
|
new MethodTagValueParameterNode(
|
|
|
|
null,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
'$backgroundColor',
|
|
|
|
null
|
|
|
|
),
|
|
|
|
],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@method',
|
|
|
|
new MethodTagValueNode(
|
|
|
|
false,
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'overridenMethod',
|
|
|
|
[],
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2019-05-21 15:22:01 +02:00
|
|
|
public function provideTemplateTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without bound and description',
|
|
|
|
'/** @template T */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
2019-10-06 12:03:17 +02:00
|
|
|
null,
|
2019-05-21 15:22:01 +02:00
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without bound',
|
|
|
|
'/** @template T the value type*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
2019-10-06 12:03:17 +02:00
|
|
|
null,
|
2019-05-21 15:22:01 +02:00
|
|
|
'the value type'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @template T of DateTime */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
|
|
|
new IdentifierTypeNode('DateTime'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2019-11-18 23:11:38 +01:00
|
|
|
yield [
|
|
|
|
'OK without description',
|
|
|
|
'/** @template T as DateTime */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
|
|
|
new IdentifierTypeNode('DateTime'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2019-05-21 15:22:01 +02:00
|
|
|
yield [
|
|
|
|
'OK with bound and description',
|
|
|
|
'/** @template T of DateTime the value type */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
2019-11-18 23:11:38 +01:00
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
|
|
|
new IdentifierTypeNode('DateTime'),
|
|
|
|
'the value type'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with bound and description',
|
|
|
|
'/** @template T as DateTime the value type */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
2019-05-21 15:22:01 +02:00
|
|
|
'@template',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
|
|
|
new IdentifierTypeNode('DateTime'),
|
|
|
|
'the value type'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without bound and description',
|
|
|
|
'/** @template */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without bound and with description',
|
|
|
|
'/** @template #desc */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'#desc',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'#desc',
|
|
|
|
Lexer::TOKEN_OTHER,
|
|
|
|
14,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-11-06 11:57:55 +01:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with covariance',
|
|
|
|
'/** @template-covariant T */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@template-covariant',
|
|
|
|
new TemplateTagValueNode(
|
|
|
|
'T',
|
|
|
|
null,
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-05-21 15:22:01 +02:00
|
|
|
}
|
|
|
|
|
2019-06-07 18:35:22 +02:00
|
|
|
public function provideExtendsTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK with one argument',
|
|
|
|
'/** @extends Foo<A> */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@extends',
|
|
|
|
new ExtendsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with two arguments',
|
|
|
|
'/** @extends Foo<A,B> */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@extends',
|
|
|
|
new ExtendsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK @implements',
|
|
|
|
'/** @implements Foo<A,B> */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@implements',
|
|
|
|
new ImplementsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
2019-12-05 21:37:59 +01:00
|
|
|
'OK @use',
|
|
|
|
'/** @use Foo<A,B> */',
|
2019-06-07 18:35:22 +02:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
2019-12-05 21:37:59 +01:00
|
|
|
'@use',
|
2019-06-07 18:35:22 +02:00
|
|
|
new UsesTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with description',
|
|
|
|
'/** @extends Foo<A> extends foo*/',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@extends',
|
|
|
|
new ExtendsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[new IdentifierTypeNode('A')]
|
|
|
|
),
|
|
|
|
'extends foo'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type',
|
|
|
|
'/** @extends */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@extends',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
13,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without arguments',
|
|
|
|
'/** @extends Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@extends',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Foo',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
17,
|
|
|
|
Lexer::TOKEN_OPEN_ANGLE_BRACKET
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-09-25 14:28:43 +02:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'class-string in @return',
|
|
|
|
'/** @return class-string */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('class-string'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'class-string in @return with description',
|
|
|
|
'/** @return class-string some description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('class-string'),
|
|
|
|
'some description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'class-string in @param',
|
|
|
|
'/** @param class-string $test */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('class-string'),
|
|
|
|
false,
|
|
|
|
'$test',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'class-string in @param with description',
|
|
|
|
'/** @param class-string $test some description */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('class-string'),
|
|
|
|
false,
|
|
|
|
'$test',
|
|
|
|
'some description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-06-07 18:35:22 +02:00
|
|
|
}
|
|
|
|
|
2020-12-30 16:13:25 +01:00
|
|
|
public function provideTypeAliasTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK',
|
|
|
|
'/** @phpstan-type TypeAlias string|int */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-type',
|
|
|
|
new TypeAliasTagValueNode(
|
|
|
|
'TypeAlias',
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('string'),
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
])
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with psalm syntax',
|
|
|
|
'/** @psalm-type TypeAlias=string|int */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@psalm-type',
|
|
|
|
new TypeAliasTagValueNode(
|
|
|
|
'TypeAlias',
|
|
|
|
new UnionTypeNode([
|
|
|
|
new IdentifierTypeNode('string'),
|
|
|
|
new IdentifierTypeNode('int'),
|
|
|
|
])
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid without type',
|
|
|
|
'/** @phpstan-type TypeAlias */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'TypeAlias',
|
2021-02-27 14:47:23 +01:00
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2020-12-30 16:13:25 +01:00
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
28,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid empty',
|
|
|
|
'/** @phpstan-type */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
2021-02-27 14:47:23 +01:00
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
2020-12-30 16:13:25 +01:00
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
18,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2021-02-27 14:47:23 +01:00
|
|
|
public function provideTypeAliasImportTagsData(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK',
|
|
|
|
'/** @phpstan-import-type TypeAlias from AnotherClass */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new TypeAliasImportTagValueNode(
|
|
|
|
'TypeAlias',
|
|
|
|
new IdentifierTypeNode('AnotherClass'),
|
|
|
|
null
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'OK with alias',
|
|
|
|
'/** @phpstan-import-type TypeAlias from AnotherClass as DifferentAlias */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new TypeAliasImportTagValueNode(
|
|
|
|
'TypeAlias',
|
|
|
|
new IdentifierTypeNode('AnotherClass'),
|
|
|
|
'DifferentAlias'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2021-04-03 16:25:57 +02:00
|
|
|
yield [
|
|
|
|
'invalid non-identifier from',
|
|
|
|
'/** @phpstan-import-type TypeAlias from 42 */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'TypeAlias from 42',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'42',
|
|
|
|
Lexer::TOKEN_INTEGER,
|
|
|
|
40,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid non-simple-identifier from',
|
|
|
|
'/** @phpstan-import-type TypeAlias from AnotherClass[] */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'Unexpected token "[", expected \'*/\' at offset 52',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'[',
|
|
|
|
Lexer::TOKEN_OPEN_SQUARE_BRACKET,
|
|
|
|
52,
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2021-02-27 14:47:23 +01:00
|
|
|
yield [
|
|
|
|
'invalid missing from',
|
|
|
|
'/** @phpstan-import-type TypeAlias */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'TypeAlias',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
35,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid missing from with alias',
|
|
|
|
'/** @phpstan-import-type TypeAlias as DifferentAlias */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'TypeAlias as DifferentAlias',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'as',
|
|
|
|
Lexer::TOKEN_IDENTIFIER,
|
|
|
|
35,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'invalid empty',
|
|
|
|
'/** @phpstan-import-type */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@phpstan-import-type',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'*/',
|
|
|
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
|
|
|
25,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2019-05-09 15:05:45 +02:00
|
|
|
public function providerDebug(): \Iterator
|
|
|
|
{
|
|
|
|
$sample = '/**
|
|
|
|
* Returns the schema for the field.
|
|
|
|
*
|
|
|
|
* This method is static because the field schema information is needed on
|
|
|
|
* creation of the field. FieldItemInterface objects instantiated at that
|
|
|
|
* time are not reliable as field settings might be missing.
|
|
|
|
*
|
|
|
|
* Computed fields having no schema should return an empty array.
|
|
|
|
*/';
|
|
|
|
yield [
|
|
|
|
'OK class line',
|
|
|
|
$sample,
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode('Returns the schema for the field.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('This method is static because the field schema information is needed on
|
|
|
|
creation of the field. FieldItemInterface objects instantiated at that
|
|
|
|
time are not reliable as field settings might be missing.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('Computed fields having no schema should return an empty array.'),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2019-04-27 00:02:37 +02:00
|
|
|
public function provideRealWorldExampleData(): \Iterator
|
2019-04-30 05:46:33 +02:00
|
|
|
{
|
|
|
|
$sample = "/**
|
|
|
|
* Returns the schema for the field.
|
|
|
|
*
|
|
|
|
* This method is static because the field schema information is needed on
|
|
|
|
* creation of the field. FieldItemInterface objects instantiated at that
|
|
|
|
* time are not reliable as field settings might be missing.
|
|
|
|
*
|
|
|
|
* Computed fields having no schema should return an empty array.
|
|
|
|
*
|
|
|
|
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface \$field_definition
|
|
|
|
* The field definition.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* An empty array if there is no schema, or an associative array with the
|
|
|
|
* following key/value pairs:
|
|
|
|
* - columns: An array of Schema API column specifications, keyed by column
|
|
|
|
* name. The columns need to be a subset of the properties defined in
|
|
|
|
* propertyDefinitions(). The 'not null' property is ignored if present,
|
|
|
|
* as it is determined automatically by the storage controller depending
|
|
|
|
* on the table layout and the property definitions. It is recommended to
|
|
|
|
* avoid having the column definitions depend on field settings when
|
|
|
|
* possible. No assumptions should be made on how storage engines
|
|
|
|
* internally use the original column name to structure their storage.
|
|
|
|
* - unique keys: (optional) An array of Schema API unique key definitions.
|
|
|
|
* Only columns that appear in the 'columns' array are allowed.
|
|
|
|
* - indexes: (optional) An array of Schema API index definitions. Only
|
|
|
|
* columns that appear in the 'columns' array are allowed. Those indexes
|
|
|
|
* will be used as default indexes. Field definitions can specify
|
|
|
|
* additional indexes or, at their own risk, modify the default indexes
|
|
|
|
* specified by the field-type module. Some storage engines might not
|
|
|
|
* support indexes.
|
|
|
|
* - foreign keys: (optional) An array of Schema API foreign key
|
|
|
|
* definitions. Note, however, that the field data is not necessarily
|
|
|
|
* stored in SQL. Also, the possible usage is limited, as you cannot
|
|
|
|
* specify another field as related, only existing SQL tables,
|
|
|
|
* such as {taxonomy_term_data}.
|
|
|
|
*/";
|
|
|
|
yield [
|
2019-05-09 15:05:45 +02:00
|
|
|
'OK FieldItemInterface::schema',
|
2019-04-30 05:46:33 +02:00
|
|
|
$sample,
|
|
|
|
new PhpDocNode([
|
2019-05-09 15:05:45 +02:00
|
|
|
new PhpDocTextNode('Returns the schema for the field.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('This method is static because the field schema information is needed on
|
2019-05-09 14:36:02 +02:00
|
|
|
creation of the field. FieldItemInterface objects instantiated at that
|
2019-05-09 15:05:45 +02:00
|
|
|
time are not reliable as field settings might be missing.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('Computed fields having no schema should return an empty array.'),
|
2019-04-30 05:46:33 +02:00
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('\Drupal\Core\Field\FieldStorageDefinitionInterface'),
|
|
|
|
false,
|
|
|
|
'$field_definition',
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTextNode('The field definition.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('array'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
2021-03-15 09:45:44 +01:00
|
|
|
new PhpDocTextNode("An empty array if there is no schema, or an associative array with the
|
|
|
|
following key/value pairs:
|
|
|
|
- columns: An array of Schema API column specifications, keyed by column
|
|
|
|
name. The columns need to be a subset of the properties defined in
|
|
|
|
propertyDefinitions(). The 'not null' property is ignored if present,
|
|
|
|
as it is determined automatically by the storage controller depending
|
|
|
|
on the table layout and the property definitions. It is recommended to
|
|
|
|
avoid having the column definitions depend on field settings when
|
|
|
|
possible. No assumptions should be made on how storage engines
|
|
|
|
internally use the original column name to structure their storage.
|
|
|
|
- unique keys: (optional) An array of Schema API unique key definitions.
|
|
|
|
Only columns that appear in the 'columns' array are allowed.
|
|
|
|
- indexes: (optional) An array of Schema API index definitions. Only
|
|
|
|
columns that appear in the 'columns' array are allowed. Those indexes
|
|
|
|
will be used as default indexes. Field definitions can specify
|
|
|
|
additional indexes or, at their own risk, modify the default indexes
|
|
|
|
specified by the field-type module. Some storage engines might not
|
|
|
|
support indexes.
|
|
|
|
- foreign keys: (optional) An array of Schema API foreign key
|
|
|
|
definitions. Note, however, that the field data is not necessarily
|
|
|
|
stored in SQL. Also, the possible usage is limited, as you cannot
|
|
|
|
specify another field as related, only existing SQL tables,
|
|
|
|
such as {taxonomy_term_data}."),
|
2019-04-30 05:46:33 +02:00
|
|
|
]),
|
|
|
|
];
|
2019-05-09 15:05:45 +02:00
|
|
|
|
|
|
|
$sample = '/**
|
|
|
|
* Parses a chunked request and return relevant information.
|
|
|
|
*
|
|
|
|
* This function must return an array containing the following
|
|
|
|
* keys and their corresponding values:
|
|
|
|
* - last: Wheter this is the last chunk of the uploaded file
|
|
|
|
* - uuid: A unique id which distinguishes two uploaded files
|
|
|
|
* This uuid must stay the same among the task of
|
|
|
|
* uploading a chunked file.
|
|
|
|
* - index: A numerical representation of the currently uploaded
|
|
|
|
* chunk. Must be higher that in the previous request.
|
|
|
|
* - orig: The original file name.
|
|
|
|
*
|
|
|
|
* @param Request $request - The request object
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/';
|
|
|
|
yield [
|
|
|
|
'OK AbstractChunkedController::parseChunkedRequest',
|
|
|
|
$sample,
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode('Parses a chunked request and return relevant information.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode('This function must return an array containing the following
|
2021-03-15 09:45:44 +01:00
|
|
|
keys and their corresponding values:
|
|
|
|
- last: Wheter this is the last chunk of the uploaded file
|
|
|
|
- uuid: A unique id which distinguishes two uploaded files
|
|
|
|
This uuid must stay the same among the task of
|
|
|
|
uploading a chunked file.
|
|
|
|
- index: A numerical representation of the currently uploaded
|
|
|
|
chunk. Must be higher that in the previous request.
|
|
|
|
- orig: The original file name.'),
|
2019-05-09 15:05:45 +02:00
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@param',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new IdentifierTypeNode('Request'),
|
|
|
|
false,
|
|
|
|
'$request',
|
|
|
|
'- The request object'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('array'),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2020-04-30 15:03:40 +02:00
|
|
|
|
2021-03-15 09:45:44 +01:00
|
|
|
yield [
|
|
|
|
'Description with indented <code>',
|
|
|
|
"/**
|
|
|
|
* Finder allows searching through directory trees using iterator.
|
|
|
|
*
|
|
|
|
* <code>
|
|
|
|
* Finder::findFiles('*.php')
|
|
|
|
* ->size('> 10kB')
|
|
|
|
* ->from('.')
|
|
|
|
* ->exclude('temp');
|
|
|
|
* </code>
|
|
|
|
*/",
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTextNode('Finder allows searching through directory trees using iterator.'),
|
|
|
|
new PhpDocTextNode(''),
|
|
|
|
new PhpDocTextNode("<code>
|
|
|
|
Finder::findFiles('*.php')
|
|
|
|
->size('> 10kB')
|
|
|
|
->from('.')
|
|
|
|
->exclude('temp');
|
|
|
|
</code>"),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2020-04-30 15:03:40 +02:00
|
|
|
yield [
|
|
|
|
'string literals in @return',
|
|
|
|
"/** @return 'foo'|'bar' */",
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new UnionTypeNode([
|
|
|
|
new ConstTypeNode(new ConstExprStringNode('foo')),
|
|
|
|
new ConstTypeNode(new ConstExprStringNode('bar')),
|
|
|
|
]),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2020-05-04 22:30:43 +02:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'malformed const fetch',
|
|
|
|
'/** @param Foo::** $a */',
|
|
|
|
new PhpDocNode([
|
2020-05-04 22:59:45 +02:00
|
|
|
new PhpDocTagNode('@param', new InvalidTagValueNode('Foo::** $a', new \PHPStan\PhpDocParser\Parser\ParserException('*', Lexer::TOKEN_WILDCARD, 17, Lexer::TOKEN_VARIABLE))),
|
2020-05-04 22:30:43 +02:00
|
|
|
]),
|
|
|
|
];
|
2020-05-04 15:56:40 +02:00
|
|
|
|
|
|
|
yield [
|
|
|
|
'multiline generic types',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @implements Foo<' . PHP_EOL .
|
|
|
|
' * A, B' . PHP_EOL .
|
|
|
|
' * >' . PHP_EOL .
|
|
|
|
' */',
|
2020-05-05 09:56:14 +02:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@implements',
|
|
|
|
new ImplementsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'multiline generic types - leading comma',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @implements Foo<' . PHP_EOL .
|
|
|
|
' * A' . PHP_EOL .
|
|
|
|
' * , B' . PHP_EOL .
|
|
|
|
' * >' . PHP_EOL .
|
|
|
|
' */',
|
2020-05-05 10:25:00 +02:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@implements',
|
|
|
|
new ImplementsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'multiline generic types - traling comma',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @implements Foo<' . PHP_EOL .
|
|
|
|
' * A,' . PHP_EOL .
|
|
|
|
' * B,' . PHP_EOL .
|
|
|
|
' * >' . PHP_EOL .
|
|
|
|
' */',
|
2020-05-04 15:56:40 +02:00
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@implements',
|
|
|
|
new ImplementsTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('A'),
|
|
|
|
new IdentifierTypeNode('B'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
2019-04-30 05:46:33 +02:00
|
|
|
}
|
|
|
|
|
2020-06-08 23:36:09 +02:00
|
|
|
public function provideDescriptionWithOrWithoutHtml(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'Description with HTML tags in @return tag (close tags together)',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @return Foo <strong>Important <i>description</i></strong>' . PHP_EOL .
|
|
|
|
' */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
'<strong>Important <i>description</i></strong>'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'Description with HTML tags in @throws tag (closed tags with text between)',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @throws FooException <strong>Important <em>description</em> etc</strong>' . PHP_EOL .
|
|
|
|
' */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@throws',
|
|
|
|
new ThrowsTagValueNode(
|
|
|
|
new IdentifierTypeNode('FooException'),
|
|
|
|
'<strong>Important <em>description</em> etc</strong>'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'Description with HTML tags in @mixin tag',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @mixin Mixin <strong>Important description</strong>' . PHP_EOL .
|
|
|
|
' */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@mixin',
|
|
|
|
new MixinTagValueNode(
|
|
|
|
new IdentifierTypeNode('Mixin'),
|
|
|
|
'<strong>Important description</strong>'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
yield [
|
|
|
|
'Description with unclosed HTML tags in @return tag - unclosed HTML tag is parsed as generics',
|
|
|
|
'/**' . PHP_EOL .
|
|
|
|
' * @return Foo <strong>Important description' . PHP_EOL .
|
|
|
|
' */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@return',
|
|
|
|
new ReturnTagValueNode(
|
|
|
|
new GenericTypeNode(
|
|
|
|
new IdentifierTypeNode('Foo'),
|
|
|
|
[
|
|
|
|
new IdentifierTypeNode('strong'),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
'Important description'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-05-04 11:11:57 +02:00
|
|
|
public function dataParseTagValue(): array
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
[
|
|
|
|
'@param',
|
|
|
|
'DateTimeImmutable::ATOM $a',
|
|
|
|
new ParamTagValueNode(
|
|
|
|
new ConstTypeNode(new ConstFetchNode('DateTimeImmutable', 'ATOM')),
|
|
|
|
false,
|
|
|
|
'$a',
|
|
|
|
''
|
|
|
|
),
|
|
|
|
],
|
2021-03-19 10:32:01 +01:00
|
|
|
[
|
|
|
|
'@var',
|
|
|
|
'$foo string[]',
|
|
|
|
new InvalidTagValueNode(
|
|
|
|
'$foo string[]',
|
|
|
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
|
|
|
'$foo',
|
|
|
|
Lexer::TOKEN_VARIABLE,
|
|
|
|
0,
|
|
|
|
Lexer::TOKEN_IDENTIFIER
|
|
|
|
)
|
|
|
|
),
|
|
|
|
],
|
2020-05-04 11:11:57 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2021-02-19 12:57:27 +01:00
|
|
|
public function provideTagsWithNumbers(): \Iterator
|
|
|
|
{
|
|
|
|
yield [
|
|
|
|
'OK without description and tag with number in it',
|
|
|
|
'/** @special3 Foo */',
|
|
|
|
new PhpDocNode([
|
|
|
|
new PhpDocTagNode(
|
|
|
|
'@special3',
|
|
|
|
new GenericTagValueNode('Foo')
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-05-04 11:11:57 +02:00
|
|
|
/**
|
|
|
|
* @dataProvider dataParseTagValue
|
|
|
|
* @param string $tag
|
|
|
|
* @param string $phpDoc
|
|
|
|
* @param PhpDocNode $expectedPhpDocNode
|
|
|
|
* @param int $nextTokenType
|
|
|
|
*/
|
|
|
|
public function testParseTagValue(string $tag, string $phpDoc, Node $expectedPhpDocNode, int $nextTokenType = Lexer::TOKEN_END): void
|
|
|
|
{
|
|
|
|
$tokens = new TokenIterator($this->lexer->tokenize($phpDoc));
|
|
|
|
$actualPhpDocNode = $this->phpDocParser->parseTagValue($tokens, $tag);
|
|
|
|
|
|
|
|
$this->assertEquals($expectedPhpDocNode, $actualPhpDocNode);
|
|
|
|
$this->assertSame((string) $expectedPhpDocNode, (string) $actualPhpDocNode);
|
|
|
|
$this->assertSame($nextTokenType, $tokens->currentTokenType());
|
|
|
|
}
|
|
|
|
|
2017-11-18 21:58:26 +01:00
|
|
|
}
|