Skip to content

Commit

Permalink
Add RequireExtends and RequireImplements attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-granados committed Feb 24, 2024
1 parent 833e1b2 commit d726548
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ These are the available attributes and their corresponding PHPDoc annotations:
| [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` |
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"require": {
"php": ">=8.0",
"ext-simplexml": "*",
"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",
"vimeo/psalm": "^5"
},
"require-dev": {
Expand Down
28 changes: 28 additions & 0 deletions tests/RequireExtendsAttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php


namespace test\PhpStaticAnalysis\PsalmPlugin;

class RequireExtendsAttributeTest extends BaseAttributeTestCase
{
public function testClassRequireExtendsAttribute(): void
{
$errors = $this->analyzeTestFile('/data/RequireExtends/TraitRequireExtendsAttribute.php');
$expectedErrors = [
'test\PhpStaticAnalysis\PsalmPlugin\data\RequireExtends\TraitRequireExtendsAttribute requires using class to extend test\PhpStaticAnalysis\PsalmPlugin\data\RequireExtends\ClassRequireExtendsAttribute, but test\PhpStaticAnalysis\PsalmPlugin\data\RequireExtends\ClassRequireExtendsAttributeChild2 does not' => 23,
];

$this->checkExpectedErrors($errors, $expectedErrors);
}

public function testInvalidClassRequireExtendsAttribute(): void
{
$errors = $this->analyzeTestFile( '/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php');

$expectedErrors = [
'Attribute RequireExtends cannot be used on a property' => 10,
];

$this->checkExpectedErrors($errors, $expectedErrors);
}
}
27 changes: 27 additions & 0 deletions tests/RequireImplementsAttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin;

class RequireImplementsAttributeTest extends BaseAttributeTestCase
{
public function testClassRequireImplementsAttribute(): void
{
$errors = $this->analyzeTestFile('/data/RequireImplements/TraitRequireImplementsAttribute.php');
$expectedErrors = [
'test\PhpStaticAnalysis\PsalmPlugin\data\RequireImplements\TraitRequireImplementsAttribute requires using class to implement test\PhpStaticAnalysis\PsalmPlugin\data\RequireImplements\InterfaceRequireImplementsAttribute3, but test\PhpStaticAnalysis\PsalmPlugin\data\RequireImplements\ClassRequireImplementsAttribute2 does not' => 35,
];

$this->checkExpectedErrors($errors, $expectedErrors);
}

public function testInvalidClassRequireImplementsAttribute(): void
{
$errors = $this->analyzeTestFile( '/data/RequireImplements/InvalidTraitRequireImplementsAttribute.php');

$expectedErrors = [
'Attribute RequireImplements cannot be used on a property' => 10,
];

$this->checkExpectedErrors($errors, $expectedErrors);
}
}
21 changes: 21 additions & 0 deletions tests/data/RequireExtends/InvalidTraitRequireExtendsAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\RequireExtends;

use PhpStaticAnalysis\Attributes\RequireExtends;

#[RequireExtends('InvalidClassRequireExtendsAttribute')]
trait InvalidTraitRequireExtendsAttribute
{
#[RequireExtends('InvalidClassRequireExtendsAttribute')]
public string $name = '';
}

class InvalidClassRequireExtendsAttribute
{
}

class InvalidClassRequireExtendsAttributeChild extends InvalidClassRequireExtendsAttribute
{
use InvalidTraitRequireExtendsAttribute;
}
24 changes: 24 additions & 0 deletions tests/data/RequireExtends/TraitRequireExtendsAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\RequireExtends;

use PhpStaticAnalysis\Attributes\RequireExtends;

#[RequireExtends('ClassRequireExtendsAttribute')] // the class using this trait needs to extend this class
trait TraitRequireExtendsAttribute
{
}

class ClassRequireExtendsAttribute
{
}

class ClassRequireExtendsAttributeChild extends ClassRequireExtendsAttribute
{
use TraitRequireExtendsAttribute;
}

class ClassRequireExtendsAttributeChild2
{
use TraitRequireExtendsAttribute;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\RequireImplements;

use PhpStaticAnalysis\Attributes\RequireImplements;

#[RequireImplements('InvalidInterfaceRequireImplementsAttribute')]
trait InvalidTraitRequireImplementsAttribute
{
#[RequireImplements('InvalidInterfaceRequireImplementsAttribute')]
public string $name = '';
}

interface InvalidInterfaceRequireImplementsAttribute
{
}

class InvalidClassRequireImplementsAttribute implements InvalidInterfaceRequireImplementsAttribute
{
use InvalidTraitRequireImplementsAttribute;
}
36 changes: 36 additions & 0 deletions tests/data/RequireImplements/TraitRequireImplementsAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\RequireImplements;

use PhpStaticAnalysis\Attributes\RequireImplements;

#[RequireImplements('InterfaceRequireImplementsAttribute')] // the class that uses this trait needs to implement these interfaces
#[RequireImplements(
'InterfaceRequireImplementsAttribute2',
'InterfaceRequireImplementsAttribute3'
)]
trait TraitRequireImplementsAttribute
{
}

interface InterfaceRequireImplementsAttribute
{
}

interface InterfaceRequireImplementsAttribute2
{
}

interface InterfaceRequireImplementsAttribute3
{
}

class ClassRequireImplementsAttribute implements InterfaceRequireImplementsAttribute, InterfaceRequireImplementsAttribute2, InterfaceRequireImplementsAttribute3
{
use TraitRequireImplementsAttribute;
}

class ClassRequireImplementsAttribute2 implements InterfaceRequireImplementsAttribute, InterfaceRequireImplementsAttribute2
{
use TraitRequireImplementsAttribute;
}

0 comments on commit d726548

Please sign in to comment.