Skip to content

Commit 4dd597d

Browse files
author
Alexander Obuhovich
committed
Adding tests to verify that @Usage annotation restrictions work
1. adding tests to verify, that if annotation can't be applied to class/method/property, then approptiate exception is thrown 2. adding descriptive comment around that check to avoid confusion while reading `$usage->$member` code
1 parent 6e005df commit 4dd597d

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

src/annotations/AnnotationManager.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
*/
2727
class AnnotationManager
2828
{
29+
const MEMBER_CLASS = 'class';
30+
31+
const MEMBER_PROPERTY = 'property';
32+
33+
const MEMBER_METHOD = 'method';
34+
2935
/**
3036
* @var boolean Enable PHP autoloader when searching for annotation classes (defaults to true)
3137
*/
@@ -251,7 +257,7 @@ public function resolveName($name)
251257
* @return IAnnotation[] array of IAnnotation objects for the given class/member/name
252258
* @throws AnnotationException for bad annotations
253259
*/
254-
protected function getAnnotations($class_name, $member_type = 'class', $member_name = null)
260+
protected function getAnnotations($class_name, $member_type = self::MEMBER_CLASS, $member_name = null)
255261
{
256262
$key = $class_name . ($member_name ? '::' . $member_name : '');
257263

@@ -260,8 +266,8 @@ protected function getAnnotations($class_name, $member_type = 'class', $member_n
260266
$this->annotations[$key] = array();
261267
}
262268

263-
if ($member_type !== 'class') {
264-
$this->getAnnotations($class_name, 'class');
269+
if ($member_type !== self::MEMBER_CLASS) {
270+
$this->getAnnotations($class_name, self::MEMBER_CLASS);
265271
}
266272

267273
if ($parent = get_parent_class($class_name)) {
@@ -335,9 +341,9 @@ protected function applyConstraints(array &$annotations, $member)
335341
{
336342
foreach ($annotations as $outerIndex => $annotation) {
337343
$type = get_class($annotation);
338-
339344
$usage = $this->getUsage($type);
340345

346+
// Checks, that annotation can be applied to given class/method/property according to it's @usage annotation.
341347
if (!$usage->$member) {
342348
throw new AnnotationException("{$type} cannot be applied to a {$member}");
343349
}
@@ -502,9 +508,9 @@ public function getMethodAnnotations($class, $method = null, $type = null)
502508
}
503509

504510
if ($type === null) {
505-
return $this->getAnnotations($class, 'method', $method);
511+
return $this->getAnnotations($class, self::MEMBER_METHOD, $method);
506512
} else {
507-
return $this->filterAnnotations($this->getAnnotations($class, 'method', $method), $type);
513+
return $this->filterAnnotations($this->getAnnotations($class, self::MEMBER_METHOD, $method), $type);
508514
}
509515
}
510516

@@ -542,9 +548,9 @@ public function getPropertyAnnotations($class, $property = null, $type = null)
542548
}
543549

544550
if ($type === null) {
545-
return $this->getAnnotations($class, 'property', '$' . $property);
551+
return $this->getAnnotations($class, self::MEMBER_PROPERTY, '$' . $property);
546552
} else {
547-
return $this->filterAnnotations($this->getAnnotations($class, 'property', '$' . $property), $type);
553+
return $this->filterAnnotations($this->getAnnotations($class, self::MEMBER_PROPERTY, '$' . $property), $type);
548554
}
549555
}
550556
}

test/suite/Annotations.case.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ public function initAnnotation(array $params)
2626
}
2727
}
2828

29+
/**
30+
* @usage
31+
*/
32+
class UselessAnnotation extends Annotation
33+
{
34+
35+
36+
}
37+
2938
/**
3039
* @usage('class'=>true)
3140
*/

test/suite/Annotations.test.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,59 @@ protected function testReadingFileAwareAnnotation()
691691
);
692692
}
693693

694+
protected function testAnnotationsConstrainedByCorrectUsageAnnotation()
695+
{
696+
$annotations = array(new NoteAnnotation());
697+
698+
$this->assertApplyConstrains($annotations, 'class');
699+
}
700+
701+
protected function testAnnotationsConstrainedByClass()
702+
{
703+
$annotations = array(new UselessAnnotation());
704+
705+
$this->setExpectedException(
706+
self::ANNOTATION_EXCEPTION,
707+
'UselessAnnotation cannot be applied to a class'
708+
);
709+
710+
$this->assertApplyConstrains($annotations, AnnotationManager::MEMBER_CLASS);
711+
}
712+
713+
protected function testAnnotationsConstrainedByMethod()
714+
{
715+
$annotations = array(new UselessAnnotation());
716+
717+
$this->setExpectedException(
718+
self::ANNOTATION_EXCEPTION,
719+
'UselessAnnotation cannot be applied to a method'
720+
);
721+
722+
$this->assertApplyConstrains($annotations, AnnotationManager::MEMBER_METHOD);
723+
}
724+
725+
protected function testAnnotationsConstrainedByProperty()
726+
{
727+
$annotations = array(new UselessAnnotation());
728+
729+
$this->setExpectedException(
730+
self::ANNOTATION_EXCEPTION,
731+
'UselessAnnotation cannot be applied to a property'
732+
);
733+
734+
$this->assertApplyConstrains($annotations, AnnotationManager::MEMBER_PROPERTY);
735+
}
736+
737+
protected function assertApplyConstrains(array &$annotations, $memberType)
738+
{
739+
$manager = Annotations::getManager();
740+
$methodReflection = new ReflectionMethod(get_class($manager), 'applyConstraints');
741+
$methodReflection->setAccessible(true);
742+
$methodReflection->invokeArgs($manager, array(&$annotations, $memberType));
743+
744+
$this->check(count($annotations) > 0);
745+
}
746+
694747
protected function testFilterUnresolvedAnnotationClass()
695748
{
696749
$annotations = Annotations::ofClass('TestBase', false);

0 commit comments

Comments
 (0)