| 
5 | 5 | use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprArrayNode;  | 
6 | 6 | use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;  | 
7 | 7 | use PHPStan\PhpDocParser\Ast\PhpDoc\DeprecatedTagValueNode;  | 
 | 8 | +use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;  | 
8 | 9 | use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;  | 
 | 10 | +use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;  | 
9 | 11 | use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;  | 
10 | 12 | use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;  | 
11 | 13 | use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;  | 
 | 
17 | 19 | use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;  | 
18 | 20 | use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;  | 
19 | 21 | use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;  | 
 | 22 | +use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;  | 
20 | 23 | use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;  | 
21 | 24 | use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;  | 
 | 25 | +use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;  | 
22 | 26 | use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;  | 
23 | 27 | use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;  | 
24 | 28 | use PHPStan\PhpDocParser\Lexer\Lexer;  | 
@@ -51,6 +55,7 @@ protected function setUp(): void  | 
51 | 55 | 	 * @dataProvider provideSingleLinePhpDocData  | 
52 | 56 | 	 * @dataProvider provideMultiLinePhpDocData  | 
53 | 57 | 	 * @dataProvider provideTemplateTagsData  | 
 | 58 | +	 * @dataProvider provideExtendsTagsData  | 
54 | 59 | 	 * @dataProvider provideRealWorldExampleData  | 
55 | 60 | 	 * @param string     $label  | 
56 | 61 | 	 * @param string     $input  | 
@@ -2368,6 +2373,143 @@ public function provideTemplateTagsData(): \Iterator  | 
2368 | 2373 | 		];  | 
2369 | 2374 | 	}  | 
2370 | 2375 | 
 
  | 
 | 2376 | +	public function provideExtendsTagsData(): \Iterator  | 
 | 2377 | +	{  | 
 | 2378 | +		yield [  | 
 | 2379 | +			'OK with one argument',  | 
 | 2380 | +			'/** @extends Foo<A> */',  | 
 | 2381 | +			new PhpDocNode([  | 
 | 2382 | +				new PhpDocTagNode(  | 
 | 2383 | +					'@extends',  | 
 | 2384 | +					new ExtendsTagValueNode(  | 
 | 2385 | +						new GenericTypeNode(  | 
 | 2386 | +							new IdentifierTypeNode('Foo'),  | 
 | 2387 | +							[  | 
 | 2388 | +								new IdentifierTypeNode('A'),  | 
 | 2389 | +							]  | 
 | 2390 | +						),  | 
 | 2391 | +						''  | 
 | 2392 | +					)  | 
 | 2393 | +				),  | 
 | 2394 | +			]),  | 
 | 2395 | +		];  | 
 | 2396 | + | 
 | 2397 | +		yield [  | 
 | 2398 | +			'OK with two arguments',  | 
 | 2399 | +			'/** @extends Foo<A,B> */',  | 
 | 2400 | +			new PhpDocNode([  | 
 | 2401 | +				new PhpDocTagNode(  | 
 | 2402 | +					'@extends',  | 
 | 2403 | +					new ExtendsTagValueNode(  | 
 | 2404 | +						new GenericTypeNode(  | 
 | 2405 | +							new IdentifierTypeNode('Foo'),  | 
 | 2406 | +							[  | 
 | 2407 | +								new IdentifierTypeNode('A'),  | 
 | 2408 | +								new IdentifierTypeNode('B'),  | 
 | 2409 | +							]  | 
 | 2410 | +						),  | 
 | 2411 | +						''  | 
 | 2412 | +					)  | 
 | 2413 | +				),  | 
 | 2414 | +			]),  | 
 | 2415 | +		];  | 
 | 2416 | + | 
 | 2417 | +		yield [  | 
 | 2418 | +			'OK @implements',  | 
 | 2419 | +			'/** @implements Foo<A,B> */',  | 
 | 2420 | +			new PhpDocNode([  | 
 | 2421 | +				new PhpDocTagNode(  | 
 | 2422 | +					'@implements',  | 
 | 2423 | +					new ImplementsTagValueNode(  | 
 | 2424 | +						new GenericTypeNode(  | 
 | 2425 | +							new IdentifierTypeNode('Foo'),  | 
 | 2426 | +							[  | 
 | 2427 | +								new IdentifierTypeNode('A'),  | 
 | 2428 | +								new IdentifierTypeNode('B'),  | 
 | 2429 | +							]  | 
 | 2430 | +						),  | 
 | 2431 | +						''  | 
 | 2432 | +					)  | 
 | 2433 | +				),  | 
 | 2434 | +			]),  | 
 | 2435 | +		];  | 
 | 2436 | + | 
 | 2437 | +		yield [  | 
 | 2438 | +			'OK @uses',  | 
 | 2439 | +			'/** @uses Foo<A,B> */',  | 
 | 2440 | +			new PhpDocNode([  | 
 | 2441 | +				new PhpDocTagNode(  | 
 | 2442 | +					'@uses',  | 
 | 2443 | +					new UsesTagValueNode(  | 
 | 2444 | +						new GenericTypeNode(  | 
 | 2445 | +							new IdentifierTypeNode('Foo'),  | 
 | 2446 | +							[  | 
 | 2447 | +								new IdentifierTypeNode('A'),  | 
 | 2448 | +								new IdentifierTypeNode('B'),  | 
 | 2449 | +							]  | 
 | 2450 | +						),  | 
 | 2451 | +						''  | 
 | 2452 | +					)  | 
 | 2453 | +				),  | 
 | 2454 | +			]),  | 
 | 2455 | +		];  | 
 | 2456 | + | 
 | 2457 | +		yield [  | 
 | 2458 | +			'OK with description',  | 
 | 2459 | +			'/** @extends Foo<A> extends foo*/',  | 
 | 2460 | +			new PhpDocNode([  | 
 | 2461 | +				new PhpDocTagNode(  | 
 | 2462 | +					'@extends',  | 
 | 2463 | +					new ExtendsTagValueNode(  | 
 | 2464 | +						new GenericTypeNode(  | 
 | 2465 | +							new IdentifierTypeNode('Foo'),  | 
 | 2466 | +							[new IdentifierTypeNode('A')]  | 
 | 2467 | +						),  | 
 | 2468 | +						'extends foo'  | 
 | 2469 | +					)  | 
 | 2470 | +				),  | 
 | 2471 | +			]),  | 
 | 2472 | +		];  | 
 | 2473 | + | 
 | 2474 | +		yield [  | 
 | 2475 | +			'invalid without type',  | 
 | 2476 | +			'/** @extends */',  | 
 | 2477 | +			new PhpDocNode([  | 
 | 2478 | +				new PhpDocTagNode(  | 
 | 2479 | +					'@extends',  | 
 | 2480 | +					new InvalidTagValueNode(  | 
 | 2481 | +						'',  | 
 | 2482 | +						new \PHPStan\PhpDocParser\Parser\ParserException(  | 
 | 2483 | +							'*/',  | 
 | 2484 | +							Lexer::TOKEN_CLOSE_PHPDOC,  | 
 | 2485 | +							13,  | 
 | 2486 | +							Lexer::TOKEN_IDENTIFIER  | 
 | 2487 | +						)  | 
 | 2488 | +					)  | 
 | 2489 | +				),  | 
 | 2490 | +			]),  | 
 | 2491 | +		];  | 
 | 2492 | + | 
 | 2493 | +		yield [  | 
 | 2494 | +			'invalid without arguments',  | 
 | 2495 | +			'/** @extends Foo */',  | 
 | 2496 | +			new PhpDocNode([  | 
 | 2497 | +				new PhpDocTagNode(  | 
 | 2498 | +					'@extends',  | 
 | 2499 | +					new InvalidTagValueNode(  | 
 | 2500 | +						'Foo',  | 
 | 2501 | +						new \PHPStan\PhpDocParser\Parser\ParserException(  | 
 | 2502 | +							'*/',  | 
 | 2503 | +							Lexer::TOKEN_CLOSE_PHPDOC,  | 
 | 2504 | +							17,  | 
 | 2505 | +							Lexer::TOKEN_OPEN_ANGLE_BRACKET  | 
 | 2506 | +						)  | 
 | 2507 | +					)  | 
 | 2508 | +				),  | 
 | 2509 | +			]),  | 
 | 2510 | +		];  | 
 | 2511 | +	}  | 
 | 2512 | + | 
2371 | 2513 | 	public function providerDebug(): \Iterator  | 
2372 | 2514 | 	{  | 
2373 | 2515 | 		$sample = '/**  | 
 | 
0 commit comments