Commit 2ffc7f17 authored by romanb's avatar romanb

[2.0] Migrated AnnotationDriver to new annotation parser. Removed addendum vendor library.

parent 08f84793
......@@ -37,6 +37,8 @@ class Lexer
const T_INTEGER = 3;
const T_STRING = 4;
const T_IDENTIFIER = 5;
const T_TRUE = 6;
const T_FALSE = 7;
/**
* Array of scanned tokens.
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
......@@ -69,7 +88,10 @@ class Parser
$this->_lexer->setInput(trim($input, '* /'));
$this->_lexer->moveNext();
return $this->Annotations();
if ($this->_lexer->isNextToken('@')) {
return $this->Annotations();
}
return array();
}
/**
......@@ -90,7 +112,7 @@ class Parser
}
if ( ! $isMatch) {
$this->syntaxError($token['value']);
$this->syntaxError($token['value'], $this->_lexer->lookahead['value']);
}
$this->_lexer->moveNext();
......@@ -102,9 +124,9 @@ class Parser
* @param $expected
* @throws Exception
*/
private function syntaxError($expected)
private function syntaxError($expected, $got = "")
{
throw new \Exception("Expected: $expected.");
throw new \Exception("Expected: $expected. Got: $got");
}
/**
......@@ -175,6 +197,7 @@ class Parser
if ( ! $this->_isNestedAnnotation && $this->_lexer->lookahead != null
&& $this->_lexer->lookahead['value'] != '('
&& $this->_lexer->lookahead['value'] != '@'
|| ! is_subclass_of($name, 'Doctrine\Common\Annotations\Annotation')) {
return false;
}
......@@ -202,22 +225,9 @@ class Parser
$values = array();
$value = $this->Value();
if (is_array($value)) {
$k = key($value);
$v = $value[$k];
if (is_string($k)) {
// FieldAssignment
$values[$k] = $v;
} else {
$values['value'][] = $value;
}
} else {
$values['value'][] = $value;
}
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
$value = $this->Value();
if ($this->_lexer->isNextToken(')')) {
// Single value
if (is_array($value)) {
$k = key($value);
$v = $value[$k];
......@@ -225,11 +235,30 @@ class Parser
// FieldAssignment
$values[$k] = $v;
} else {
$values['value'][] = $value;
$values['value']= $value;
}
} else {
$values['value'][] = $value;
$values['value'] = $value;
}
return $values;
} else {
// FieldAssignment
$k = key($value);
$v = $value[$k];
$values[$k] = $v;
}
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
$value = $this->Value();
if ( ! is_array($value)) {
$this->syntaxError('FieldAssignment', $value);
}
$k = key($value);
$v = $value[$k];
$values[$k] = $v;
}
return $values;
......@@ -269,6 +298,12 @@ class Parser
case Lexer::T_FLOAT:
$this->match(Lexer::T_FLOAT);
return $this->_lexer->token['value'];
case Lexer::T_TRUE:
$this->match(Lexer::T_TRUE);
return true;
case Lexer::T_FALSE:
$this->match(Lexer::T_FALSE);
return false;
default:
var_dump($this->_lexer->lookahead);
throw new \Exception("Invalid value.");
......
......@@ -21,25 +21,24 @@
/* Annotations */
final class Entity extends \Annotation {
final class Entity extends \Doctrine\Common\Annotations\Annotation {
public $repositoryClass;
}
final class InheritanceType extends \Annotation {}
final class DiscriminatorColumn extends \Annotation {
final class InheritanceType extends \Doctrine\Common\Annotations\Annotation {}
final class DiscriminatorColumn extends \Doctrine\Common\Annotations\Annotation {
public $name;
public $type;
public $length;
}
//final class DiscriminatorMap extends \Annotation {}
final class DiscriminatorValue extends \Annotation {}
final class SubClasses extends \Annotation {}
final class Id extends \Annotation {}
final class GeneratedValue extends \Annotation {
final class DiscriminatorValue extends \Doctrine\Common\Annotations\Annotation {}
final class SubClasses extends \Doctrine\Common\Annotations\Annotation {}
final class Id extends \Doctrine\Common\Annotations\Annotation {}
final class GeneratedValue extends \Doctrine\Common\Annotations\Annotation {
public $strategy;
//public $generator;
}
final class Version extends \Annotation {}
final class JoinColumn extends \Annotation {
final class Version extends \Doctrine\Common\Annotations\Annotation {}
final class JoinColumn extends \Doctrine\Common\Annotations\Annotation {
public $name;
public $referencedColumnName;
public $unique = false;
......@@ -47,57 +46,57 @@ final class JoinColumn extends \Annotation {
public $onDelete;
public $onUpdate;
}
final class JoinColumns extends \Annotation {}
final class Column extends \Annotation {
final class JoinColumns extends \Doctrine\Common\Annotations\Annotation {}
final class Column extends \Doctrine\Common\Annotations\Annotation {
public $type;
public $length;
public $unique = false;
public $nullable = false;
public $name;
}
final class OneToOne extends \Annotation {
final class OneToOne extends \Doctrine\Common\Annotations\Annotation {
public $targetEntity;
public $mappedBy;
public $cascade;
public $fetch;
public $optional;
}
final class OneToMany extends \Annotation {
final class OneToMany extends \Doctrine\Common\Annotations\Annotation {
public $mappedBy;
public $targetEntity;
public $cascade;
public $fetch;
}
final class ManyToOne extends \Annotation {
final class ManyToOne extends \Doctrine\Common\Annotations\Annotation {
public $targetEntity;
public $cascade;
public $fetch;
public $optional;
}
final class ManyToMany extends \Annotation {
final class ManyToMany extends \Doctrine\Common\Annotations\Annotation {
public $targetEntity;
public $mappedBy;
public $cascade;
public $fetch;
}
final class ElementCollection extends \Annotation {
final class ElementCollection extends \Doctrine\Common\Annotations\Annotation {
public $tableName;
}
final class Table extends \Annotation {
final class Table extends \Doctrine\Common\Annotations\Annotation {
public $name;
public $schema;
}
final class JoinTable extends \Annotation {
final class JoinTable extends \Doctrine\Common\Annotations\Annotation {
public $name;
public $schema;
public $joinColumns;
public $inverseJoinColumns;
}
final class SequenceGenerator extends \Annotation {
final class SequenceGenerator extends \Doctrine\Common\Annotations\Annotation {
//public $name;
public $sequenceName;
public $allocationSize = 10;
public $initialValue = 1;
}
final class ChangeTrackingPolicy extends \Annotation {}
final class DoctrineX extends \Annotation {}
final class ChangeTrackingPolicy extends \Doctrine\Common\Annotations\Annotation {}
final class DoctrineX extends \Doctrine\Common\Annotations\Annotation {}
This diff is collapsed.
This diff is collapsed.
<?php
/**
* Addendum PHP Reflection Annotations
* http://code.google.com/p/addendum/
*
* Copyright (C) 2006 Jan "johno Suchal <johno@jsmf.net>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**/
class CompositeMatcher {
protected $matchers = array();
private $wasConstructed = false;
public function add($matcher) {
$this->matchers[] = $matcher;
}
public function matches($string, &$value) {
if(!$this->wasConstructed) {
$this->build();
$this->wasConstructed = true;
}
return $this->match($string, $value);
}
protected function build() {}
}
class ParallelMatcher extends CompositeMatcher {
protected function match($string, &$value) {
$maxLength = false;
$result = null;
foreach($this->matchers as $matcher) {
$length = $matcher->matches($string, $subvalue);
if($maxLength === false || $length > $maxLength) {
$maxLength = $length;
$result = $subvalue;
}
}
$value = $this->process($result);
return $maxLength;
}
protected function process($value) {
return $value;
}
}
class SerialMatcher extends CompositeMatcher {
protected function match($string, &$value) {
$results = array();
$total_length = 0;
foreach($this->matchers as $matcher) {
if(($length = $matcher->matches($string, $result)) === false) return false;
$total_length += $length;
$results[] = $result;
$string = substr($string, $length);
}
$value = $this->process($results);
return $total_length;
}
protected function process($results) {
return implode('', $results);
}
}
class SimpleSerialMatcher extends SerialMatcher {
private $return_part_index;
public function __construct($return_part_index = 0) {
$this->return_part_index = $return_part_index;
}
public function process($parts) {
return $parts[$this->return_part_index];
}
}
class RegexMatcher {
private $regex;
public function __construct($regex) {
$this->regex = $regex;
}
public function matches($string, &$value) {
if(preg_match("/^{$this->regex}/", $string, $matches)) {
$value = $this->process($matches);
return strlen($matches[0]);
}
$value = false;
return false;
}
protected function process($matches) {
return $matches[0];
}
}
class AnnotationsMatcher {
public function matches($string, &$annotations) {
$annotations = array();
$annotation_matcher = new AnnotationMatcher;
while(true) {
if(preg_match('/\s(?=@)/', $string, $matches, PREG_OFFSET_CAPTURE)) {
$offset = $matches[0][1] + 1;
$string = substr($string, $offset);
} else {
return; // no more annotations
}
if(($length = $annotation_matcher->matches($string, $data)) !== false) {
$string = substr($string, $length);
list($name, $params) = $data;
$annotations[$name][] = $params;
}
}
}
}
class AnnotationMatcher extends SerialMatcher {
protected function build() {
$this->add(new RegexMatcher('@'));
$this->add(new RegexMatcher('[A-Z][a-zA-Z0-9_]+'));
$this->add(new AnnotationParametersMatcher);
}
protected function process($results) {
return array($results[1], $results[2]);
}
}
class ConstantMatcher extends RegexMatcher {
private $constant;
public function __construct($regex, $constant) {
parent::__construct($regex);
$this->constant = $constant;
}
protected function process($matches) {
return $this->constant;
}
}
class AnnotationParametersMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('', array()));
$this->add(new ConstantMatcher('\(\)', array()));
$params_matcher = new SimpleSerialMatcher(1);
$params_matcher->add(new RegexMatcher('\(\s*'));
$params_matcher->add(new AnnotationValuesMatcher);
$params_matcher->add(new RegexMatcher('\s*\)'));
$this->add($params_matcher);
}
}
class AnnotationValuesMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationTopValueMatcher);
$this->add(new AnnotationHashMatcher);
}
}
class AnnotationTopValueMatcher extends AnnotationValueMatcher {
protected function process($value) {
return array('value' => $value);
}
}
class AnnotationValueMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('true', true));
$this->add(new ConstantMatcher('false', false));
$this->add(new ConstantMatcher('TRUE', true));
$this->add(new ConstantMatcher('FALSE', false));
$this->add(new AnnotationStringMatcher);
$this->add(new AnnotationNumberMatcher);
$this->add(new AnnotationArrayMatcher);
$this->add(new AnnotationStaticConstantMatcher);
}
}
class AnnotationKeyMatcher extends ParallelMatcher {
protected function build() {
$this->add(new RegexMatcher('[a-zA-Z][a-zA-Z0-9_]*'));
$this->add(new AnnotationStringMatcher);
$this->add(new AnnotationIntegerMatcher);
}
}
class AnnotationPairMatcher extends SerialMatcher {
protected function build() {
$this->add(new AnnotationKeyMatcher);
$this->add(new RegexMatcher('\s*=\s*'));
$this->add(new AnnotationValueMatcher);
}
protected function process($parts) {
return array($parts[0] => $parts[2]);
}
}
class AnnotationHashMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationPairMatcher);
$this->add(new AnnotationMorePairsMatcher);
}
}
class AnnotationMorePairsMatcher extends SerialMatcher {
protected function build() {
$this->add(new AnnotationPairMatcher);
$this->add(new RegexMatcher('\s*,\s*'));
$this->add(new AnnotationHashMatcher);
}
protected function match($string, &$value) {
$result = parent::match($string, $value);
return $result;
}
public function process($parts) {
return array_merge($parts[0], $parts[2]);
}
}
class AnnotationArrayMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('{}', array()));
$values_matcher = new SimpleSerialMatcher(1);
$values_matcher->add(new RegexMatcher('\s*{\s*'));
$values_matcher->add(new AnnotationArrayValuesMatcher);
$values_matcher->add(new RegexMatcher('\s*}\s*'));
$this->add($values_matcher);
}
}
class AnnotationArrayValuesMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationArrayValueMatcher);
$this->add(new AnnotationMoreValuesMatcher);
}
}
class AnnotationMoreValuesMatcher extends SimpleSerialMatcher {
protected function build() {
$this->add(new AnnotationArrayValueMatcher);
$this->add(new RegexMatcher('\s*,\s*'));
$this->add(new AnnotationArrayValuesMatcher);
}
protected function match($string, &$value) {
$result = parent::match($string, $value);
return $result;
}
public function process($parts) {
return array_merge($parts[0], $parts[2]);
}
}
class AnnotationArrayValueMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationValueInArrayMatcher);
$this->add(new AnnotationPairMatcher);
}
}
class AnnotationValueInArrayMatcher extends AnnotationValueMatcher {
public function process($value) {
return array($value);
}
}
class AnnotationStringMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationSingleQuotedStringMatcher);
$this->add(new AnnotationDoubleQuotedStringMatcher);
}
}
class AnnotationNumberMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("-?[0-9]*\.?[0-9]*");
}
protected function process($matches) {
$isFloat = strpos($matches[0], '.') !== false;
return $isFloat ? (float) $matches[0] : (int) $matches[0];
}
}
class AnnotationIntegerMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("-?[0-9]*");
}
protected function process($matches) {
return (int) $matches[0];
}
}
class AnnotationSingleQuotedStringMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("'([^']*)'");
}
protected function process($matches) {
return $matches[1];
}
}
class AnnotationDoubleQuotedStringMatcher extends RegexMatcher {
public function __construct() {
parent::__construct('"([^"]*)"');
}
protected function process($matches) {
return $matches[1];
}
}
class AnnotationStaticConstantMatcher extends RegexMatcher {
public function __construct() {
parent::__construct('(\w+::\w+)');
}
protected function process($matches) {
$name = $matches[1];
if(!defined($name)) {
trigger_error("Constant '$name' used in annotation was not defined.");
return false;
}
return constant($name);
}
}
?>
<?php
class DocComment {
private static $classes = array();
private static $methods = array();
private static $fields = array();
private static $parsedFiles = array();
public static function clearCache() {
self::$classes = array();
self::$methods = array();
self::$fields = array();
self::$parsedFiles = array();
}
public function get($reflection) {
if($reflection instanceof ReflectionClass) {
return $this->forClass($reflection);
} elseif($reflection instanceof ReflectionMethod) {
return $this->forMethod($reflection);
} elseif($reflection instanceof ReflectionProperty) {
return $this->forProperty($reflection);
}
}
public function forClass($reflection) {
$this->process($reflection->getFileName());
$name = $reflection->getName();
return isset(self::$classes[$name]) ? self::$classes[$name] : false;
}
public function forMethod($reflection) {
$this->process($reflection->getDeclaringClass()->getFileName());
$class = $reflection->getDeclaringClass()->getName();
$method = $reflection->getName();
return isset(self::$methods[$class][$method]) ? self::$methods[$class][$method] : false;
}
public function forProperty($reflection) {
$this->process($reflection->getDeclaringClass()->getFileName());
$class = $reflection->getDeclaringClass()->getName();
$field = $reflection->getName();
return isset(self::$fields[$class][$field]) ? self::$fields[$class][$field] : false;
}
private function process($file) {
if(!isset(self::$parsedFiles[$file])) {
$this->parse($file);
self::$parsedFiles[$file] = true;
}
}
protected function parse($file) {
$tokens = $this->getTokens($file);
$currentClass = false;
$currentBlock = false;
$max = count($tokens);
$i = 0;
while($i < $max) {
$token = $tokens[$i];
if(is_array($token)) {
list($code, $value) = $token;
switch($code) {
case T_DOC_COMMENT:
$comment = $value;
break;
case T_CLASS:
$class = $this->getString($tokens, $i, $max);
if($comment !== false) {
self::$classes[$class] = $comment;
$comment = false;
}
break;
case T_VARIABLE:
if($comment !== false) {
$field = substr($token[1], 1);
self::$fields[$class][$field] = $comment;
$comment = false;
}
break;
case T_FUNCTION:
if($comment !== false) {
$function = $this->getString($tokens, $i, $max);
self::$methods[$class][$function] = $comment;
$comment = false;
}
break;
// ignore
case T_WHITESPACE:
case T_PUBLIC:
case T_PROTECTED:
case T_PRIVATE:
case T_ABSTRACT:
case T_FINAL:
case T_VAR:
break;
default:
$comment = false;
break;
}
} else {
$comment = false;
}
$i++;
}
}
private function getString($tokens, &$i, $max) {
do {
$token = $tokens[$i];
$i++;
if(is_array($token)) {
if($token[0] == T_STRING) {
return $token[1];
}
}
} while($i <= $max);
return false;
}
private function getTokens($file) {
return token_get_all(file_get_contents($file));
}
}
?>
\ No newline at end of file
<?php
require_once('simpletest/unit_tester.php');
require_once('simpletest/reporter.php');
require_once(dirname(__FILE__).'/acceptance_test.php');
require_once(dirname(__FILE__).'/annotation_test.php');
require_once(dirname(__FILE__).'/constrained_annotation_test.php');
require_once(dirname(__FILE__).'/annotation_parser_test.php');
require_once(dirname(__FILE__).'/doc_comment_test.php');
$suite = new TestSuite('All tests');
$suite->add(new TestOfAnnotations);
$suite->add(new TestOfPerformanceFeatures);
$suite->add(new TestOfSupportingFeatures);
$suite->add(new TestOfAnnotation);
$suite->add(new TestOfConstrainedAnnotation);
$suite->add(new TestOfMatchers);
$suite->add(new TestOfAnnotationMatchers);
$suite->add(new TestOfDocComment);
$reporter = TextReporter::inCli() ? new TextReporter() : new HtmlReporter();
Addendum::setRawMode(false);
$suite->run($reporter);
Addendum::setRawMode(true);
$suite->run($reporter);
?>
<?php
require_once('simpletest/autorun.php');
require_once(dirname(__FILE__).'/../../annotations.php');
class TestingAnnotation extends Annotation {
public $optional = 'default';
public $required;
}
class TestOfAnnotation extends UnitTestCase {
public function testConstructorsFillsParameters() {
$annotation = new TestingAnnotation(array('optional' => 1, 'required' => 2), $this);
$this->assertEqual($annotation->optional, 1);
$this->assertEqual($annotation->required, 2);
}
public function testConstructorThrowsErrorOnInvalidParameter() {
$this->expectError("Property 'unknown' not defined for annotation 'TestingAnnotation'");
$annotation = new TestingAnnotation(array('unknown' => 1), $this);
}
public function TODO_testConstructorThrowsErrorWithoutSpecifingRequiredParameters() {
$this->expectError("Property 'required' in annotation 'TestingAnnotation' is required");
$annotation = new TestingAnnotation();
}
}
?>
<?php
require_once('simpletest/autorun.php');
require_once(dirname(__FILE__).'/../../annotations.php');
/** @Target("class") */
class ClassRestrictedAnnotation extends Annotation {}
/** @Target("method") */
class MethodRestrictedAnnotation extends Annotation {}
/** @Target("property") */
class PropertyRestrictedAnnotation extends Annotation {}
/** @Target({"class", "property"}) */
class ClassOrPropertyRestrictedAnnotation extends Annotation {}
class BadlyAnnotatedClass {
/** @ClassRestrictedAnnotation */
private $property;
/** @ClassRestrictedAnnotation */
public function method() {}
/** @ClassOrPropertyRestrictedAnnotation */
public function method2() {}
}
/** @ClassRestrictedAnnotation */
class SuccesfullyAnnotatedClass {
/** @PropertyRestrictedAnnotation */
private $property;
/** @ClassOrPropertyRestrictedAnnotation */
private $property2;
/** @MethodRestrictedAnnotation */
public function method() {}
}
class TestOfConstrainedAnnotation extends UnitTestCase {
public function testClassAnnotationThrowsErrorWhenOnMethod() {
$this->expectError("Annotation 'ClassRestrictedAnnotation' not allowed on BadlyAnnotatedClass::method");
$reflection = new ReflectionAnnotatedClass('BadlyAnnotatedClass');
$method = $reflection->getMethod('method');
}
public function testClassAnnotationThrowsErrorWhenOnProperty() {
$this->expectError("Annotation 'ClassRestrictedAnnotation' not allowed on BadlyAnnotatedClass::\$property");
$reflection = new ReflectionAnnotatedClass('BadlyAnnotatedClass');
$method = $reflection->getProperty('property');
}
public function testSingleTargetAnnotationThrowsNoErrorWhenOnRightPlace() {
$reflection = new ReflectionAnnotatedClass('SuccesfullyAnnotatedClass');
$method = $reflection->getMethod('method');
$property = $reflection->getProperty('property');
}
public function testMultiTargetAnnotationThrowsErrorWhenOnWrongPlace() {
$this->expectError("Annotation 'ClassOrPropertyRestrictedAnnotation' not allowed on BadlyAnnotatedClass::method2");
$reflection = new ReflectionAnnotatedClass('BadlyAnnotatedClass');
$method = $reflection->getMethod('method2');
}
public function testMultiTargetAnnotationThrowsNoErrorWhenOnRightPlace() {
$reflection = new ReflectionAnnotatedClass('SuccesfullyAnnotatedClass');
$method = $reflection->getProperty('property2');
}
}
?>
<?php
require_once('simpletest/autorun.php');
require_once('simpletest/mock_objects.php');
require_once(dirname(__FILE__).'/../doc_comment.php');
Mock::generatePartial('DocComment', 'MockDocComment', array('parse'));
/** class doccomment */
class SomeClass {
/** field doccomment */
private $field1;
private $field2;
/** method1 doccomment */
public function method1() {
}
public function method2() {}
/** bad one */
}
class SomeOtherClass {
/** field doccomment */
private $field1;
}
class TestOfDocComment extends UnitTestCase {
public function setUp() {
DocComment::clearCache();
}
public function testFinderFindsClassDocBlock() {
$reflection = new ReflectionClass('SomeClass');
$finder = new DocComment();
$this->assertEqual($finder->get($reflection), '/** class doccomment */');
}
public function testFinderFindsFieldDocBlock() {
$reflection = new ReflectionClass('SomeClass');
$property = $reflection->getProperty('field1');
$finder = new DocComment();
$this->assertEqual($finder->get($property), '/** field doccomment */');
$property = $reflection->getProperty('field2');
$finder = new DocComment();
$this->assertFalse($finder->get($property));
}
public function testFinderFindsMethodDocBlock() {
$reflection = new ReflectionClass('SomeClass');
$method = $reflection->getMethod('method1');
$finder = new DocComment();
$this->assertEqual($finder->get($method), '/** method1 doccomment */');
$method = $reflection->getMethod('method2');
$finder = new DocComment();
$this->assertFalse($finder->get($method));
}
public function testMisplacedDocCommentDoesNotCausesDisaster() {
$reflection = new ReflectionClass('SomeOtherClass');
$finder = new DocComment();
$this->assertEqual($finder->get($reflection), false);
}
public function testUnanotatedClassCanHaveAnotatedField() {
$reflection = new ReflectionClass('SomeOtherClass');
$property = $reflection->getProperty('field1');
$finder = new DocComment();
$this->assertEqual($finder->get($property), '/** field doccomment */');
}
public function testParserIsOnlyCalledOncePerFile() {
$reflection = new ReflectionClass('SomeClass');
$finder = new MockDocComment();
$finder->expectOnce('parse');
$this->assertEqual($finder->get($reflection), false);
$this->assertEqual($finder->get($reflection), false);
$reflection = new ReflectionClass('SomeClass');
$finder = new MockDocComment();
$finder->expectNever('parse');
$this->assertEqual($finder->get($reflection), false);
}
}
?>
......@@ -31,8 +31,7 @@ class AnnotationReaderTest extends \Doctrine\Tests\DoctrineTestCase
$methodAnnots = $reader->getMethodAnnotations($getField1Method);
$this->assertEquals(1, count($methodAnnots));
$this->assertTrue($methodAnnots[$annotName] instanceof DummyAnnotation);
$this->assertEquals("methodHello", $methodAnnots[$annotName]->dummyValue);
$this->assertEquals(array(array(1, 2, "three")), $methodAnnots[$annotName]->value);
$this->assertEquals(array(1, 2, "three"), $methodAnnots[$annotName]->value);
$field2Prop = $class->getProperty('field2');
$propAnnots = $reader->getPropertyAnnotations($field2Prop);
......@@ -81,7 +80,7 @@ class DummyClass {
* Gets the value of field1.
*
* @return mixed
* @DummyAnnotation({1,2,"three"}, dummyValue="methodHello")
* @DummyAnnotation({1,2,"three"})
*/
public function getField1() {
}
......
......@@ -28,25 +28,19 @@ class ParserTest extends \Doctrine\Tests\DoctrineTestCase
$this->assertTrue(isset($annot->foo['key1']));
// Nested arrays with nested annotations
$result = $parser->parse('@Name(foo=1, 2, 3, {1,2, {"key"=@Name}})');
$result = $parser->parse('@Name(foo={1,2, {"key"=@Name}})');
$annot = $result['Doctrine\Tests\Common\Annotations\Name'];
$this->assertTrue($annot instanceof Name);
$this->assertEquals(3, count($annot->value));
$this->assertEquals(1, $annot->foo);
$this->assertEquals(2, $annot->value[0]);
$this->assertEquals(3, $annot->value[1]);
$this->assertTrue(is_array($annot->value[2]));
$nestedArray = $annot->value[2];
$this->assertEquals(3, count($nestedArray));
$this->assertEquals(1, $nestedArray[0]);
$this->assertEquals(2, $nestedArray[1]);
$this->assertTrue(is_array($nestedArray[2]));
$this->assertNull($annot->value);
$this->assertEquals(3, count($annot->foo));
$this->assertEquals(1, $annot->foo[0]);
$this->assertEquals(2, $annot->foo[1]);
$this->assertTrue(is_array($annot->foo[2]));
$nestedArray2 = $nestedArray[2];
$this->assertTrue(isset($nestedArray2['key']));
$this->assertTrue($nestedArray2['key'] instanceof Name);
$nestedArray = $annot->foo[2];
$this->assertTrue(isset($nestedArray['key']));
$this->assertTrue($nestedArray['key'] instanceof Name);
// Complete docblock
$docblock = <<<DOCBLOCK
......
......@@ -40,8 +40,8 @@ class CmsUser
/**
* @ManyToMany(targetEntity="CmsGroup", cascade={"save"})
* @JoinTable(name="cms_users_groups",
joinColumns={{"name"="user_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="group_id", "referencedColumnName"="id"}})
joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")})
*/
public $groups;
......
......@@ -35,8 +35,8 @@ class CompanyPerson
/**
* @ManyToMany(targetEntity="CompanyPerson")
* @JoinTable(name="company_persons_friends",
joinColumns={{"name"="person_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="friend_id", "referencedColumnName"="id"}})
joinColumns={@JoinColumn(name="person_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="friend_id", referencedColumnName="id")})
*/
private $friends;
......
......@@ -35,8 +35,8 @@ class ECommerceCart
/**
* @ManyToMany(targetEntity="ECommerceProduct", cascade={"save"})
* @JoinTable(name="ecommerce_carts_products",
joinColumns={{"name"="cart_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="product_id", "referencedColumnName"="id"}})
joinColumns={@JoinColumn(name="cart_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="product_id", referencedColumnName="id")})
*/
private $products;
......
......@@ -40,8 +40,8 @@ class ECommerceProduct
/**
* @ManyToMany(targetEntity="ECommerceCategory", cascade={"save"})
* @JoinTable(name="ecommerce_products_categories",
joinColumns={{"name"="product_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="category_id", "referencedColumnName"="id"}})
joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="category_id", referencedColumnName="id")})
*/
private $categories;
......@@ -50,8 +50,8 @@ class ECommerceProduct
* simplicity.
* @ManyToMany(targetEntity="ECommerceProduct", cascade={"save"})
* @JoinTable(name="ecommerce_products_related",
joinColumns={{"name"="product_id", "referencedColumnName"="id"}},
inverseJoinColumns={{"name"="related_id", "referencedColumnName"="id"}})
joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="related_id", referencedColumnName="id")})
*/
private $related;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment