AnnotationReaderTest.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. namespace EasySwoole\DoctrineAnnotation\Tests;
  3. use EasySwoole\DoctrineAnnotation\AnnotationReader;
  4. use EasySwoole\DoctrineAnnotation\DocParser;
  5. use EasySwoole\DoctrineAnnotation\Reader;
  6. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\Annotation\SingleUseAnnotation;
  7. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithFullPathUseStatement;
  8. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithImportedIgnoredAnnotation;
  9. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithPHPCodeSnifferAnnotation;
  10. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithPhpCsSuppressAnnotation;
  11. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithPHPStanGenericsAnnotations;
  12. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\IgnoredNamespaces\AnnotatedAtClassLevel;
  13. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\IgnoredNamespaces\AnnotatedAtMethodLevel;
  14. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\IgnoredNamespaces\AnnotatedAtPropertyLevel;
  15. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\IgnoredNamespaces\AnnotatedWithAlias;
  16. use InvalidArgumentException;
  17. use LogicException;
  18. use ReflectionClass;
  19. use function class_exists;
  20. use function spl_autoload_register;
  21. use function spl_autoload_unregister;
  22. class AnnotationReaderTest extends AbstractReaderTest
  23. {
  24. /**
  25. * @return AnnotationReader
  26. */
  27. protected function getReader(?DocParser $parser = null): Reader
  28. {
  29. return new AnnotationReader($parser);
  30. }
  31. public function testMethodAnnotationFromTrait(): void
  32. {
  33. $reader = $this->getReader();
  34. $ref = new ReflectionClass(Fixtures\ClassUsesTrait::class);
  35. $annotations = $reader->getMethodAnnotations($ref->getMethod('someMethod'));
  36. self::assertInstanceOf(Bar\Autoload::class, $annotations[0]);
  37. $annotations = $reader->getMethodAnnotations($ref->getMethod('traitMethod'));
  38. self::assertInstanceOf(Fixtures\Annotation\Autoload::class, $annotations[0]);
  39. }
  40. public function testMethodAnnotationFromOverwrittenTrait(): void
  41. {
  42. $reader = $this->getReader();
  43. $ref = new ReflectionClass(Fixtures\ClassOverwritesTrait::class);
  44. $annotations = $reader->getMethodAnnotations($ref->getMethod('traitMethod'));
  45. self::assertInstanceOf(Bar2\Autoload::class, $annotations[0]);
  46. }
  47. public function testPropertyAnnotationFromTrait(): void
  48. {
  49. $reader = $this->getReader();
  50. $ref = new ReflectionClass(Fixtures\ClassUsesTrait::class);
  51. $annotations = $reader->getPropertyAnnotations($ref->getProperty('aProperty'));
  52. self::assertInstanceOf(Bar\Autoload::class, $annotations[0]);
  53. $annotations = $reader->getPropertyAnnotations($ref->getProperty('traitProperty'));
  54. self::assertInstanceOf(Fixtures\Annotation\Autoload::class, $annotations[0]);
  55. }
  56. public function testOmitNotRegisteredAnnotation(): void
  57. {
  58. $parser = new DocParser();
  59. $parser->setIgnoreNotImportedAnnotations(true);
  60. $reader = $this->getReader($parser);
  61. $ref = new ReflectionClass(Fixtures\ClassWithNotRegisteredAnnotationUsed::class);
  62. $annotations = $reader->getMethodAnnotations($ref->getMethod('methodWithNotRegisteredAnnotation'));
  63. self::assertEquals([], $annotations);
  64. }
  65. /**
  66. * @group 45
  67. * @runInSeparateProcess
  68. */
  69. public function testClassAnnotationIsIgnored(): void
  70. {
  71. $reader = $this->getReader();
  72. $ref = new ReflectionClass(AnnotatedAtClassLevel::class);
  73. $reader::addGlobalIgnoredNamespace('SomeClassAnnotationNamespace');
  74. self::assertEmpty($reader->getClassAnnotations($ref));
  75. }
  76. /**
  77. * @group 45
  78. * @runInSeparateProcess
  79. */
  80. public function testMethodAnnotationIsIgnored(): void
  81. {
  82. $reader = $this->getReader();
  83. $ref = new ReflectionClass(AnnotatedAtMethodLevel::class);
  84. $reader::addGlobalIgnoredNamespace('SomeMethodAnnotationNamespace');
  85. self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('test')));
  86. }
  87. /**
  88. * @group 45
  89. * @runInSeparateProcess
  90. */
  91. public function testPropertyAnnotationIsIgnored(): void
  92. {
  93. $reader = $this->getReader();
  94. $ref = new ReflectionClass(AnnotatedAtPropertyLevel::class);
  95. $reader::addGlobalIgnoredNamespace('SomePropertyAnnotationNamespace');
  96. self::assertEmpty($reader->getPropertyAnnotations($ref->getProperty('property')));
  97. }
  98. /**
  99. * @group 244
  100. * @runInSeparateProcess
  101. */
  102. public function testAnnotationWithAliasIsIgnored(): void
  103. {
  104. $reader = $this->getReader();
  105. $ref = new ReflectionClass(AnnotatedWithAlias::class);
  106. $reader::addGlobalIgnoredNamespace('SomePropertyAnnotationNamespace');
  107. self::assertEmpty($reader->getPropertyAnnotations($ref->getProperty('property')));
  108. }
  109. public function testClassWithFullPathUseStatement(): void
  110. {
  111. if (class_exists(SingleUseAnnotation::class, false)) {
  112. throw new LogicException(
  113. 'The SingleUseAnnotation must not be used in other tests for this test to be useful.' .
  114. 'If the class is already loaded then the code path that finds the class to load is not used and ' .
  115. 'this test becomes useless.'
  116. );
  117. }
  118. $reader = $this->getReader();
  119. $ref = new ReflectionClass(ClassWithFullPathUseStatement::class);
  120. $annotations = $reader->getClassAnnotations($ref);
  121. self::assertInstanceOf(SingleUseAnnotation::class, $annotations[0]);
  122. }
  123. public function testPhpCsSuppressAnnotationIsIgnored(): void
  124. {
  125. $reader = $this->getReader();
  126. $ref = new ReflectionClass(ClassWithPhpCsSuppressAnnotation::class);
  127. self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('foo')));
  128. }
  129. public function testGloballyIgnoredAnnotationNotIgnored(): void
  130. {
  131. $reader = $this->getReader();
  132. $class = new ReflectionClass(Fixtures\ClassDDC1660::class);
  133. $testLoader = static function (string $className): bool {
  134. if ($className === 'since') {
  135. throw new InvalidArgumentException(
  136. 'Globally ignored annotation names should never be passed to an autoloader.'
  137. );
  138. }
  139. return false;
  140. };
  141. spl_autoload_register($testLoader, true, true);
  142. try {
  143. self::assertEmpty($reader->getClassAnnotations($class));
  144. } finally {
  145. spl_autoload_unregister($testLoader);
  146. }
  147. }
  148. public function testPHPCodeSnifferAnnotationsAreIgnored(): void
  149. {
  150. $reader = $this->getReader();
  151. $ref = new ReflectionClass(ClassWithPHPCodeSnifferAnnotation::class);
  152. self::assertEmpty($reader->getClassAnnotations($ref));
  153. }
  154. public function testPHPStanGenericsAnnotationsAreIgnored(): void
  155. {
  156. $reader = $this->getReader();
  157. $ref = new ReflectionClass(ClassWithPHPStanGenericsAnnotations::class);
  158. self::assertEmpty($reader->getClassAnnotations($ref));
  159. self::assertEmpty($reader->getPropertyAnnotations($ref->getProperty('bar')));
  160. self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('foo')));
  161. $this->expectException('\EasySwoole\DoctrineAnnotation\AnnotationException');
  162. $this->expectExceptionMessage(
  163. '[Semantical Error] The annotation "@Template" in method' .
  164. ' EasySwoole\DoctrineAnnotation\Tests\Fixtures\ClassWithPHPStanGenericsAnnotations' .
  165. '::twigTemplateFunctionName() was never imported.'
  166. );
  167. self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('twigTemplateFunctionName')));
  168. }
  169. public function testImportedIgnoredAnnotationIsStillIgnored(): void
  170. {
  171. $reader = $this->getReader();
  172. $ref = new ReflectionClass(ClassWithImportedIgnoredAnnotation::class);
  173. self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('something')));
  174. }
  175. }