AbstractReaderTest.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. <?php
  2. namespace Doctrine\Tests\Common\Annotations;
  3. use Doctrine\Common\Annotations\DoctrineReader;
  4. use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
  5. use Doctrine\Common\Annotations\Annotation\IgnorePhpDoc;
  6. use ReflectionClass, Doctrine\Common\Annotations\AnnotationReader;
  7. use Doctrine\Tests\Common\Annotations\DummyAnnotation;
  8. use Doctrine\Tests\Common\Annotations\Name;
  9. use Doctrine\Tests\Common\Annotations\DummyId;
  10. use Doctrine\Tests\Common\Annotations\DummyJoinTable;
  11. use Doctrine\Tests\Common\Annotations\DummyJoinColumn;
  12. use Doctrine\Tests\Common\Annotations\DummyColumn;
  13. use Doctrine\Tests\Common\Annotations\DummyGeneratedValue;
  14. require_once __DIR__ . '/TopLevelAnnotation.php';
  15. abstract class AbstractReaderTest extends \PHPUnit_Framework_TestCase
  16. {
  17. public function testAnnotations()
  18. {
  19. $reader = $this->getReader();
  20. $class = new ReflectionClass('Doctrine\Tests\Common\Annotations\DummyClass');
  21. $this->assertEquals(1, count($reader->getClassAnnotations($class)));
  22. $this->assertInstanceOf($annotName = 'Doctrine\Tests\Common\Annotations\DummyAnnotation', $annot = $reader->getClassAnnotation($class, $annotName));
  23. $this->assertEquals("hello", $annot->dummyValue);
  24. $field1Prop = $class->getProperty('field1');
  25. $propAnnots = $reader->getPropertyAnnotations($field1Prop);
  26. $this->assertEquals(1, count($propAnnots));
  27. $this->assertInstanceOf($annotName, $annot = $reader->getPropertyAnnotation($field1Prop, $annotName));
  28. $this->assertEquals("fieldHello", $annot->dummyValue);
  29. $getField1Method = $class->getMethod('getField1');
  30. $methodAnnots = $reader->getMethodAnnotations($getField1Method);
  31. $this->assertEquals(1, count($methodAnnots));
  32. $this->assertInstanceOf($annotName, $annot = $reader->getMethodAnnotation($getField1Method, $annotName));
  33. $this->assertEquals(array(1, 2, "three"), $annot->value);
  34. $field2Prop = $class->getProperty('field2');
  35. $propAnnots = $reader->getPropertyAnnotations($field2Prop);
  36. $this->assertEquals(1, count($propAnnots));
  37. $this->assertInstanceOf($annotName = 'Doctrine\Tests\Common\Annotations\DummyJoinTable', $joinTableAnnot = $reader->getPropertyAnnotation($field2Prop, $annotName));
  38. $this->assertEquals(1, count($joinTableAnnot->joinColumns));
  39. $this->assertEquals(1, count($joinTableAnnot->inverseJoinColumns));
  40. $this->assertTrue($joinTableAnnot->joinColumns[0] instanceof DummyJoinColumn);
  41. $this->assertTrue($joinTableAnnot->inverseJoinColumns[0] instanceof DummyJoinColumn);
  42. $this->assertEquals('col1', $joinTableAnnot->joinColumns[0]->name);
  43. $this->assertEquals('col2', $joinTableAnnot->joinColumns[0]->referencedColumnName);
  44. $this->assertEquals('col3', $joinTableAnnot->inverseJoinColumns[0]->name);
  45. $this->assertEquals('col4', $joinTableAnnot->inverseJoinColumns[0]->referencedColumnName);
  46. $dummyAnnot = $reader->getMethodAnnotation($class->getMethod('getField1'), 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
  47. $this->assertEquals('', $dummyAnnot->dummyValue);
  48. $this->assertEquals(array(1, 2, 'three'), $dummyAnnot->value);
  49. $dummyAnnot = $reader->getPropertyAnnotation($class->getProperty('field1'), 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
  50. $this->assertEquals('fieldHello', $dummyAnnot->dummyValue);
  51. $classAnnot = $reader->getClassAnnotation($class, 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
  52. $this->assertEquals('hello', $classAnnot->dummyValue);
  53. }
  54. /**
  55. * @expectedException Doctrine\Common\Annotations\AnnotationException
  56. * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in class Doctrine\Tests\Common\Annotations\DummyClassSyntaxError.
  57. */
  58. public function testClassSyntaxErrorContext()
  59. {
  60. $reader = $this->getReader();
  61. $reader->getClassAnnotations(new \ReflectionClass('Doctrine\Tests\Common\Annotations\DummyClassSyntaxError'));
  62. }
  63. /**
  64. * @expectedException Doctrine\Common\Annotations\AnnotationException
  65. * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in method Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError::foo().
  66. */
  67. public function testMethodSyntaxErrorContext()
  68. {
  69. $reader = $this->getReader();
  70. $reader->getMethodAnnotations(new \ReflectionMethod('Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError', 'foo'));
  71. }
  72. /**
  73. * @expectedException Doctrine\Common\Annotations\AnnotationException
  74. * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in property Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError::$foo.
  75. */
  76. public function testPropertySyntaxErrorContext()
  77. {
  78. $reader = $this->getReader();
  79. $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError', 'foo'));
  80. }
  81. /**
  82. * @group regression
  83. */
  84. public function testMultipleAnnotationsOnSameLine()
  85. {
  86. $reader = $this->getReader();
  87. $annots = $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClass2', 'id'));
  88. $this->assertEquals(3, count($annots));
  89. }
  90. public function testNonAnnotationProblem()
  91. {
  92. $reader = $this->getReader();
  93. $this->assertNotNull($annot = $reader->getPropertyAnnotation(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClassNonAnnotationProblem', 'foo'), $name = 'Doctrine\Tests\Common\Annotations\DummyAnnotation'));
  94. $this->assertType($name, $annot);
  95. }
  96. public function testImportWithConcreteAnnotation()
  97. {
  98. $reader = $this->getReader();
  99. $property = new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestImportWithConcreteAnnotation', 'field');
  100. $annotations = $reader->getPropertyAnnotations($property);
  101. $this->assertEquals(1, count($annotations));
  102. $this->assertNotNull($reader->getPropertyAnnotation($property, 'Doctrine\Tests\Common\Annotations\DummyAnnotation'));
  103. }
  104. public function testImportWithInheritance()
  105. {
  106. $reader = $this->getReader();
  107. $class = new TestParentClass();
  108. $ref = new \ReflectionClass($class);
  109. $childAnnotations = $reader->getPropertyAnnotations($ref->getProperty('child'));
  110. $this->assertEquals(1, count($childAnnotations));
  111. $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Foo\Name', reset($childAnnotations));
  112. $parentAnnotations = $reader->getPropertyAnnotations($ref->getProperty('parent'));
  113. $this->assertEquals(1, count($parentAnnotations));
  114. $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Bar\Name', reset($parentAnnotations));
  115. }
  116. /**
  117. * @expectedException Doctrine\Common\Annotations\AnnotationException
  118. * @expectedExceptionMessage The annotation "@NameFoo" in property Doctrine\Tests\Common\Annotations\TestAnnotationNotImportedClass::$field was never imported.
  119. */
  120. public function testImportDetectsNotImportedAnnotation()
  121. {
  122. $reader = $this->getReader();
  123. $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestAnnotationNotImportedClass', 'field'));
  124. }
  125. /**
  126. * @expectedException Doctrine\Common\Annotations\AnnotationException
  127. * @expectedExceptionMessage The annotation "@Foo\Bar\Name" in property Doctrine\Tests\Common\Annotations\TestNonExistentAnnotationClass::$field was never imported.
  128. */
  129. public function testImportDetectsNonExistentAnnotation()
  130. {
  131. $reader = $this->getReader();
  132. $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestNonExistentAnnotationClass', 'field'));
  133. }
  134. public function testTopLevelAnnotation()
  135. {
  136. $reader = $this->getReader();
  137. $annotations = $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestTopLevelAnnotationClass', 'field'));
  138. $this->assertEquals(1, count($annotations));
  139. $this->assertInstanceOf('\TopLevelAnnotation', reset($annotations));
  140. }
  141. public function testIgnoresAnnotationsNotPrefixedWithWhitespace()
  142. {
  143. $reader = $this->getReader();
  144. $annotation = $reader->getClassAnnotation(new \ReflectionClass(new TestIgnoresNonAnnotationsClass()), 'Doctrine\Tests\Common\Annotations\Name');
  145. $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Name', $annotation);
  146. }
  147. abstract protected function getReader();
  148. }
  149. /**
  150. * @parseAnnotation("var")
  151. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  152. *
  153. */
  154. class TestParseAnnotationClass
  155. {
  156. /**
  157. * @var
  158. */
  159. private $field;
  160. }
  161. /**
  162. * @Name
  163. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  164. */
  165. class TestIgnoresNonAnnotationsClass
  166. {
  167. }
  168. class TestTopLevelAnnotationClass
  169. {
  170. /**
  171. * @\TopLevelAnnotation
  172. */
  173. private $field;
  174. }
  175. class TestNonExistentAnnotationClass
  176. {
  177. /**
  178. * @Foo\Bar\Name
  179. */
  180. private $field;
  181. }
  182. class TestAnnotationNotImportedClass
  183. {
  184. /**
  185. * @NameFoo
  186. */
  187. private $field;
  188. }
  189. class TestChildClass
  190. {
  191. /**
  192. * @\Doctrine\Tests\Common\Annotations\Foo\Name(name = "foo")
  193. */
  194. protected $child;
  195. }
  196. class TestParentClass extends TestChildClass
  197. {
  198. /**
  199. * @\Doctrine\Tests\Common\Annotations\Bar\Name(name = "bar")
  200. */
  201. private $parent;
  202. }
  203. class TestImportWithConcreteAnnotation
  204. {
  205. /**
  206. * @DummyAnnotation(dummyValue = "bar")
  207. */
  208. private $field;
  209. }
  210. /**
  211. * A description of this class.
  212. *
  213. * Let's see if the parser recognizes that this @ is not really referring to an
  214. * annotation. Also make sure that @var \ is not concated to "@var\is".
  215. *
  216. * @author robo
  217. * @since 2.0
  218. * @DummyAnnotation(dummyValue="hello")
  219. */
  220. class DummyClass {
  221. /**
  222. * A nice property.
  223. *
  224. * @var mixed
  225. * @DummyAnnotation(dummyValue="fieldHello")
  226. */
  227. private $field1;
  228. /**
  229. * @DummyJoinTable(name="join_table",
  230. * joinColumns={@DummyJoinColumn(name="col1", referencedColumnName="col2")},
  231. * inverseJoinColumns={
  232. * @DummyJoinColumn(name="col3", referencedColumnName="col4")
  233. * })
  234. */
  235. private $field2;
  236. /**
  237. * Gets the value of field1.
  238. *
  239. * @return mixed
  240. * @DummyAnnotation({1,2,"three"})
  241. */
  242. public function getField1() {
  243. }
  244. }
  245. /**
  246. * @ignoreAnnotation("var")
  247. */
  248. class DummyClass2 {
  249. /**
  250. * @DummyId @DummyColumn(type="integer") @DummyGeneratedValue
  251. * @var integer
  252. */
  253. private $id;
  254. }
  255. class DummyId extends \Doctrine\Common\Annotations\Annotation {}
  256. class DummyColumn extends \Doctrine\Common\Annotations\Annotation {
  257. public $type;
  258. }
  259. class DummyGeneratedValue extends \Doctrine\Common\Annotations\Annotation {}
  260. class DummyAnnotation extends \Doctrine\Common\Annotations\Annotation {
  261. public $dummyValue;
  262. }
  263. class DummyJoinColumn extends \Doctrine\Common\Annotations\Annotation {
  264. public $name;
  265. public $referencedColumnName;
  266. }
  267. class DummyJoinTable extends \Doctrine\Common\Annotations\Annotation {
  268. public $name;
  269. public $joinColumns;
  270. public $inverseJoinColumns;
  271. }
  272. /**
  273. * @DummyAnnotation(@)
  274. */
  275. class DummyClassSyntaxError
  276. {
  277. }
  278. class DummyClassMethodSyntaxError
  279. {
  280. /**
  281. * @DummyAnnotation(@)
  282. */
  283. public function foo()
  284. {
  285. }
  286. }
  287. class DummyClassPropertySyntaxError
  288. {
  289. /**
  290. * @DummyAnnotation(@)
  291. */
  292. public $foo;
  293. }
  294. /**
  295. * @ignoreAnnotation({"since", "var"})
  296. */
  297. class DummyClassNonAnnotationProblem
  298. {
  299. /**
  300. * @DummyAnnotation
  301. *
  302. * @var \Test
  303. * @since 0.1
  304. */
  305. public $foo;
  306. }
  307. /**
  308. * @DummyAnnotation Foo bar <foobar@1domain.com>
  309. */
  310. class DummyClassWithEmail
  311. {
  312. }
  313. namespace Doctrine\Tests\Common\Annotations\Foo;
  314. class Name extends \Doctrine\Common\Annotations\Annotation
  315. {
  316. public $name;
  317. }
  318. namespace Doctrine\Tests\Common\Annotations\Bar;
  319. class Name extends \Doctrine\Common\Annotations\Annotation
  320. {
  321. public $name;
  322. }