Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

adds parsing for some PHPDoc annotations

  • Loading branch information...
commit 6bad124f40689cc3fa655b111048c04515d18679 1 parent 31e5f19
@schmittjoh schmittjoh authored
View
15 lib/Doctrine/Common/Annotations/Annotation/Author.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Doctrine\Common\Annotations\Annotation;
+
+final class Author
+{
+ public $name;
+
+ public function __construct(array $values)
+ {
+ if (isset($values['value'])) {
+ $this->name = $values['value'];
+ }
+ }
+}
View
15 lib/Doctrine/Common/Annotations/Annotation/Since.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Doctrine\Common\Annotations\Annotation;
+
+final class Since
+{
+ public $version;
+
+ public function __construct(array $values)
+ {
+ if (isset($values['value'])) {
+ $this->version = $values['value'];
+ }
+ }
+}
View
38 lib/Doctrine/Common/Annotations/Annotation/Type.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Doctrine\Common\Annotations\Annotation;
+
+final class Type
+{
+ const TYPE_INTEGER = 'integer';
+ const TYPE_DOUBLE = 'double';
+ const TYPE_BOOLEAN = 'boolean';
+ const TYPE_ARRAY = 'array';
+ const TYPE_UNKNOWN = 'unknown';
+
+ public $name;
+ public $type;
+
+ public function __construct(array $values)
+ {
+ if (isset($values['value'])) {
+ $name = $values['value'];
+ if (false !== $pos = strpos($name, ' ')) {
+ $name = substr($name, 0, $pos);
+ }
+ $this->name = $name;
+
+ if ('integer' === $name || 'int' === $name) {
+ $this->type = self::TYPE_INTEGER;
+ } else if ('double' === $name || 'float' === $name) {
+ $this->type = self::TYPE_FLOAT;
+ } else if ('string' === $name) {
+ $this->type = self::TYPE_STRING;
+ } else if ('array' === $name) {
+ $this->type = self::TYPE_ARRAY;
+ } else {
+ $this->type = self::TYPE_UNKNOWN;
+ }

forgotten boolean? :-)

TYPE_STRING is not defined...

And what about @var SomeObject? I'd opt for splitting at whitespace and simply use type and (optional) description from that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ }
+ }
+}
View
9 lib/Doctrine/Common/Annotations/AnnotationReader.php
@@ -43,6 +43,9 @@
*/
private static $globalImports = array(
'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation',
+ 'var' => 'Doctrine\Common\Annotations\Annotation\Type',
+ 'author' => 'Doctrine\Common\Annotations\Annotation\Author',
+ 'since' => 'Doctrine\Common\Annotations\Annotation\Since',
);
/**
@@ -110,9 +113,7 @@ static public function addGlobalIgnoredName($name)
private $ignoredAnnotationNames = array();
/**
- * Constructor. Initializes a new AnnotationReader that uses the given Cache provider.
- *
- * @param DocParser $parser The parser to use. If none is provided, the default parser is used.
+ * Constructor. Initializes a new AnnotationReader.
*/
public function __construct()
{
@@ -307,8 +308,8 @@ private function collectParsingMetadata(ReflectionClass $class)
$name = $class->getName();
$this->imports[$name] = array_merge(
- self::$globalImports,
$this->phpParser->parseClass($class),
+ self::$globalImports,
array('__NAMESPACE__' => $class->getNamespaceName())
);
$this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames;
View
56 lib/Doctrine/Common/Annotations/DocParser.php
@@ -274,20 +274,11 @@ private function Annotations()
continue;
}
- // make sure the @ is preceded by non-catchable pattern
- if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
+ if (!$this->isAtMarkingAnnotation()) {
$this->lexer->moveNext();
continue;
}
- // make sure the @ is followed by either a namespace separator, or
- // an identifier token
- if ((null === $peek = $this->lexer->glimpse())
- || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true))
- || $peek['position'] !== $this->lexer->lookahead['position'] + 1) {
- $this->lexer->moveNext();
- continue;
- }
$this->isNestedAnnotation = false;
if (false !== $annot = $this->Annotation()) {
@@ -298,8 +289,26 @@ private function Annotations()
return $annotations;
}
+ private function isAtMarkingAnnotation()
+ {
+ // make sure the @ is preceded by non-catchable pattern
+ if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
+ return false;
+ }
+
+ // make sure the @ is followed by either a namespace separator, or
+ // an identifier token
+ if ((null === $peek = $this->lexer->glimpse())
+ || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true))
+ || $peek['position'] !== $this->lexer->lookahead['position'] + 1) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
- * Annotation ::= "@" AnnotationName ["(" [Values] ")"]
+ * Annotation ::= "@" AnnotationName ( ["(" [Values] ")"] | { ¬ @ }* )
* AnnotationName ::= QualifiedName | SimpleName
* QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
* NameSpacePart ::= identifier | null | false | true
@@ -357,17 +366,40 @@ private function Annotation()
// that it is loaded
// Next will be nested
- $this->isNestedAnnotation = true;
$values = array();
if ($this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) {
$this->match(DocLexer::T_OPEN_PARENTHESIS);
+ $this->isNestedAnnotation = true;
if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
$values = $this->Values();
}
$this->match(DocLexer::T_CLOSE_PARENTHESIS);
+ } else if (!$this->isNestedAnnotation) {
+ // take everything until the next @
+ $value = '';
+ while (null !== $this->lexer->lookahead
+ && (DocLexer::T_AT !== $this->lexer->lookahead['type'] || !$this->isAtMarkingAnnotation())) {
+ $this->lexer->moveNext();
+
+ if (DocLexer::T_STRING === $this->lexer->token['type']) {
+ $value .= '"'.$this->lexer->token['value'].'"';
+
+ if ($this->lexer->lookahead['position'] - 2 !== $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
+ $value .= ' ';
+ }
+ } else {
+ $value .= $this->lexer->token['value'];
+
+ if ($this->lexer->lookahead['position'] !== $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
+ $value .= ' ';
+ }
+ }
+ }
+
+ $values['value'] = '' === $value ? null : trim($value);
}
return new $name($values);
View
6 tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php
@@ -16,13 +16,13 @@ public function testAnnotations()
$reader = $this->getReader();
$class = new ReflectionClass('Doctrine\Tests\Common\Annotations\DummyClass');
- $this->assertEquals(1, count($reader->getClassAnnotations($class)));
+ $this->assertEquals(4, count($reader->getClassAnnotations($class)));
$this->assertInstanceOf($annotName = 'Doctrine\Tests\Common\Annotations\DummyAnnotation', $annot = $reader->getClassAnnotation($class, $annotName));
$this->assertEquals("hello", $annot->dummyValue);
$field1Prop = $class->getProperty('field1');
$propAnnots = $reader->getPropertyAnnotations($field1Prop);
- $this->assertEquals(1, count($propAnnots));
+ $this->assertEquals(2, count($propAnnots));
$this->assertInstanceOf($annotName, $annot = $reader->getPropertyAnnotation($field1Prop, $annotName));
$this->assertEquals("fieldHello", $annot->dummyValue);
@@ -93,7 +93,7 @@ public function testMultipleAnnotationsOnSameLine()
{
$reader = $this->getReader();
$annots = $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClass2', 'id'));
- $this->assertEquals(3, count($annots));
+ $this->assertEquals(4, count($annots));
}
public function testNonAnnotationProblem()
View
3  tests/Doctrine/Tests/Common/Annotations/CachedReaderTest.php
@@ -2,6 +2,8 @@
namespace Doctrine\Tests\Common\Annotations;
+use Doctrine\Common\Annotations\Annotation\Author;
+
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
@@ -45,6 +47,7 @@ public function testIgnoresStaleCache()
$reader = new CachedReader(new AnnotationReader(), $cache, true);
$this->assertEquals(array(
new Route(array('value' => '/someprefix')),
+ new Author(array('value' => 'Johannes M. Schmitt <schmittjoh@gmail.com>'))
), $reader->getClassAnnotations(new \ReflectionClass($name)));
}
Please sign in to comment.
Something went wrong with that request. Please try again.