|
60 | 60 | use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
|
61 | 61 | use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
|
62 | 62 | use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
| 63 | +use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode; |
63 | 64 | use PHPStan\PhpDocParser\Ast\Type\InvalidTypeNode;
|
64 | 65 | use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
|
65 | 66 | use PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
|
|
71 | 72 | use PHPUnit\Framework\TestCase;
|
72 | 73 | use function count;
|
73 | 74 | use function sprintf;
|
| 75 | +use const DIRECTORY_SEPARATOR; |
74 | 76 | use const PHP_EOL;
|
75 | 77 |
|
76 | 78 | class PhpDocParserTest extends TestCase
|
@@ -4211,6 +4213,176 @@ public function provideMultiLinePhpDocData(): iterable
|
4211 | 4213 | ]),
|
4212 | 4214 | ];
|
4213 | 4215 |
|
| 4216 | +yield [ |
| 4217 | +'Multiline PHPDoc with multiple new line within union type declaration', |
| 4218 | +'/**' . PHP_EOL . |
| 4219 | +' * @param array<string, array{' . PHP_EOL . |
| 4220 | +' * foo: int,' . PHP_EOL . |
| 4221 | +' * bar?: array<string,' . PHP_EOL . |
| 4222 | +' * array{foo1: int, bar1?: true}' . PHP_EOL . |
| 4223 | +' * | array{foo1: int, foo2: true, bar1?: true}' . PHP_EOL . |
| 4224 | +' * | array{foo2: int, foo3: bool, bar2?: true}' . PHP_EOL . |
| 4225 | +' * | array{foo1: int, foo3: true, bar3?: false}' . PHP_EOL . |
| 4226 | +' * >,' . PHP_EOL . |
| 4227 | +' * }> $a' . PHP_EOL . |
| 4228 | +' */', |
| 4229 | +new PhpDocNode([ |
| 4230 | +new PhpDocTagNode('@param', new ParamTagValueNode( |
| 4231 | +new GenericTypeNode( |
| 4232 | +new IdentifierTypeNode('array'), |
| 4233 | +[ |
| 4234 | +new IdentifierTypeNode('string'), |
| 4235 | +ArrayShapeNode::createSealed([ |
| 4236 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo'), false, new IdentifierTypeNode('int')), |
| 4237 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar'), true, new GenericTypeNode( |
| 4238 | +new IdentifierTypeNode('array'), |
| 4239 | +[ |
| 4240 | +new IdentifierTypeNode('string'), |
| 4241 | +new UnionTypeNode([ |
| 4242 | +ArrayShapeNode::createSealed([ |
| 4243 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4244 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar1'), true, new IdentifierTypeNode('true')), |
| 4245 | +]), |
| 4246 | +ArrayShapeNode::createSealed([ |
| 4247 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4248 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo2'), false, new IdentifierTypeNode('true')), |
| 4249 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar1'), true, new IdentifierTypeNode('true')), |
| 4250 | +]), |
| 4251 | +ArrayShapeNode::createSealed([ |
| 4252 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo2'), false, new IdentifierTypeNode('int')), |
| 4253 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo3'), false, new IdentifierTypeNode('bool')), |
| 4254 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar2'), true, new IdentifierTypeNode('true')), |
| 4255 | +]), |
| 4256 | +ArrayShapeNode::createSealed([ |
| 4257 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4258 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo3'), false, new IdentifierTypeNode('true')), |
| 4259 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar3'), true, new IdentifierTypeNode('false')), |
| 4260 | +]), |
| 4261 | +]), |
| 4262 | +], |
| 4263 | +[ |
| 4264 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4265 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4266 | +], |
| 4267 | +)), |
| 4268 | +]), |
| 4269 | +], |
| 4270 | +[ |
| 4271 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4272 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4273 | +], |
| 4274 | +), |
| 4275 | +false, |
| 4276 | +'$a', |
| 4277 | +'', |
| 4278 | +false, |
| 4279 | +)), |
| 4280 | +]), |
| 4281 | +]; |
| 4282 | + |
| 4283 | +yield [ |
| 4284 | +'Multiline PHPDoc with multiple new line within intersection type declaration', |
| 4285 | +'/**' . PHP_EOL . |
| 4286 | +' * @param array<string, array{' . PHP_EOL . |
| 4287 | +' * foo: int,' . PHP_EOL . |
| 4288 | +' * bar?: array<string,' . PHP_EOL . |
| 4289 | +' * array{foo1: int, bar1?: true}' . PHP_EOL . |
| 4290 | +' * & array{foo1: int, foo2: true, bar1?: true}' . PHP_EOL . |
| 4291 | +' * & array{foo2: int, foo3: bool, bar2?: true}' . PHP_EOL . |
| 4292 | +' * & array{foo1: int, foo3: true, bar3?: false}' . PHP_EOL . |
| 4293 | +' * >,' . PHP_EOL . |
| 4294 | +' * }> $a' . PHP_EOL . |
| 4295 | +' */', |
| 4296 | +new PhpDocNode([ |
| 4297 | +new PhpDocTagNode('@param', new ParamTagValueNode( |
| 4298 | +new GenericTypeNode( |
| 4299 | +new IdentifierTypeNode('array'), |
| 4300 | +[ |
| 4301 | +new IdentifierTypeNode('string'), |
| 4302 | +ArrayShapeNode::createSealed([ |
| 4303 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo'), false, new IdentifierTypeNode('int')), |
| 4304 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar'), true, new GenericTypeNode( |
| 4305 | +new IdentifierTypeNode('array'), |
| 4306 | +[ |
| 4307 | +new IdentifierTypeNode('string'), |
| 4308 | +new IntersectionTypeNode([ |
| 4309 | +ArrayShapeNode::createSealed([ |
| 4310 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4311 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar1'), true, new IdentifierTypeNode('true')), |
| 4312 | +]), |
| 4313 | +ArrayShapeNode::createSealed([ |
| 4314 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4315 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo2'), false, new IdentifierTypeNode('true')), |
| 4316 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar1'), true, new IdentifierTypeNode('true')), |
| 4317 | +]), |
| 4318 | +ArrayShapeNode::createSealed([ |
| 4319 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo2'), false, new IdentifierTypeNode('int')), |
| 4320 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo3'), false, new IdentifierTypeNode('bool')), |
| 4321 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar2'), true, new IdentifierTypeNode('true')), |
| 4322 | +]), |
| 4323 | +ArrayShapeNode::createSealed([ |
| 4324 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo1'), false, new IdentifierTypeNode('int')), |
| 4325 | +new ArrayShapeItemNode(new IdentifierTypeNode('foo3'), false, new IdentifierTypeNode('true')), |
| 4326 | +new ArrayShapeItemNode(new IdentifierTypeNode('bar3'), true, new IdentifierTypeNode('false')), |
| 4327 | +]), |
| 4328 | +]), |
| 4329 | +], |
| 4330 | +[ |
| 4331 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4332 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4333 | +], |
| 4334 | +)), |
| 4335 | +]), |
| 4336 | +], |
| 4337 | +[ |
| 4338 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4339 | +GenericTypeNode::VARIANCE_INVARIANT, |
| 4340 | +], |
| 4341 | +), |
| 4342 | +false, |
| 4343 | +'$a', |
| 4344 | +'', |
| 4345 | +false, |
| 4346 | +)), |
| 4347 | +]), |
| 4348 | +]; |
| 4349 | + |
| 4350 | +yield [ |
| 4351 | +'Multiline PHPDoc with multiple new line being invalid due to union and intersection type declaration', |
| 4352 | +'/**' . PHP_EOL . |
| 4353 | +' * @param array<string, array{' . PHP_EOL . |
| 4354 | +' * foo: int,' . PHP_EOL . |
| 4355 | +' * bar?: array<string,' . PHP_EOL . |
| 4356 | +' * array{foo1: int, bar1?: true}' . PHP_EOL . |
| 4357 | +' * & array{foo1: int, foo2: true, bar1?: true}' . PHP_EOL . |
| 4358 | +' * | array{foo2: int, foo3: bool, bar2?: true}' . PHP_EOL . |
| 4359 | +' * & array{foo1: int, foo3: true, bar3?: false}' . PHP_EOL . |
| 4360 | +' * >,' . PHP_EOL . |
| 4361 | +' * }> $a' . PHP_EOL . |
| 4362 | +' */', |
| 4363 | +new PhpDocNode([ |
| 4364 | +new PhpDocTagNode('@param', new InvalidTagValueNode( |
| 4365 | +'array<string, array{' . PHP_EOL . |
| 4366 | +' foo: int,' . PHP_EOL . |
| 4367 | +' bar?: array<string,' . PHP_EOL . |
| 4368 | +' array{foo1: int, bar1?: true}' . PHP_EOL . |
| 4369 | +' & array{foo1: int, foo2: true, bar1?: true}' . PHP_EOL . |
| 4370 | +' | array{foo2: int, foo3: bool, bar2?: true}' . PHP_EOL . |
| 4371 | +' & array{foo1: int, foo3: true, bar3?: false}' . PHP_EOL . |
| 4372 | +' >,' . PHP_EOL . |
| 4373 | +'}> $a', |
| 4374 | +new ParserException( |
| 4375 | +'?', |
| 4376 | +Lexer::TOKEN_NULLABLE, |
| 4377 | +DIRECTORY_SEPARATOR === '\\' ? 65 : 62, |
| 4378 | +Lexer::TOKEN_CLOSE_CURLY_BRACKET, |
| 4379 | +null, |
| 4380 | +4, |
| 4381 | +), |
| 4382 | +)), |
| 4383 | +]), |
| 4384 | +]; |
| 4385 | + |
4214 | 4386 | /**
|
4215 | 4387 | * @return object{
|
4216 | 4388 | * a: int,
|
|
0 commit comments