Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Constants Support #263

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/Doctrine/Common/Annotations/Annotation/Target.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ final class Target
public const TARGET_PROPERTY = 4;
public const TARGET_ANNOTATION = 8;
public const TARGET_FUNCTION = 16;
public const TARGET_ALL = 31;
public const TARGET_CONSTANT = 32;
public const TARGET_ALL = 63;

/** @var array<string, int> */
private static $map = [
Expand All @@ -36,6 +37,7 @@ final class Target
'PROPERTY' => self::TARGET_PROPERTY,
'FUNCTION' => self::TARGET_FUNCTION,
'ANNOTATION' => self::TARGET_ANNOTATION,
'CONSTANT' => self::TARGET_CONSTANT,
];

/** @phpstan-var list<string> */
Expand Down
56 changes: 55 additions & 1 deletion lib/Doctrine/Common/Annotations/AnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* A reader for docblock annotations.
*/
class AnnotationReader implements Reader
class AnnotationReader implements Reader, ReaderWithConstantsAnnotations
{
/**
* Global map for imports.
Expand Down Expand Up @@ -226,6 +226,38 @@ public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
return null;
}

/**
* {@inheritDoc}
*/
jkufner marked this conversation as resolved.
Show resolved Hide resolved
public function getConstantAnnotations(\ReflectionClassConstant $constant): array
{
$class = $constant->getDeclaringClass();
$context = 'constant ' . $class->getName() . "::" . $constant->getName();

$this->parser->setTarget(Target::TARGET_CONSTANT);
$this->parser->setImports($this->getConstantImports($constant));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);

return $this->parser->parse($constant->getDocComment(), $context);
}

/**
* {@inheritDoc}
*/
jkufner marked this conversation as resolved.
Show resolved Hide resolved
public function getConstantAnnotation(\ReflectionClassConstant $constant, $annotationName)
{
$annotations = $this->getConstantAnnotations($constant);

foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}

return null;
}

/**
* Gets the annotations applied to a function.
*
Expand Down Expand Up @@ -352,6 +384,28 @@ private function getPropertyImports(ReflectionProperty $property)
return array_merge($classImports, $traitImports);
}

/**
* Retrieves imports for constants.
*/
private function getConstantImports(\ReflectionClassConstant $constant): array
{
$class = $constant->getDeclaringClass();
$classImports = $this->getImports($class);
if (!method_exists($class, 'getTraits')) {
return $classImports;
}

$traitImports = array();

foreach ($class->getTraits() as $trait) {
if ($trait->hasConstant($constant->getName())) {
$traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait));
}
}

return array_merge($classImports, $traitImports);
}

