Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

[DCOM-94] Support for constants on annotation #104

Merged
merged 3 commits into from

6 participants

@FabioBatSilva

Hello

This patch adds support for constants on annotation readers (DocParser)

The following usage are allowed :

<?php
/**
* @SomeAnnotation(PHP_EOL)
* @SomeAnnotation(SomeClass::SOME_VALUE)
* @SomeAnnotation({SomeClass::VALUE1,SomeClass::VALUE2})
* @SomeAnnotation({SomeClass::SOME_KEY = SomeClass::SOME_VALUE})
*/

Please let me know if can I make some thing better

Thanks

@schmittjoh
Collaborator

How does this affect the caching? I think it's broken if we add support for this, no?

@FabioBatSilva

Hello @schmittjoh

Are you right..
But if you think this way all Cache implementation could be broken.
See the following case, I think is valid for constants or annotations classes.

1 : Write a annotation class or class contant
2 : Use that annotation / class const on the doc block of some property of a entity
3 : Read the entity annotation and cache this result
4 : Change the annotation class or class contant
5 : Read the entity annotation from cache

On the step 5 the cached reader will check only the life time from entity class
then the cache will be valid, but the annotation class or class contant is changed and the cache is broken.

What you think about ?

@Ocramius
Owner

@FabioBatSilva @schmittjoh I think that changing any other class when results are already cached would need a cache refresh anyway, as cache could be broken in any case.

Let's take a simple example where you remove a field from a parent class that is not an @Entity nor an @MappedSuperclass and from which you inherit from.

Yes, the failure would be more visible because of exceptions, but it still would be caused by caching issues.

From my point of view, changing metadata or classes implicitly requires the developer to clear caches. Not an issue...

@stof
Collaborator

@Ocramius You are confusing the metadata caching and the annotation caching. We are talking about annotation cache here

@Ocramius
Owner

@stof ah, yes, but that would be the same problem to me...
Supposing you disable metadata cache and keep annotation cache only, the same concepts apply.

(sorry for having mixed up ORM/ODM concepts with common :) )

@stof
Collaborator

@Ocramius if you change the annotations in the parent class, it does not affect at all the annotations of the current class. the annotation reader does not handle inheriting stuff from the parent at all.

@FabioBatSilva

Hi guys.

The concept is the same for annotation classe, parent class, or constants.
The fix for this is more complex than the own feature.

If we not assume this as a limitation. we can't support this feature.

@schmittjoh
Collaborator

@FabioBatSilva, the case you mentioned exists, but is solely applicable to people who are writing libraries, not to end users. The latter are typically only using annotations provided by other bundles. For constants, on the other hand typically the end-user is responsible, and he will expect that if he changes the value of a constant that this is also reflected by the annotation.

Risking stale caches here is not really an option to me, and I would expect that we get bug reports on that (which we cannot fix). I also don't think that telling people to manually clear their caches during development is a good idea.

I basically see three options:

1) delay evaluation of constants, and re-evaluate each time an annotation is loaded from cache
2) limit possible constants to constants of the same class (no parent classes), or PHP constants
3) do not change anything

What was the use case for allowing constants?

@Ocramius
Owner

@stof yep, sorry, had to read again in the code, guess I'm exaggerating again :)

@FabioBatSilva this is a very interesting feature for me, and it adds a lot of flexibility. For me, code change = wiping cache, and I've always done that. @schmittjoh I guess that documenting this would be fine...

@stof
Collaborator

@Ocramius it is not. We get many reports about documented behaviors, because unfortunately people read the doc after reporting an issue and being told to RTFM, not before.
So a feature causing WTF in dev when all other caches are regenerating themselves is not a good idea IMO

@FabioBatSilva

I think class constants is the more usual.
This could make configurations more flexible.
i'm not sure about re-evaluate each time, could create a considerable impact on performance.

My suggestion is: Support this considering the cache in dev a limitation or does not suport this.

@Ocramius
Owner

Re-evaluating every time makes it very difficult to cache anything and would surely cause performance degradation.
Supporting only class constants would imo result in a total mess, worse than the scenario @stof has painted (at least from the question-answer perspective).
I still think this is a great feature, and it shouldn't be blocked by RTFM users. If we want to argue about that, there's still the NativeSQL on annotations PR on ORM, right @FabioBatSilva? :D

@FabioBatSilva

Hi guys :)
@guilhermeblanco @beberlei @asm89 @jwage

What do you think about this ?

@beberlei
Owner

+1 from me, did you by any chance test the performance impact on the regex and grammer change? I doubt its significant, just checking.

