mirror of
https://github.com/danog/phpdoc-parser.git
synced 2024-11-30 04:29:20 +01:00
Allow unparenthesized conditional type in conditional else branch
This commit is contained in:
parent
44615481d8
commit
5f13698464
@ -17,7 +17,7 @@ Intersection
|
|||||||
= 1*(TokenIntersection Atomic)
|
= 1*(TokenIntersection Atomic)
|
||||||
|
|
||||||
Conditional
|
Conditional
|
||||||
= 1*ByteHorizontalWs TokenIs [TokenNot] Atomic TokenNullable Atomic TokenColon Atomic
|
= 1*ByteHorizontalWs TokenIs [TokenNot] Atomic TokenNullable Type TokenColon ParenthesizedType
|
||||||
|
|
||||||
Nullable
|
Nullable
|
||||||
= TokenNullable Atomic
|
= TokenNullable Atomic
|
||||||
|
@ -242,7 +242,7 @@ class TypeParser
|
|||||||
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
|
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
|
||||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
||||||
|
|
||||||
$elseType = $this->parse($tokens);
|
$elseType = $this->subParse($tokens);
|
||||||
|
|
||||||
return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated);
|
return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated);
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ class TypeParser
|
|||||||
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
|
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
|
||||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
||||||
|
|
||||||
$elseType = $this->parse($tokens);
|
$elseType = $this->subParse($tokens);
|
||||||
|
|
||||||
return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated);
|
return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
|
|||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TypelessParamTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TypelessParamTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||||
|
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
|
||||||
|
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
|
||||||
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
||||||
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
|
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
|
||||||
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
|
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
|
||||||
@ -4381,6 +4383,178 @@ Finder::findFiles('*.php')
|
|||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'complex stub from Psalm',
|
||||||
|
'/**' . PHP_EOL .
|
||||||
|
' * @psalm-pure' . PHP_EOL .
|
||||||
|
' * @template TFlags as int-mask<0, 256, 512>' . PHP_EOL .
|
||||||
|
' *' . PHP_EOL .
|
||||||
|
' * @param string $pattern' . PHP_EOL .
|
||||||
|
' * @param string $subject' . PHP_EOL .
|
||||||
|
' * @param mixed $matches' . PHP_EOL .
|
||||||
|
' * @param TFlags $flags' . PHP_EOL .
|
||||||
|
" * @param-out (TFlags is 256 ? array<array-key, array{string, 0|positive-int}|array{'', -1}> :" . PHP_EOL .
|
||||||
|
' * TFlags is 512 ? array<array-key, string|null> :' . PHP_EOL .
|
||||||
|
' * TFlags is 768 ? array<array-key, array{string, 0|positive-int}|array{null, -1}> :' . PHP_EOL .
|
||||||
|
' * array<array-key, string>' . PHP_EOL .
|
||||||
|
' * ) $matches' . PHP_EOL .
|
||||||
|
' * @return 1|0|false' . PHP_EOL .
|
||||||
|
' * @psalm-ignore-falsable-return' . PHP_EOL .
|
||||||
|
' */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode('@psalm-pure', new GenericTagValueNode('')),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@template',
|
||||||
|
new TemplateTagValueNode(
|
||||||
|
'TFlags',
|
||||||
|
new GenericTypeNode(
|
||||||
|
new IdentifierTypeNode('int-mask'),
|
||||||
|
[
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('0')),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('256')),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('512')),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTextNode(''),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@param',
|
||||||
|
new ParamTagValueNode(
|
||||||
|
new IdentifierTypeNode('string'),
|
||||||
|
false,
|
||||||
|
'$pattern',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@param',
|
||||||
|
new ParamTagValueNode(
|
||||||
|
new IdentifierTypeNode('string'),
|
||||||
|
false,
|
||||||
|
'$subject',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@param',
|
||||||
|
new ParamTagValueNode(
|
||||||
|
new IdentifierTypeNode('mixed'),
|
||||||
|
false,
|
||||||
|
'$matches',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@param',
|
||||||
|
new ParamTagValueNode(
|
||||||
|
new IdentifierTypeNode('TFlags'),
|
||||||
|
false,
|
||||||
|
'$flags',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@param-out',
|
||||||
|
new ParamOutTagValueNode(
|
||||||
|
new ConditionalTypeNode(
|
||||||
|
new IdentifierTypeNode('TFlags'),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('256')),
|
||||||
|
new GenericTypeNode(
|
||||||
|
new IdentifierTypeNode('array'),
|
||||||
|
[
|
||||||
|
new IdentifierTypeNode('array-key'),
|
||||||
|
new UnionTypeNode([
|
||||||
|
new ArrayShapeNode([
|
||||||
|
new ArrayShapeItemNode(null, false, new IdentifierTypeNode('string')),
|
||||||
|
new ArrayShapeItemNode(
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
new UnionTypeNode([
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('0')),
|
||||||
|
new IdentifierTypeNode('positive-int'),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
new ArrayShapeNode([
|
||||||
|
new ArrayShapeItemNode(null, false, new ConstTypeNode(new ConstExprStringNode(''))),
|
||||||
|
new ArrayShapeItemNode(null, false, new ConstTypeNode(new ConstExprIntegerNode('-1'))),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
new ConditionalTypeNode(
|
||||||
|
new IdentifierTypeNode('TFlags'),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('512')),
|
||||||
|
new GenericTypeNode(
|
||||||
|
new IdentifierTypeNode('array'),
|
||||||
|
[
|
||||||
|
new IdentifierTypeNode('array-key'),
|
||||||
|
new UnionTypeNode([
|
||||||
|
new IdentifierTypeNode('string'),
|
||||||
|
new IdentifierTypeNode('null'),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
new ConditionalTypeNode(
|
||||||
|
new IdentifierTypeNode('TFlags'),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('768')),
|
||||||
|
new GenericTypeNode(
|
||||||
|
new IdentifierTypeNode('array'),
|
||||||
|
[
|
||||||
|
new IdentifierTypeNode('array-key'),
|
||||||
|
new UnionTypeNode([
|
||||||
|
new ArrayShapeNode([
|
||||||
|
new ArrayShapeItemNode(null, false, new IdentifierTypeNode('string')),
|
||||||
|
new ArrayShapeItemNode(
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
new UnionTypeNode([
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('0')),
|
||||||
|
new IdentifierTypeNode('positive-int'),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
new ArrayShapeNode([
|
||||||
|
new ArrayShapeItemNode(null, false, new IdentifierTypeNode('null')),
|
||||||
|
new ArrayShapeItemNode(null, false, new ConstTypeNode(new ConstExprIntegerNode('-1'))),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
new GenericTypeNode(
|
||||||
|
new IdentifierTypeNode('array'),
|
||||||
|
[
|
||||||
|
new IdentifierTypeNode('array-key'),
|
||||||
|
new IdentifierTypeNode('string'),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
'$matches',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@return',
|
||||||
|
new ReturnTagValueNode(
|
||||||
|
new UnionTypeNode([
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('1')),
|
||||||
|
new ConstTypeNode(new ConstExprIntegerNode('0')),
|
||||||
|
new IdentifierTypeNode('false'),
|
||||||
|
]),
|
||||||
|
''
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new PhpDocTagNode('@psalm-ignore-falsable-return', new GenericTagValueNode('')),
|
||||||
|
]),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideDescriptionWithOrWithoutHtml(): Iterator
|
public function provideDescriptionWithOrWithoutHtml(): Iterator
|
||||||
|
@ -1266,6 +1266,56 @@ class TypeParserTest extends TestCase
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'(T is Foo ? true : T is Bar ? false : null)',
|
||||||
|
new ConditionalTypeNode(
|
||||||
|
new IdentifierTypeNode('T'),
|
||||||
|
new IdentifierTypeNode('Foo'),
|
||||||
|
new IdentifierTypeNode('true'),
|
||||||
|
new ConditionalTypeNode(
|
||||||
|
new IdentifierTypeNode('T'),
|
||||||
|
new IdentifierTypeNode('Bar'),
|
||||||
|
new IdentifierTypeNode('false'),
|
||||||
|
new IdentifierTypeNode('null'),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'(T is Foo ? T is Bar ? true : false : null)',
|
||||||
|
new ParserException(
|
||||||
|
'is',
|
||||||
|
Lexer::TOKEN_IDENTIFIER,
|
||||||
|
14,
|
||||||
|
Lexer::TOKEN_COLON
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'($foo is Foo ? true : $foo is Bar ? false : null)',
|
||||||
|
new ConditionalTypeForParameterNode(
|
||||||
|
'$foo',
|
||||||
|
new IdentifierTypeNode('Foo'),
|
||||||
|
new IdentifierTypeNode('true'),
|
||||||
|
new ConditionalTypeForParameterNode(
|
||||||
|
'$foo',
|
||||||
|
new IdentifierTypeNode('Bar'),
|
||||||
|
new IdentifierTypeNode('false'),
|
||||||
|
new IdentifierTypeNode('null'),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'($foo is Foo ? $foo is Bar ? true : false : null)',
|
||||||
|
new ParserException(
|
||||||
|
'$foo',
|
||||||
|
Lexer::TOKEN_VARIABLE,
|
||||||
|
15,
|
||||||
|
Lexer::TOKEN_IDENTIFIER
|
||||||
|
),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user