/**
* Collects parsing metadata for a given class or function.
*
Expand Down
37 changes: 36 additions & 1 deletion lib/Doctrine/Common/Annotations/CachedReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* A cache aware annotation reader.
*/
final class CachedReader implements Reader
final class CachedReader implements Reader, ReaderWithConstantsAnnotations
{
/** @var Reader */
private $delegate;
Expand Down Expand Up @@ -113,6 +113,41 @@ public function getPropertyAnnotation(ReflectionProperty $property, $annotationN
return null;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotations(\ReflectionClassConstant $constant): array
{
$class = $constant->getDeclaringClass();
$cacheKey = $class->getName().'::'.$constant->getName();

if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}

$annots = $this->fetchFromCache($cacheKey, $class);
if ($annots === false) {
$annots = $this->delegate->getConstantAnnotations($constant);
$this->saveToCache($cacheKey, $annots);
}

return $this->loadedAnnotations[$cacheKey] = $annots;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotation(\ReflectionClassConstant $constant, $annotationName)
{
foreach ($this->getConstantAnnotations($constant) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}

return null;
}

/**
* {@inheritDoc}
*/
Expand Down
53 changes: 52 additions & 1 deletion lib/Doctrine/Common/Annotations/FileCacheReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
* in version 2.0.0 of doctrine/annotations. Please use the
* {@see \Doctrine\Common\Annotations\CachedReader} instead.
*/
class FileCacheReader implements Reader
class FileCacheReader implements Reader, ReaderWithConstantsAnnotations
{
/** @var Reader */
private $reader;
Expand Down Expand Up @@ -166,6 +166,41 @@ public function getPropertyAnnotations(ReflectionProperty $property)
return $this->loadedAnnotations[$key] = include $path;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotations(\ReflectionClassConstant $constant): array
{
$class = $constant->getDeclaringClass();
if ( ! isset($this->classNameHashes[$class->name])) {
$this->classNameHashes[$class->name] = sha1($class->name);
}
$key = $this->classNameHashes[$class->name].'::'.$constant->getName();

if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}

$path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
if (!is_file($path)) {
$annot = $this->reader->getConstantAnnotations($constant);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}

if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
@unlink($path);

$annot = $this->reader->getConstantAnnotations($constant);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}

return $this->loadedAnnotations[$key] = include $path;
}
jkufner marked this conversation as resolved.
Show resolved Hide resolved

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -303,6 +338,22 @@ public function getPropertyAnnotation(ReflectionProperty $property, $annotationN
return null;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotation(\ReflectionClassConstant $constant, $annotationName)
{
$annotations = $this->getConstantAnnotations($constant);

foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}

return null;
}

/**
* Clears loaded annotations.
*
Expand Down
23 changes: 22 additions & 1 deletion lib/Doctrine/Common/Annotations/IndexedReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/**
* Allows the reader to be used in-place of Doctrine's reader.
*/
class IndexedReader implements Reader
class IndexedReader implements Reader, ReaderWithConstantsAnnotations
{
/** @var Reader */
private $delegate;
Expand Down Expand Up @@ -85,6 +85,27 @@ public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
return $this->delegate->getPropertyAnnotation($property, $annotation);
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotations(\ReflectionClassConstant $constant): array
{
$annotations = [];
foreach ($this->delegate->getConstantAnnotations($constant) as $annot) {
$annotations[get_class($annot)] = $annot;
}

return $annotations;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotation(\ReflectionClassConstant $constant, $annotation)
{
return $this->delegate->getConstantAnnotation($constant, $annotation);
}

/**
* Proxies all methods to the delegate.
*
Expand Down
49 changes: 49 additions & 0 deletions lib/Doctrine/Common/Annotations/ReaderWithConstantsAnnotations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\Common\Annotations;

/**
* Interface for annotations readers with constant annotations support.
*
* @author Josef Kufner <[email protected]>
* @deprecated This interface will be merged into Reader interface and removed in version 2.0.
*/
interface ReaderWithConstantsAnnotations extends Reader
{
/**
* Gets the annotations applied to a constant.
*
* @param \ReflectionClassConstant $constant The ReflectionClassConstant of the constant
* from which the annotations should be read.
*
* @return object[] An array of Annotations.
*/
function getConstantAnnotations(\ReflectionClassConstant $constant): array;

/**
* Gets a constant annotation.
*
* @param \ReflectionClassConstant $constant The ReflectionClassConstant to read the annotations from.
* @param string $annotationName The name of the annotation.
*
* @return object|null The Annotation or NULL, if the requested annotation does not exist.
*/
function getConstantAnnotation(\ReflectionClassConstant $constant, $annotationName);
}
27 changes: 26 additions & 1 deletion lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* @deprecated Deprecated in favour of using AnnotationReader
*/
class SimpleAnnotationReader implements Reader
class SimpleAnnotationReader implements Reader, ReaderWithConstantsAnnotations
{
/** @var DocParser */
private $parser;
Expand Down Expand Up @@ -70,6 +70,17 @@ public function getPropertyAnnotations(ReflectionProperty $property)
);
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotations(\ReflectionClassConstant $constant): array
{
return $this->parser->parse(
$constant->getDocComment(),
'constant '.$constant->getDeclaringClass()->name.'::'.$constant->getName()
);
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -111,4 +122,18 @@ public function getPropertyAnnotation(ReflectionProperty $property, $annotationN

return null;
}

/**
* {@inheritDoc}
*/
public function getConstantAnnotation(\ReflectionClassConstant $constant, $annotationName)
{
foreach ($this->getConstantAnnotations($constant) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public function testAnnotations(): void
);
self::assertEquals('hello', $annot->dummyValue);

$constant = $class->getReflectionConstant('SOME_CONSTANT');
$constAnnots = $reader->getConstantAnnotations($constant);
self::assertCount(1, $constAnnots);
self::assertInstanceOf($annotName, $annot = $reader->getConstantAnnotation($constant, $annotName));
self::assertEquals('constantHello', $annot->dummyValue);

$field1Prop = $class->getProperty('field1');
$propAnnots = $reader->getPropertyAnnotations($field1Prop);
self::assertCount(1, $propAnnots);
Expand Down
Loading