@guilhermeblanco

+1, can I merge?

@FabioBatSilva

Hi @beberlei

The test performance are very similar but a little more slower :

Current master :

phpunit tests/Doctrine/Tests/Common/Annotations/PerformanceTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /Users/fabio/workspace/doctrine-common/phpunit.xml

.
----------------------------------
cached reader (in-memory) results:
==================================
Iterations:         500
Total Time:         0.004 s
Time per iteration: 0.008 ms
----------------------------------
.
-----------------------------
cached reader (file) results:
=============================
Iterations:         500
Total Time:         0.071 s
Time per iteration: 0.142 ms
-----------------------------
.
----------------------------
reader results:
============================
Iterations:         150
Total Time:         0.172 s
Time per iteration: 1.147 ms
----------------------------
.
----------------------------
doc-parser results:
============================
Iterations:         200
Total Time:         0.145 s
Time per iteration: 0.727 ms
----------------------------
.
----------------------------
doc-lexer results:
============================
Iterations:         500
Total Time:         0.120 s
Time per iteration: 0.239 ms
----------------------------
.
----------------------------------
doc-parser-with-short-cut results:
==================================
Iterations:         500
Total Time:         0.240 s
Time per iteration: 0.479 ms
----------------------------------
.
-------------------------------------
doc-parser-without-short-cut results:
=====================================
Iterations:         500
Total Time:         0.183 s
Time per iteration: 0.365 ms
-------------------------------------


Time: 1 second, Memory: 5.75Mb

OK (7 tests, 0 assertions)

My branch annot-const :

phpunit tests/Doctrine/Tests/Common/Annotations/PerformanceTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /Users/fabio/workspace/doctrine-common/phpunit.xml

.
----------------------------------
cached reader (in-memory) results:
==================================
Iterations:         500
Total Time:         0.004 s
Time per iteration: 0.008 ms
----------------------------------
.
-----------------------------
cached reader (file) results:
=============================
Iterations:         500
Total Time:         0.073 s
Time per iteration: 0.147 ms
-----------------------------
.
----------------------------
reader results:
============================
Iterations:         150
Total Time:         0.176 s
Time per iteration: 1.170 ms
----------------------------
.
----------------------------
doc-parser results:
============================
Iterations:         200
Total Time:         0.149 s
Time per iteration: 0.746 ms
----------------------------
.
----------------------------
doc-lexer results:
============================
Iterations:         500
Total Time:         0.122 s
Time per iteration: 0.245 ms
----------------------------
.
----------------------------------
doc-parser-with-short-cut results:
==================================
Iterations:         500
Total Time:         0.250 s
Time per iteration: 0.499 ms
----------------------------------
.
-------------------------------------
doc-parser-without-short-cut results:
=====================================
Iterations:         500
Total Time:         0.182 s
Time per iteration: 0.365 ms
-------------------------------------


Time: 1 second, Memory: 5.75Mb

OK (7 tests, 0 assertions)
@schmittjoh schmittjoh merged commit 970912e into doctrine:master
@schmittjoh
Collaborator

Ok, I've merged this in.

Could you update the documentation, and also stress the fact that caches need to be cleared manually when changing constants?

@FabioBatSilva

Thanks @schmittjoh

I'll update the docs :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 5, 2012
  1. @FabioBatSilva
Commits on Feb 8, 2012
  1. @FabioBatSilva

    fix invalid identifier

    FabioBatSilva authored
  2. @FabioBatSilva

    rename test

    FabioBatSilva authored
