Skip to content

Commit

Permalink
Add support for attributes on interfaces (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
cspray authored Jun 8, 2022
1 parent e035b9a commit 03d99ec
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.1](https://github.com/cspray/annotated-target/tree/v0.1.1) - 2022-06-08

### Fixed

- Fixed a bug where Attributes on interfaces were not properly parsed.

## [0.1.0](https://github.com/cspray/annotated-target/tree/v0.1.0) - 2022-06-08

### Added
Expand Down
10 changes: 10 additions & 0 deletions fixture_src/ClassOnlyAttributeSingleInterface/FooInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php declare(strict_types=1);

namespace Cspray\AnnotatedTargetFixture\ClassOnlyAttributeSingleInterface;

use Cspray\AnnotatedTargetFixture\ClassOnly;

#[ClassOnly('foo')]
interface FooInterface {

}
17 changes: 17 additions & 0 deletions fixture_src/ClassOnlyAttributeSingleInterfaceFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);

namespace Cspray\AnnotatedTargetFixture;

use Cspray\Typiphy\ObjectType;
use function Cspray\Typiphy\objectType;

class ClassOnlyAttributeSingleInterfaceFixture implements Fixture {

public function getPath() : string {
return __DIR__ .'/ClassOnlyAttributeSingleInterface';
}

public function fooInterface() : ObjectType {
return objectType(ClassOnlyAttributeSingleInterface\FooInterface::class);
}
}
4 changes: 4 additions & 0 deletions fixture_src/Fixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,8 @@ public static function nonPhpFile() : NonPhpFileFixture {
return new NonPhpFileFixture();
}

public static function classOnlyAttributeSingleInterface() : ClassOnlyAttributeSingleInterfaceFixture {
return new ClassOnlyAttributeSingleInterfaceFixture();
}

}
4 changes: 2 additions & 2 deletions src/PhpParserAnnotatedTargetParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function leaveNode(Node $node) {
if (!empty($this->filteredAttributes) && !in_array($attrType, $this->filteredAttributes)) {
continue;
}
if ($node instanceof Node\Stmt\Class_) {
if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_) {
($this->consumer)($this->getAnnotatedTargetFromClassNode($node, $index));
} else if ($node instanceof Node\Stmt\Property) {
foreach ($node->props as $prop) {
Expand All @@ -106,7 +106,7 @@ public function leaveNode(Node $node) {
}
}

private function getAnnotatedTargetFromClassNode(Node\Stmt\Class_ $class, int $index) : AnnotatedTarget {
private function getAnnotatedTargetFromClassNode(Node\Stmt\Class_|Node\Stmt\Interface_ $class, int $index) : AnnotatedTarget {
$classType = $class->namespacedName->toString();
return $this->getAnnotatedTarget(fn() => new ReflectionClass($classType), $index);
}
Expand Down
47 changes: 47 additions & 0 deletions tests/Unit/ClassOnlyInterfaceAttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php declare(strict_types=1);

namespace Cspray\AnnotatedTarget\Unit;

use Cspray\AnnotatedTargetFixture\ClassOnly;
use Cspray\AnnotatedTargetFixture\Fixtures;
use function Cspray\Typiphy\objectType;

uses(AnnotatedTargetParserTestCase::class);

beforeEach()->withFixtures(Fixtures::classOnlyAttributeSingleInterface());

it('counts parsed targets for single class')
->expect(fn() => $this->getTargets())
->toHaveCount(1);

it('ensures all targets are correct type')
->expect(fn() => $this->getTargets())
->toContainOnlyAnnotatedTargets();

it('ensures all targets share target reflection')
->expect(fn() => $this->getTargets())
->toShareTargetReflection();

it('ensures all targets share attribute reflection')
->expect(fn() => $this->getTargets())
->toShareAttributeReflection();

it('ensures all targets share attribute instance')
->expect(fn() => $this->getTargets())
->toShareAttributeInstance();

it('includes target reflection class')
->expect(fn() => $this->getTargets())
->toContainTargetClass(Fixtures::classOnlyAttributeSingleInterface()->fooInterface());

it('includes attribute reflection class')
->expect(fn() => $this->getTargets())
->toContainTargetClassWithAttribute(Fixtures::classOnlyAttributeSingleInterface()->fooInterface(), objectType(ClassOnly::class));

it('includes attribute instance with correct value')
->expect(fn() => $this->getTargets())
->toContainTargetClassWithAttributeInstance(
Fixtures::classOnlyAttributeSingleInterface()->fooInterface(),
objectType(ClassOnly::class),
fn(ClassOnly $classOnly) => $classOnly->value === 'foo'
);

0 comments on commit 03d99ec

Please sign in to comment.