Skip to content

Commit

Permalink
Add the TemplateExtends, TemplateImplements and TemplateUse attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-granados committed Feb 23, 2024
1 parent 1a0052e commit 9403aa4
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,7 @@ These are the available attributes and their corresponding PHPDoc annotations:
| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` |
| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` |
| [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` |
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.10 || dev-main",
"php-static-analysis/node-visitor": "^0.1.10 || dev-main",
"php-static-analysis/attributes": "^0.1.11 || dev-main",
"php-static-analysis/node-visitor": "^0.1.11 || dev-main",
"vimeo/psalm": "^5"
},
"require-dev": {
Expand Down
29 changes: 29 additions & 0 deletions tests/TemplateExtendsAttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin;

class TemplateExtendsAttributeTest extends BaseAttributeTestCase
{
public function testClassTemplateExtendsAttribute(): void
{
$errors = $this->analyzeTestFile( '/data/TemplateExtends/ClassTemplateExtendsAttribute.php');
$this->assertCount(0, $errors);
}

public function testInvalidClassTemplateExtendsAttribute(): void
{
$errors = $this->analyzeTestFile( '/data/TemplateExtends/InvalidClassTemplateExtendsAttribute.php');

$expectedErrors = [
'Extended class cannot be empty in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttributeChild' => 13,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttributeChild has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttribute, expecting 1' => 14,
'Argument 1 of PhpStaticAnalysis\Attributes\TemplateExtends::__construct expects string, but 0 provided' => 13,
'Invalid type \'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\+5\' in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttributeChild2' => 18,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttributeChild2 has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends\InvalidClassTemplateExtendsAttribute, expecting 1' => 19,
'Attribute TemplateExtends is not repeatable' => 24,
'Attribute TemplateExtends cannot be used on a property' => 27,
];

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

namespace test\PhpStaticAnalysis\PsalmPlugin;

class TemplateImplementsAttributeTest extends BaseAttributeTestCase
{
public function testInterfaceTemplateImplementsAttribute(): void
{
$errors = $this->analyzeTestFile('/data/TemplateImplements/InterfaceTemplateImplementsAttribute.php');
$this->assertCount(0, $errors);
}

public function testInvalidInterfaceTemplateImplementsAttribute(): void
{
$errors = $this->analyzeTestFile('/data/TemplateImplements/InvalidInterfaceTemplateImplementsAttribute.php');

$expectedErrors = [
'Extended class cannot be empty in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidClassTemplateImplementsAttribute' => 13,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidClassTemplateImplementsAttribute has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidInterfaceTemplateImplementsAttribute, expecting 1' => 14,
'Argument 1 of PhpStaticAnalysis\Attributes\TemplateImplements::__construct expects string, but 0 provided' => 13,
'Invalid type \'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\+5\' in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidClassTemplateImplementsAttribute2' => 18,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidClassTemplateImplementsAttribute2 has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements\InvalidInterfaceTemplateImplementsAttribute, expecting 1' => 19,
'Attribute TemplateImplements cannot be used on a property' => 21,
];

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

namespace test\PhpStaticAnalysis\PsalmPlugin;

class TemplateUseAttributeTest extends BaseAttributeTestCase
{
public function testTraitTemplateUseAttribute(): void
{
$errors = $this->analyzeTestFile('/data/TemplateUse/TraitTemplateUseAttribute.php');
$this->assertCount(0, $errors);
}

public function testInvalidTraitTemplateUseAttribute(): void
{
$errors = $this->analyzeTestFile('/data/TemplateUse/InvalidTraitTemplateUseAttribute.php');

$expectedErrors = [
'Argument 1 of PhpStaticAnalysis\Attributes\TemplateUse::__construct expects string, but 0 provided' => 13,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse\InvalidClassTemplateUseAttribute has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse\InvalidTraitTemplateUseAttribute, expecting 1' => 16,
'test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse\InvalidClassTemplateUseAttribute2 has missing template params when extending test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse\InvalidTraitTemplateUseAttribute, expecting 1' => 22,
'Attribute TemplateUse cannot be used on a property' => 24,
];

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

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateExtends;

#[Template('T')]
class ClassTemplateExtendsAttribute
{
}

#[TemplateExtends('ClassTemplateExtendsAttribute<int>')] // this class extends the base template
class ClassTemplateExtendsAttributeChild extends ClassTemplateExtendsAttribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateExtends;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateExtends;

#[Template('T')]
class InvalidClassTemplateExtendsAttribute
{
}

#[TemplateExtends(0)]
class InvalidClassTemplateExtendsAttributeChild extends InvalidClassTemplateExtendsAttribute
{
}

#[TemplateExtends('+5')]
class InvalidClassTemplateExtendsAttributeChild2 extends InvalidClassTemplateExtendsAttribute
{
}

#[TemplateExtends('InvalidClassTemplateExtendsAttribute<int>')]
#[TemplateExtends('InvalidClassTemplateExtendsAttribute<int>')]
class InvalidClassTemplateExtendsAttributeChild3 extends InvalidClassTemplateExtendsAttribute
{
#[TemplateExtends('InvalidClassTemplateExtendsAttribute<int>')]
public string $name = '';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateImplements;

#[Template('T')]
interface InterfaceTemplateImplementsAttribute
{
}

#[Template('T')]
interface InterfaceTemplateImplementsAttribute2
{
}

#[Template('T')]
interface InterfaceTemplateImplementsAttribute3
{
}

#[TemplateImplements('InterfaceTemplateImplementsAttribute<int>')] // this class implements the base interface
#[TemplateImplements(
'InterfaceTemplateImplementsAttribute2<int>',
'InterfaceTemplateImplementsAttribute3<int>'
)]
class ClassTemplateImplementsAttribute implements InterfaceTemplateImplementsAttribute, InterfaceTemplateImplementsAttribute2, InterfaceTemplateImplementsAttribute3
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateImplements;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateImplements;

#[Template('T')]
interface InvalidInterfaceTemplateImplementsAttribute
{
}

#[TemplateImplements(0)]
class InvalidClassTemplateImplementsAttribute implements InvalidInterfaceTemplateImplementsAttribute
{
}

#[TemplateImplements('+5')]
class InvalidClassTemplateImplementsAttribute2 implements InvalidInterfaceTemplateImplementsAttribute
{
#[TemplateImplements('InvalidInterfaceTemplateImplementsAttribute<int>')]
public string $name = '';
}
26 changes: 26 additions & 0 deletions tests/data/TemplateUse/InvalidTraitTemplateUseAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateUse;

#[Template('T')]
trait InvalidTraitTemplateUseAttribute
{
}

#[TemplateUse(0)]
class InvalidClassTemplateUseAttribute
{
use InvalidTraitTemplateUseAttribute;
}

#[TemplateUse('+5')]
class InvalidClassTemplateUseAttribute2
{
use InvalidTraitTemplateUseAttribute;

#[TemplateUse('InvalidTraitTemplateUseAttribute<int>')]
public string $name = '';
}
33 changes: 33 additions & 0 deletions tests/data/TemplateUse/TraitTemplateUseAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace test\PhpStaticAnalysis\PsalmPlugin\data\TemplateUse;

use PhpStaticAnalysis\Attributes\Template;
use PhpStaticAnalysis\Attributes\TemplateUse;

#[Template('T')]
trait TraitTemplateUseAttribute
{
}

#[Template('T')]
trait TraitTemplateUseAttribute2
{
}

#[Template('T')]
trait TraitTemplateUseAttribute3
{
}

#[TemplateUse('TraitTemplateUseAttribute<int>')] // this class uses the base trait
#[TemplateUse(
'TraitTemplateUseAttribute2<int>',
'TraitTemplateUseAttribute3<int>'
)]
class ClassTemplateUseAttribute
{
use TraitTemplateUseAttribute;
use TraitTemplateUseAttribute2;
use TraitTemplateUseAttribute3;
}

0 comments on commit 9403aa4

Please sign in to comment.