From a05bd5e20cb4903f5017ed686abea69cef4948e9 Mon Sep 17 00:00:00 2001 From: beberlei Date: Fri, 30 Oct 2009 20:58:06 +0000 Subject: [PATCH] [2.0] DDC-78 - Added support for context specific information in Annotation Parser Syntax Error Exceptions. --- .../Common/Annotations/AnnotationReader.php | 12 +-- lib/Doctrine/Common/Annotations/Parser.php | 21 ++++- .../Annotations/AnnotationReaderTest.php | 78 +++++++++++++++++++ .../Tests/Common/Annotations/ParserTest.php | 18 ++++- 4 files changed, 118 insertions(+), 11 deletions(-) diff --git a/lib/Doctrine/Common/Annotations/AnnotationReader.php b/lib/Doctrine/Common/Annotations/AnnotationReader.php index f7b91682f..36354fef1 100644 --- a/lib/Doctrine/Common/Annotations/AnnotationReader.php +++ b/lib/Doctrine/Common/Annotations/AnnotationReader.php @@ -99,7 +99,7 @@ class AnnotationReader return $this->_cache->fetch($cacheKey); } - $annotations = $this->_parser->parse($class->getDocComment()); + $annotations = $this->_parser->parse($class->getDocComment(), "class ".$class->getName()); $this->_cache->save($cacheKey, $annotations, null); return $annotations; @@ -133,8 +133,9 @@ class AnnotationReader if ($this->_cache->contains($cacheKey)) { return $this->_cache->fetch($cacheKey); } - - $annotations = $this->_parser->parse($property->getDocComment()); + + $context = "property ".$property->getDeclaringClass()->getName()."::\$".$property->getName(); + $annotations = $this->_parser->parse($property->getDocComment(), $context); $this->_cache->save($cacheKey, $annotations, null); return $annotations; @@ -168,8 +169,9 @@ class AnnotationReader if ($this->_cache->contains($cacheKey)) { return $this->_cache->fetch($cacheKey); } - - $annotations = $this->_parser->parse($method->getDocComment()); + + $context = "method ".$method->getDeclaringClass()->getName()."::".$method->getName()."()"; + $annotations = $this->_parser->parse($method->getDocComment(), $context); $this->_cache->save($cacheKey, $annotations, null); return $annotations; diff --git a/lib/Doctrine/Common/Annotations/Parser.php b/lib/Doctrine/Common/Annotations/Parser.php index 6ceba3d06..dbd0b6153 100644 --- a/lib/Doctrine/Common/Annotations/Parser.php +++ b/lib/Doctrine/Common/Annotations/Parser.php @@ -72,6 +72,11 @@ class Parser * @var array */ private $_namespaceAliases = array(); + + /** + * @var string + */ + private $_context = ''; /** * Constructs a new AnnotationParser. @@ -107,11 +112,14 @@ class Parser /** * Parses the given docblock string for annotations. * - * @param $docBlockString + * @param string $docBlockString + * @param string $context * @return array Array of Annotations. If no annotations are found, an empty array is returned. */ - public function parse($docBlockString) + public function parse($docBlockString, $context='') { + $this->_context = $context; + // Strip out some known inline tags. $input = str_replace(self::$_strippedInlineTags, '', $docBlockString); @@ -164,10 +172,15 @@ class Parser $message = "Expected '{$expected}', got "; if ($this->_lexer->lookahead === null) { - $message .= 'end of string.'; + $message .= 'end of string'; } else { - $message .= "'{$token['value']}' at position {$token['position']}."; + $message .= "'{$token['value']}' at position {$token['position']}"; } + + if(strlen($this->_context)) { + $message .= ' in '.$this->_context; + } + $message .= '.'; throw AnnotationException::syntaxError($message); } diff --git a/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php b/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php index 8973f9183..013a4dc39 100644 --- a/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php +++ b/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php @@ -57,6 +57,57 @@ class AnnotationReaderTest extends \Doctrine\Tests\DoctrineTestCase $classAnnot = $reader->getClassAnnotation($class, 'Doctrine\Tests\Common\Annotations\DummyAnnotation'); $this->assertEquals('hello', $classAnnot->dummyValue); } + + public function testClassSyntaxErrorContext() + { + $this->setExpectedException( + "Doctrine\Common\Annotations\AnnotationException", + "[Syntax Error] Expected '', got ')' at position 18 in class ". + "Doctrine\Tests\Common\Annotations\DummyClassSyntaxError." + ); + + $class = new \ReflectionClass('\Doctrine\Tests\Common\Annotations\DummyClassSyntaxError'); + + $reader = $this->createAnnotationReader(); + $reader->getClassAnnotations($class); + } + + public function testMethodSyntaxErrorContext() + { + $this->setExpectedException( + "Doctrine\Common\Annotations\AnnotationException", + "[Syntax Error] Expected '', got ')' at position 18 in ". + "method Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError::foo()." + ); + + $class = new \ReflectionClass('\Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError'); + $method = $class->getMethod('foo'); + + $reader = $this->createAnnotationReader(); + $reader->getMethodAnnotations($method); + } + + public function testPropertySyntaxErrorContext() + { + $this->setExpectedException( + "Doctrine\Common\Annotations\AnnotationException", + "[Syntax Error] Expected '', got ')' at position 18 in ". + "property Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError::\$foo." + ); + + $class = new \ReflectionClass('\Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError'); + $property = $class->getProperty('foo'); + + $reader = $this->createAnnotationReader(); + $reader->getPropertyAnnotations($property); + } + + public function createAnnotationReader() + { + $reader = new AnnotationReader(new \Doctrine\Common\Cache\ArrayCache); + $reader->setDefaultAnnotationNamespace('Doctrine\Tests\Common\Annotations\\'); + return $reader; + } } /** @@ -107,4 +158,31 @@ class DummyJoinTable extends \Doctrine\Common\Annotations\Annotation { public $name; public $joinColumns; public $inverseJoinColumns; +} + +/** + * @DummyAnnotation(@) + */ +class DummyClassSyntaxError +{ + +} + +class DummyClassMethodSyntaxError +{ + /** + * @DummyAnnotation(@) + */ + public function foo() + { + + } +} + +class DummyClassPropertySyntaxError +{ + /** + * @DummyAnnotation(@) + */ + public $foo; } \ No newline at end of file diff --git a/tests/Doctrine/Tests/Common/Annotations/ParserTest.php b/tests/Doctrine/Tests/Common/Annotations/ParserTest.php index fbc66dd9e..8f663d05f 100644 --- a/tests/Doctrine/Tests/Common/Annotations/ParserTest.php +++ b/tests/Doctrine/Tests/Common/Annotations/ParserTest.php @@ -10,8 +10,7 @@ class ParserTest extends \Doctrine\Tests\DoctrineTestCase { public function testBasicAnnotations() { - $parser = new Parser; - $parser->setDefaultAnnotationNamespace('Doctrine\Tests\Common\Annotations\\'); + $parser = $this->createTestParser(); // Marker annotation $result = $parser->parse("@Name"); @@ -108,6 +107,21 @@ DOCBLOCK; $parser->setDefaultAnnotationNamespace('Doctrine\Tests\Common\Annotations\\'); return $parser; } + + /** + * @group DDC-78 + */ + public function testSyntaxErrorWithContextDescription() + { + $this->setExpectedException( + 'Doctrine\Common\Annotations\AnnotationException', + "[Syntax Error] Expected 'PlainValue', got ''' at position 10 ". + "in class \Doctrine\Tests\Common\Annotations\Name" + ); + + $parser = $this->createTestParser(); + $parser->parse("@Name(foo='bar')", "class \Doctrine\Tests\Common\Annotations\Name"); + } } class Name extends \Doctrine\Common\Annotations\Annotation {