This page is out of date. Refresh to see the latest.
View
16 lib/Doctrine/Common/Annotations/AnnotationException.php
@@ -53,6 +53,22 @@ public static function semanticalError($message)
}
/**
+ * Creates a new AnnotationException describing a constant semantical error.
+ *
+ * @since 2.3
+ * @param string $identifier
+ * @param string $context
+ * @return AnnotationException
+ */
+ public static function semanticalErrorConstants($identifier, $context = null)
+ {
+ return self::semanticalError(sprintf(
+ "Couldn't find constant %s%s", $identifier,
+ $context ? ", $context." : "."
+ ));
+ }
+
+ /**
* Creates a new AnnotationException describing an error which occurred during
* the creation of the annotation.
*
View
13 lib/Doctrine/Common/Annotations/DocLexer.php
@@ -33,11 +33,12 @@
final class DocLexer extends Lexer
{
const T_NONE = 1;
- const T_IDENTIFIER = 2;
- const T_INTEGER = 3;
- const T_STRING = 4;
- const T_FLOAT = 5;
+ const T_INTEGER = 2;
+ const T_STRING = 3;
+ const T_FLOAT = 4;
+ // All tokens that are also identifiers should be >= 100
+ const T_IDENTIFIER = 100;
const T_AT = 101;
const T_CLOSE_CURLY_BRACES = 102;
const T_CLOSE_PARENTHESIS = 103;
@@ -57,7 +58,7 @@
protected function getCatchablePatterns()
{
return array(
- '[a-z_][a-z0-9_:]*',
+ '[a-z_\\\][a-z0-9_\:\\\]*[a-z]{1}',
'(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?',
'"(?:[^"]|"")*"',
);
@@ -127,7 +128,7 @@ protected function getType(&$value)
return self::T_COLON;
default:
- if (ctype_alpha($value[0]) || $value[0] === '_') {
+ if (ctype_alpha($value[0]) || $value[0] === '_' || $value[0] === '\\') {
return self::T_IDENTIFIER;
}
View
118 lib/Doctrine/Common/Annotations/DocParser.php
@@ -537,20 +537,7 @@ private function Annotation()
$this->match(DocLexer::T_AT);
// check if we have an annotation
- if ($this->lexer->isNextTokenAny(self::$classIdentifiers)) {
- $this->lexer->moveNext();
- $name = $this->lexer->token['value'];
- } else if ($this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {
- $name = '';
- } else {
- $this->syntaxError('namespace separator or identifier');
- }
-
- while ($this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value']) && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {
- $this->match(DocLexer::T_NAMESPACE_SEPARATOR);
- $this->matchAny(self::$classIdentifiers);
- $name .= '\\'.$this->lexer->token['value'];
- }
+ $name = $this->Identifier();
// only process names which are not fully qualified, yet
// fully qualified names must start with a \
@@ -747,6 +734,90 @@ private function Values()
}
/**
+ * Constant ::= integer | string | float | boolean
+ *
+ * @return mixed
+ */
+ private function Constant()
+ {
+ $identifier = $this->Identifier();
+
+ if (!defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) {
+
+ list($className, $const) = explode('::', $identifier);
+ $alias = (false === $pos = strpos($className, '\\'))? $className : substr($className, 0, $pos);
+
+ $found = false;
+ switch (true) {
+ case !empty ($this->namespace):
+ foreach ($this->namespaces as $ns) {
+ if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
+ $className = $ns.'\\'.$className;
+ $found = true;
+ break;
+ }
+ }
+ break;
+
+ case isset($this->imports[$loweredAlias = strtolower($alias)]):
+ $found = true;
+ if (false !== $pos) {
+ $className = $this->imports[$loweredAlias].substr($className, $pos);
+ } else {
+ $className = $this->imports[$loweredAlias];
+ }
+ break;
+
+ default:
+ if(isset($this->imports['__NAMESPACE__'])) {
+ $ns = $this->imports['__NAMESPACE__'];
+ if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
+ $className = $ns.'\\'.$className;
+ $found = true;
+ }
+ }
+ break;
+ }
+
+ if ($found) {
+ $identifier = $className . '::' . $const;
+ }
+ }
+
+ if (!defined($identifier)) {
+ throw AnnotationException::semanticalErrorConstants($identifier, $this->context);
+ }
+
+ return constant($identifier);
+ }
+
+ /**
+ * Identifier ::= string
+ *
+ * @return string
+ */
+ private function Identifier()
+ {
+ // check if we have an annotation
+ if ($this->lexer->isNextTokenAny(self::$classIdentifiers)) {
+ $this->lexer->moveNext();
+ $className = $this->lexer->token['value'];
+ } else {
+ $this->syntaxError('namespace separator or identifier');
+ }
+
+ while ($this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value']))
+ && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {
+
+ $this->match(DocLexer::T_NAMESPACE_SEPARATOR);
+ $this->matchAny(self::$classIdentifiers);
+ $className .= '\\' . $this->lexer->token['value'];
+ }
+
+ return $className;
+ }
+
+ /**
* Value ::= PlainValue | FieldAssignment
*
* @return mixed
@@ -777,6 +848,10 @@ private function PlainValue()
return $this->Annotation();
}
+ if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
+ return $this->Constant();
+ }
+
switch ($this->lexer->lookahead['type']) {
case DocLexer::T_STRING:
$this->match(DocLexer::T_STRING);
@@ -838,7 +913,7 @@ private function Arrayx()
$this->match(DocLexer::T_OPEN_CURLY_BRACES);
$values[] = $this->ArrayEntry();
-
+
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
$this->match(DocLexer::T_COMMA);
@@ -867,8 +942,8 @@ private function Arrayx()
/**
* ArrayEntry ::= Value | KeyValuePair
- * KeyValuePair ::= Key ("=" | ":") PlainValue
- * Key ::= string | integer
+ * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant
+ * Key ::= string | integer | Constant
*
* @return array
*/
@@ -878,9 +953,14 @@ private function ArrayEntry()
if (DocLexer::T_EQUALS === $peek['type']
|| DocLexer::T_COLON === $peek['type']) {
- $this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING));
- $key = $this->lexer->token['value'];
+ if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
+ $key = $this->Constant();
+ } else {
+ $this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING));
+ $key = $this->lexer->token['value'];
+ }
+
$this->matchAny(array(DocLexer::T_EQUALS, DocLexer::T_COLON));
return array($key, $this->PlainValue());
View
110 tests/Doctrine/Tests/Common/Annotations/DocLexerTest.php
@@ -24,4 +24,114 @@ public function testMarkerAnnotation()
$this->assertFalse($lexer->moveNext());
}
+
+ public function testScannerTokenizesDocBlockWhitConstants()
+ {
+ $lexer = new DocLexer();
+ $docblock = '@AnnotationWithConstants(PHP_EOL, ClassWithConstants::SOME_VALUE, \Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_VALUE)';
+
+ $tokens = array (
+ array(
+ 'value' => '@',
+ 'position' => 0,
+ 'type' => DocLexer::T_AT,
+ ),
+ array(
+ 'value' => 'AnnotationWithConstants',
+ 'position' => 1,
+ 'type' => DocLexer::T_IDENTIFIER,
+ ),
+ array(
+ 'value' => '(',
+ 'position' => 24,
+ 'type' => DocLexer::T_OPEN_PARENTHESIS,
+ ),
+ array(
+ 'value' => 'PHP_EOL',
+ 'position' => 25,
+ 'type' => DocLexer::T_IDENTIFIER,
+ ),
+ array(
+ 'value' => ',',
+ 'position' => 32,
+ 'type' => DocLexer::T_COMMA,
+ ),
+ array(
+ 'value' => 'ClassWithConstants::SOME_VALUE',
+ 'position' => 34,
+ 'type' => DocLexer::T_IDENTIFIER,
+ ),
+ array(
+ 'value' => ',',
+ 'position' => 64,
+ 'type' => DocLexer::T_COMMA,
+ ),
+ array(
+ 'value' => '\\Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IntefaceWithConstants::SOME_VALUE',
+ 'position' => 66,
+ 'type' => DocLexer::T_IDENTIFIER,
+ ),
+ array(
+ 'value' => ')',
+ 'position' => 143,
+ 'type' => DocLexer::T_CLOSE_PARENTHESIS,
+ )
+
+ );
+
+ $lexer->setInput($docblock);
+
+ foreach ($tokens as $expected) {
+ $lexer->moveNext();
+ $lookahead = $lexer->lookahead;
+ $this->assertEquals($expected['value'], $lookahead['value']);
+ $this->assertEquals($expected['type'], $lookahead['type']);
+ $this->assertEquals($expected['position'], $lookahead['position']);
+ }
+
+ $this->assertFalse($lexer->moveNext());
+ }
+
+
+ public function testScannerTokenizesDocBlockWhitInvalidIdentifier()
+ {
+ $lexer = new DocLexer();
+ $docblock = '@Foo\3.42';
+
+ $tokens = array (
+ array(
+ 'value' => '@',
+ 'position' => 0,
+ 'type' => DocLexer::T_AT,
+ ),
+ array(
+ 'value' => 'Foo',
+ 'position' => 1,
+ 'type' => DocLexer::T_IDENTIFIER,
+ ),
+ array(
+ 'value' => '\\',
+ 'position' => 4,
+ 'type' => DocLexer::T_NAMESPACE_SEPARATOR,
+ ),
+ array(
+ 'value' => 3.42,
+ 'position' => 5,
+ 'type' => DocLexer::T_FLOAT,
+ )
+ );
+
+ $lexer->setInput($docblock);
+
+ foreach ($tokens as $expected) {
+ $lexer->moveNext();
+ $lookahead = $lexer->lookahead;
+ $this->assertEquals($expected['value'], $lookahead['value']);
+ $this->assertEquals($expected['type'], $lookahead['type']);
+ $this->assertEquals($expected['position'], $lookahead['position']);
+ }
+
+ $this->assertFalse($lexer->moveNext());
+ }
+
}
View
94 tests/Doctrine/Tests/Common/Annotations/DocParserTest.php
@@ -7,6 +7,9 @@
use Doctrine\Common\Annotations\DocParser;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Annotations\Annotation\Target;
+use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants;
+use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants;
+use Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants;
class DocParserTest extends \PHPUnit_Framework_TestCase
{
@@ -662,6 +665,93 @@ public function testAnnotationWithRequiredAttributesWithoutContructor()
}
+ public function getConstantsProvider()
+ {
+ $provider[] = array(
+ '@AnnotationWithConstants(PHP_EOL)',
+ PHP_EOL
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(AnnotationWithConstants::INTEGER)',
+ AnnotationWithConstants::INTEGER
+ );
+ $provider[] = array(
+ '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants(AnnotationWithConstants::STRING)',
+ AnnotationWithConstants::STRING
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants::FLOAT)',
+ AnnotationWithConstants::FLOAT
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(ClassWithConstants::SOME_VALUE)',
+ ClassWithConstants::SOME_VALUE
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_VALUE)',
+ ClassWithConstants::SOME_VALUE
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(IntefaceWithConstants::SOME_VALUE)',
+ IntefaceWithConstants::SOME_VALUE
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants(\Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_VALUE)',
+ IntefaceWithConstants::SOME_VALUE
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants({AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT})',
+ array(AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT)
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants({
+ AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER
+ })',
+ array(AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER)
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants({
+ Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
+ })',
+ array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants({
+ \Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
+ })',
+ array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
+ );
+ $provider[] = array(
+ '@AnnotationWithConstants({
+ AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER,
+ ClassWithConstants::SOME_KEY = ClassWithConstants::SOME_VALUE,
+ Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_KEY = IntefaceWithConstants::SOME_VALUE
+ })',
+ array(
+ AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER,
+ ClassWithConstants::SOME_KEY => ClassWithConstants::SOME_VALUE,
+ ClassWithConstants::SOME_KEY => IntefaceWithConstants::SOME_VALUE
+ )
+ );
+ return $provider;
+ }
+
+ /**
+ * @dataProvider getConstantsProvider
+ */
+ public function testSupportClassConstants($docblock, $expected)
+ {
+ $parser = $this->createTestParser();
+ $parser->setImports(array(
+ 'classwithconstants' => 'Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants',
+ 'intefacewithconstants' => 'Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants',
+ 'annotationwithconstants' => 'Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants'
+ ));
+
+ $result = $parser->parse($docblock);
+ $this->assertInstanceOf('\Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants', $annotation = $result[0]);
+ $this->assertEquals($expected, $annotation->value);
+ }
/**
* @expectedException Doctrine\Common\Annotations\AnnotationException
@@ -1045,9 +1135,9 @@ public function testArrayWithColon()
/**
* @expectedException Doctrine\Common\Annotations\AnnotationException
- * @expectedExceptionMessage [Syntax Error] Expected PlainValue, got 'foo:' at position 6.
+ * @expectedExceptionMessage [Semantical Error] Couldn't find constant foo.
*/
- public function testColonNotAllowedOnTopLevel()
+ public function testInvalidContantName()
{
$parser = $this->createTestParser();
$parser->parse('@Name(foo: "bar")');
View
20 tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithConstants.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Doctrine\Tests\Common\Annotations\Fixtures;
+
+/**
+ * @Annotation
+ * @Target("ALL")
+ */
+final class AnnotationWithConstants
+{
+
+ const INTEGER = 1;
+ const FLOAT = 1.2;
+ const STRING = '1.2.3';
+
+ /**
+ * @var mixed
+ */
+ public $value;
+}
View
10 tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithConstants.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Doctrine\Tests\Common\Annotations\Fixtures;
+
+class ClassWithConstants
+{
+
+ const SOME_VALUE = 'ClassWithConstants.SOME_VALUE';
+ const SOME_KEY = 'ClassWithConstants.SOME_KEY';
+}
View
10 tests/Doctrine/Tests/Common/Annotations/Fixtures/IntefaceWithConstants.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Doctrine\Tests\Common\Annotations\Fixtures;
+
+interface IntefaceWithConstants
+{
+
+ const SOME_VALUE = 'IntefaceWithConstants.SOME_VALUE';
+ const SOME_KEY = 'IntefaceWithConstants.SOME_KEY';
+}
Something went wrong with that request. Please try again.