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 ;
2019-03-18 22:10:28 +01:00
use PHPStan\PhpDocParser\Ast\PhpDoc\DeprecatedTagValueNode ;
2017-11-18 21:58:26 +01:00
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode ;
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode ;
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode ;
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode ;
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 ;
2017-11-18 21:58:26 +01:00
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode ;
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode ;
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 ();
$this -> phpDocParser = new PhpDocParser ( new TypeParser (), new ConstExprParser ());
}
/**
2017-12-16 16:05:37 +01:00
* @ dataProvider provideParamTagsData
* @ dataProvider provideVarTagsData
* @ dataProvider provideReturnTagsData
* @ dataProvider provideThrowsTagsData
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
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'
)
),
]),
];
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
)
),
]),
];
}
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 (
'123' ,
Lexer :: TOKEN_INTEGER ,
20 ,
Lexer :: TOKEN_IDENTIFIER
)
)
),
]),
];
}
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
)
)
),
]),
];
}
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' ,
' /** @ deprecated text first
*
* @ deprecated text second
*/ ' ,
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' ,
' /** @ deprecated text first
* @ deprecated text second
*/ ' ,
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-04-24 18:29:53 +02:00
new DeprecatedTagValueNode ( '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.' )
),
]),
];
yield [
'OK with multiple and long descriptions' ,
' /**
* Sample class
*
* @ author Foo Baz < foo @ baz . com >
*
* @ 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 PhpDocTextNode ( 'Sample class' ),
new PhpDocTextNode ( '' ),
new PhpDocTagNode (
'@author' ,
new GenericTagValueNode ( 'Foo Baz <foo@baz.com>' )
),
new PhpDocTextNode ( '' ),
new PhpDocTagNode (
'@deprecated' ,
new DeprecatedTagValueNode ( '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.' )
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'
)
),
]),
];
}
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 1 st multi world description
* @ param Bar $bar 2 nd 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 1 st multi world description
* some text in the middle
* @ param Bar $bar 2 nd 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-04-25 17:40:59 +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 1 st 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 2 nd 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' ,
new IdentifierTypeNode ( 'mixed' ),
''
)
),
]),
];
yield [
'OK without bound' ,
'/** @template T the value type*/' ,
new PhpDocNode ([
new PhpDocTagNode (
'@template' ,
new TemplateTagValueNode (
'T' ,
new IdentifierTypeNode ( 'mixed' ),
'the value type'
)
),
]),
];
yield [
'OK without description' ,
'/** @template T of DateTime */' ,
new PhpDocNode ([
new PhpDocTagNode (
'@template' ,
new TemplateTagValueNode (
'T' ,
new IdentifierTypeNode ( 'DateTime' ),
''
)
),
]),
];
yield [
'OK with bound and description' ,
'/** @template T of DateTime the value type */' ,
new PhpDocNode ([
new PhpDocTagNode (
'@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
)
)
),
]),
];
}
2017-11-18 21:58:26 +01:00
}