From cd6091ad69bce5ea42f733269e0bd4c3271ecd23 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Tue, 5 Mar 2024 09:19:22 +0100 Subject: [PATCH] Add DefineType and ImportType attributes --- README.md | 2 + composer.json | 4 +- tests/DefineTypeAttributeTest.php | 40 +++++++++++++++++++ tests/ImportTypeAttributeTest.php | 37 +++++++++++++++++ tests/TypeAttributeTest.php | 12 +++--- .../DefineType/ClassDefineTypeAttribute.php | 21 ++++++++++ .../InterfaceDefineTypeAttribute.php | 10 +++++ .../InvalidClassDefineTypeAttribute.php | 17 ++++++++ .../DefineType/TraitDefineTypeAttribute.php | 10 +++++ .../ImportType/ClassImportTypeAttribute.php | 30 ++++++++++++++ .../InterfaceImportTypeAttribute.php | 16 ++++++++ .../InvalidClassImportTypeAttribute.php | 23 +++++++++++ .../ImportType/TraitImportTypeAttribute.php | 16 ++++++++ .../Type/InvalidPropertyTypeAttribute.php | 7 +++- tests/data/Type/PropertyTypeAttribute.php | 1 + 15 files changed, 237 insertions(+), 9 deletions(-) create mode 100644 tests/DefineTypeAttributeTest.php create mode 100644 tests/ImportTypeAttributeTest.php create mode 100644 tests/data/DefineType/ClassDefineTypeAttribute.php create mode 100644 tests/data/DefineType/InterfaceDefineTypeAttribute.php create mode 100644 tests/data/DefineType/InvalidClassDefineTypeAttribute.php create mode 100644 tests/data/DefineType/TraitDefineTypeAttribute.php create mode 100644 tests/data/ImportType/ClassImportTypeAttribute.php create mode 100644 tests/data/ImportType/InterfaceImportTypeAttribute.php create mode 100644 tests/data/ImportType/InvalidClassImportTypeAttribute.php create mode 100644 tests/data/ImportType/TraitImportTypeAttribute.php diff --git a/README.md b/README.md index 744116e..2a07fc6 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,10 @@ These are the available attributes and their corresponding PHPDoc annotations: | Attribute | PHPDoc Annotations | |-------------------------------------------------------------------------------------------------------------------|--------------------------------------| +| [DefineType](https://github.com/php-static-analysis/attributes/blob/main/doc/DefineType.md) | `@type` | | [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` | | [Immmutable](https://github.com/php-static-analysis/attributes/blob/main/doc/Immmutable.md) | `@immmutable` | +| [ImportType](https://github.com/php-static-analysis/attributes/blob/main/doc/ImportType.md) | `@import-type` | | [Impure](https://github.com/php-static-analysis/attributes/blob/main/doc/Impure.md) | `@impure` | | [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` | diff --git a/composer.json b/composer.json index d0cb790..b1f8640 100644 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ "prefer-stable": true, "require": { "php": ">=8.0", - "php-static-analysis/attributes": "^0.1.17 || dev-main", - "php-static-analysis/node-visitor": "^0.1.17 || dev-main", + "php-static-analysis/attributes": "^0.2.2 || dev-main", + "php-static-analysis/node-visitor": "^0.2.2 || dev-main", "phpstan/phpstan": "^1.8" }, "require-dev": { diff --git a/tests/DefineTypeAttributeTest.php b/tests/DefineTypeAttributeTest.php new file mode 100644 index 0000000..dc23dd9 --- /dev/null +++ b/tests/DefineTypeAttributeTest.php @@ -0,0 +1,40 @@ +analyse(__DIR__ . '/data/DefineType/ClassDefineTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testInterfaceDefineTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/DefineType/InterfaceDefineTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testTraitDefineTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/DefineType/TraitDefineTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testInvalidClassDefineTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/DefineType/InvalidClassDefineTypeAttribute.php'); + + $expectedErrors = [ + 'PHPDoc tag @phpstan-type has invalid value (): Unexpected token "\n * ", expected type at offset 20' => 7, + 'PHPDoc tag @phpstan-type name has invalid value: Unexpected token "(", expected TOKEN_PHPDOC_EOL at offset 72' => 7, + 'PHPDoc tag @phpstan-type string has invalid value: Unexpected token "\n * ", expected type at offset 44' => 7, + 'Parameter #1 ...$types of attribute class PhpStaticAnalysis\Attributes\DefineType constructor expects string, int given.' => 7, + 'Type alias has an invalid name: string.' => 7, + 'Attribute class PhpStaticAnalysis\Attributes\DefineType does not have the method target.' => 12, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } +} diff --git a/tests/ImportTypeAttributeTest.php b/tests/ImportTypeAttributeTest.php new file mode 100644 index 0000000..e9aba3e --- /dev/null +++ b/tests/ImportTypeAttributeTest.php @@ -0,0 +1,37 @@ +analyse(__DIR__ . '/data/ImportType/ClassImportTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testInterfaceImportTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/ImportType/InterfaceImportTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testTraitImportTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/ImportType/TraitImportTypeAttribute.php'); + $this->assertCount(0, $errors); + } + + public function testInvalidClassImportTypeAttribute(): void + { + $errors = $this->analyse(__DIR__ . '/data/ImportType/InvalidClassImportTypeAttribute.php'); + + $expectedErrors = [ + 'PHPDoc tag @phpstan-import-type has invalid value (Unexpected token "(", expected \'*/\' at offset 98 on line 4): Unexpected token "(", expected \'*/\' at offset 98' => 8, + 'Parameter #1 ...$from of attribute class PhpStaticAnalysis\Attributes\ImportType constructor expects string, int given.' => 8, + 'Attribute class PhpStaticAnalysis\Attributes\ImportType does not have the method target.' => 13, + ]; + + $this->checkExpectedErrors($errors, $expectedErrors); + } +} diff --git a/tests/TypeAttributeTest.php b/tests/TypeAttributeTest.php index 49d8cf2..14f03b3 100644 --- a/tests/TypeAttributeTest.php +++ b/tests/TypeAttributeTest.php @@ -15,12 +15,12 @@ public function testInvalidPropertyTypeAttribute(): void $errors = $this->analyse(__DIR__ . '/data/Type/InvalidPropertyTypeAttribute.php'); $expectedErrors = [ - 'Attribute class PhpStaticAnalysis\Attributes\Type does not have the class target.' => 7, - 'PHPDoc tag @var has invalid value (): Unexpected token "\n ", expected type at offset 11' => 10, - 'Parameter #1 $type of attribute class PhpStaticAnalysis\Attributes\Type constructor expects string, int given.' => 10, - 'Attribute class PhpStaticAnalysis\Attributes\Type is not repeatable but is already present above the property.' => 14, - 'Attribute class PhpStaticAnalysis\Attributes\Type constructor invoked with 2 parameters, 1 required.' => 17, - 'PHPDoc tag @var has invalid value ($a + $b): Unexpected token "$a", expected type at offset 12' => 20, + 'PHPDoc tag @var has invalid value (): Unexpected token "\n ", expected type at offset 11' => 9, + 'Parameter #1 $type of attribute class PhpStaticAnalysis\Attributes\Type constructor expects string, int given.' => 9, + 'Attribute class PhpStaticAnalysis\Attributes\Type is not repeatable but is already present above the property.' => 13, + 'Attribute class PhpStaticAnalysis\Attributes\Type constructor invoked with 2 parameters, 1 required.' => 16, + 'PHPDoc tag @var has invalid value ($a + $b): Unexpected token "$a", expected type at offset 12' => 19, + 'Attribute class PhpStaticAnalysis\Attributes\Type does not have the parameter target.' => 23, ]; $this->checkExpectedErrors($errors, $expectedErrors); diff --git a/tests/data/DefineType/ClassDefineTypeAttribute.php b/tests/data/DefineType/ClassDefineTypeAttribute.php new file mode 100644 index 0000000..7f38f0e --- /dev/null +++ b/tests/data/DefineType/ClassDefineTypeAttribute.php @@ -0,0 +1,21 @@ +