diff --git a/README.md b/README.md index 54941f5..e7dee75 100644 --- a/README.md +++ b/README.md @@ -94,27 +94,29 @@ This extension works by interacting with the parser that PHPStan uses to parse t These are the available attributes and their corresponding PHPDoc annotations: -| Attribute | PHPDoc Annotations | -|-------------------------------------------------------------------------------------------------------------------|--------------------------------------| -| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` | -| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` | -| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` | -| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` | -| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` | -| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` | -| [ParamOut](https://github.com/php-static-analysis/attributes/blob/main/doc/ParamOut.md) | `@param-out` | -| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` | -| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` | -| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` | -| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` | -| [SelfOut](https://github.com/php-static-analysis/attributes/blob/main/doc/SelfOut.md) | `@self-out` `@this-out` | -| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` | +| Attribute | PHPDoc Annotations | +|------------------------------------------------------------------------------------------------------------|--------------------------------------| +| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` | +| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` | +| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` | +| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` | +| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` | +| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` | +| [ParamOut](https://github.com/php-static-analysis/attributes/blob/main/doc/ParamOut.md) | `@param-out` | +| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` | +| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` | +| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` | +| [RequireExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireExtends.md) | `@require-extends` | +| [RequireImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireImplements.md) | `@require-implements` | +| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` | +| [SelfOut](https://github.com/php-static-analysis/attributes/blob/main/doc/SelfOut.md) | `@self-out` `@this-out` | +| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` | | [TemplateContravariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateContravariant.md) | `@template-contravariant` | -| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` | -| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` | -| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` | -| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` | -| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` | +| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` | +| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` | +| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` | +| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` | +| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` | diff --git a/composer.json b/composer.json index 18b7fa1..946a26d 100644 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ "prefer-stable": true, "require": { "php": ">=8.0", - "php-static-analysis/attributes": "^0.1.13 || dev-main", - "php-static-analysis/node-visitor": "^0.1.13 || dev-main", + "php-static-analysis/attributes": "^0.1.14 || dev-main", + "php-static-analysis/node-visitor": "^0.1.14 || dev-main", "phpstan/phpstan": "^1.8" }, "require-dev": { diff --git a/tests/RequireExtendsAttributeTest.php b/tests/RequireExtendsAttributeTest.php new file mode 100644 index 0000000..8043694 --- /dev/null +++ b/tests/RequireExtendsAttributeTest.php @@ -0,0 +1,32 @@ +analyse(__DIR__ . '/data/RequireExtends/TraitRequireExtendsAttribute.php'); + $expectedErrors = [ + 'Trait test\PhpStaticAnalysis\PHPStanExtension\data\RequireExtends\TraitRequireExtendsAttribute requires using class to extend test\PhpStaticAnalysis\PHPStanExtension\data\RequireExtends\ClassRequireExtendsAttribute, but test\PhpStaticAnalysis\PHPStanExtension\data\RequireExtends\ClassRequireExtendsAttributeChild2 does not.' => 21, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } + + public function testInvalidClassRequireExtendsAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php'); + + $expectedErrors = [ + 'PHPDoc tag @phpstan-require-extends has invalid value (): Unexpected token "\n ", expected type at offset 31' => 7, + 'Parameter #1 $class of attribute class PhpStaticAnalysis\Attributes\RequireExtends constructor expects string, int given.' => 7, + 'PHPDoc tag @phpstan-require-extends contains non-object type int.' => 12, + 'PHPDoc tag @phpstan-require-extends can only be used once.' => 17, + 'Attribute class PhpStaticAnalysis\Attributes\RequireExtends is not repeatable but is already present above the class.' => 18, + 'Attribute class PhpStaticAnalysis\Attributes\RequireExtends does not have the property target.' => 21, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } +} diff --git a/tests/RequireImplementsAttributeTest.php b/tests/RequireImplementsAttributeTest.php new file mode 100644 index 0000000..1a2d573 --- /dev/null +++ b/tests/RequireImplementsAttributeTest.php @@ -0,0 +1,30 @@ +analyse(__DIR__ . '/data/RequireImplements/TraitRequireImplementsAttribute.php'); + $expectedErrors = [ + 'Trait test\PhpStaticAnalysis\PHPStanExtension\data\RequireImplements\TraitRequireImplementsAttribute requires using class to implement test\PhpStaticAnalysis\PHPStanExtension\data\RequireImplements\InterfaceRequireImplementsAttribute3, but test\PhpStaticAnalysis\PHPStanExtension\data\RequireImplements\ClassRequireImplementsAttribute2 does not.' => 33, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } + + public function testInvalidClassRequireImplementsAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/RequireImplements/InvalidTraitRequireImplementsAttribute.php'); + + $expectedErrors = [ + 'PHPDoc tag @phpstan-require-implements has invalid value (): Unexpected token "\n ", expected type at offset 34' => 7, + 'Parameter #1 ...$interfaces of attribute class PhpStaticAnalysis\Attributes\RequireImplements constructor expects string, int given.' => 7, + 'PHPDoc tag @phpstan-require-implements contains non-object type int.' => 12, + 'Attribute class PhpStaticAnalysis\Attributes\RequireImplements does not have the property target.' => 15, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } +} diff --git a/tests/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php b/tests/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php new file mode 100644 index 0000000..bd35b47 --- /dev/null +++ b/tests/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php @@ -0,0 +1,32 @@ +