Showing preview only (439K chars total). Download the full file or copy to clipboard to get everything.
Repository: doctrine/annotations
Branch: 2.0.x
Commit: 17815fb6b2f4
Files: 163
Total size: 392.5 KB
Directory structure:
gitextract_dxqf29h2/
├── .doctrine-project.json
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── coding-standards.yml
│ ├── composer-lint.yml
│ ├── continuous-integration.yml
│ ├── documentation.yml
│ ├── release-on-milestone-closed.yml
│ └── static-analysis.yml
├── .gitignore
├── LICENSE
├── README.md
├── UPGRADE.md
├── composer.json
├── docs/
│ ├── composer.json
│ └── en/
│ ├── annotations.rst
│ ├── custom.rst
│ ├── index.rst
│ └── sidebar.rst
├── lib/
│ └── Doctrine/
│ └── Common/
│ └── Annotations/
│ ├── Annotation/
│ │ ├── Attribute.php
│ │ ├── Attributes.php
│ │ ├── Enum.php
│ │ ├── IgnoreAnnotation.php
│ │ ├── NamedArgumentConstructor.php
│ │ ├── Required.php
│ │ └── Target.php
│ ├── Annotation.php
│ ├── AnnotationException.php
│ ├── AnnotationReader.php
│ ├── AnnotationRegistry.php
│ ├── DocLexer.php
│ ├── DocParser.php
│ ├── ImplicitlyIgnoredAnnotationNames.php
│ ├── IndexedReader.php
│ ├── PhpParser.php
│ ├── PsrCachedReader.php
│ ├── Reader.php
│ └── TokenParser.php
├── phpbench.json.dist
├── phpcs.xml.dist
├── phpstan.neon
├── phpunit.xml.dist
├── psalm.xml
└── tests/
└── Doctrine/
├── Performance/
│ └── Common/
│ ├── Annotations/
│ │ ├── CachedReadPerformanceWithInMemoryBench.php
│ │ ├── DocLexerPerformanceBench.php
│ │ ├── DocParserPerformanceBench.php
│ │ ├── MethodInitializer.php
│ │ ├── PhpParserPerformanceWithShortCutBench.php
│ │ ├── PhpParserPerformanceWithoutShortCutBench.php
│ │ └── ReadPerformanceBench.php
│ └── bootstrap.php
└── Tests/
├── Common/
│ └── Annotations/
│ ├── AbstractReaderTest.php
│ ├── Annotation/
│ │ └── TargetTest.php
│ ├── AnnotationReaderTest.php
│ ├── AnnotationRegistryTest.php
│ ├── AnnotationTest.php
│ ├── DocLexerTest.php
│ ├── DocParserTest.php
│ ├── DummyClass.php
│ ├── Fixtures/
│ │ ├── AbstractController.php
│ │ ├── Annotation/
│ │ │ ├── AnnotWithDefaultValue.php
│ │ │ ├── Autoload.php
│ │ │ ├── CanBeAutoLoaded.php
│ │ │ ├── LoadedUsingRegisterFile.php
│ │ │ ├── Param.php
│ │ │ ├── Route.php
│ │ │ ├── Secure.php
│ │ │ ├── ShouldNeverBeLoaded.php
│ │ │ ├── SingleUseAnnotation.php
│ │ │ ├── Template.php
│ │ │ └── Version.php
│ │ ├── AnnotationEnum.php
│ │ ├── AnnotationEnumInvalid.php
│ │ ├── AnnotationEnumLiteral.php
│ │ ├── AnnotationEnumLiteralInvalid.php
│ │ ├── AnnotationTargetAll.php
│ │ ├── AnnotationTargetAnnotation.php
│ │ ├── AnnotationTargetClass.php
│ │ ├── AnnotationTargetMethod.php
│ │ ├── AnnotationTargetPropertyMethod.php
│ │ ├── AnnotationWithAttributes.php
│ │ ├── AnnotationWithConstants.php
│ │ ├── AnnotationWithEnumProperty.php
│ │ ├── AnnotationWithRequiredAttributes.php
│ │ ├── AnnotationWithRequiredAttributesWithoutConstructor.php
│ │ ├── AnnotationWithTargetSyntaxError.php
│ │ ├── AnnotationWithVarType.php
│ │ ├── Api.php
│ │ ├── ClassDDC1660.php
│ │ ├── ClassNoNamespaceNoComment.php
│ │ ├── ClassOverwritesTrait.php
│ │ ├── ClassThatUsesTraitThatUsesAnotherTrait.php
│ │ ├── ClassThatUsesTraitThatUsesAnotherTraitWithMethods.php
│ │ ├── ClassUsesTrait.php
│ │ ├── ClassWithAnnotationConstantReferenceWithDashes.php
│ │ ├── ClassWithAnnotationEnum.php
│ │ ├── ClassWithAnnotationWithSelfConstantReference.php
│ │ ├── ClassWithAnnotationWithTargetSyntaxError.php
│ │ ├── ClassWithAnnotationWithVarType.php
│ │ ├── ClassWithAtInDescriptionAndAnnotation.php
│ │ ├── ClassWithClassAnnotationOnly.php
│ │ ├── ClassWithClosure.php
│ │ ├── ClassWithConstants.php
│ │ ├── ClassWithEnumAnnotations.php
│ │ ├── ClassWithFullPathUseStatement.php
│ │ ├── ClassWithFullyQualifiedUseStatements.php
│ │ ├── ClassWithIgnoreAnnotation.php
│ │ ├── ClassWithImportedIgnoredAnnotation.php
│ │ ├── ClassWithInvalidAnnotationContainingDashes.php
│ │ ├── ClassWithInvalidAnnotationTargetAtClass.php
│ │ ├── ClassWithInvalidAnnotationTargetAtMethod.php
│ │ ├── ClassWithInvalidAnnotationTargetAtProperty.php
│ │ ├── ClassWithNotRegisteredAnnotationUsed.php
│ │ ├── ClassWithPHPCodeSnifferAnnotation.php
│ │ ├── ClassWithPHPStanGenericsAnnotations.php
│ │ ├── ClassWithPhpCsSuppressAnnotation.php
│ │ ├── ClassWithRequire.php
│ │ ├── ClassWithValidAnnotationTarget.php
│ │ ├── Controller.php
│ │ ├── ControllerWithParentClass.php
│ │ ├── ControllerWithTrait.php
│ │ ├── DifferentNamespacesPerFileWithClassAsFirst.php
│ │ ├── DifferentNamespacesPerFileWithClassAsLast.php
│ │ ├── EmptyInterface.php
│ │ ├── EqualNamespacesPerFileWithClassAsFirst.php
│ │ ├── EqualNamespacesPerFileWithClassAsLast.php
│ │ ├── GlobalNamespacesPerFileWithClassAsFirst.php
│ │ ├── GlobalNamespacesPerFileWithClassAsLast.php
│ │ ├── GroupUseStatement.php
│ │ ├── HereForTesting.php
│ │ ├── IgnoreAnnotationClass.php
│ │ ├── IgnoredNamespaces/
│ │ │ ├── AnnotatedAtClassLevel.php
│ │ │ ├── AnnotatedAtMethodLevel.php
│ │ │ ├── AnnotatedAtPropertyLevel.php
│ │ │ └── AnnotatedWithAlias.php
│ │ ├── InterfaceThatExtendsAnInterface.php
│ │ ├── InterfaceWithConstants.php
│ │ ├── InvalidAnnotationUsageButIgnoredClass.php
│ │ ├── InvalidAnnotationUsageClass.php
│ │ ├── MultipleClassesInFile.php
│ │ ├── MultipleImportsInUseStatement.php
│ │ ├── NamespaceAndClassCommentedOut.php
│ │ ├── NamespaceWithClosureDeclaration.php
│ │ ├── NamespacedSingleClassLOC1000.php
│ │ ├── NoAnnotation.php
│ │ ├── NonNamespacedClass.php
│ │ ├── SingleClassLOC1000.php
│ │ ├── Suit.php
│ │ ├── TraitWithAnnotatedMethod.php
│ │ ├── Traits/
│ │ │ ├── EmptyTrait.php
│ │ │ ├── SecretRouteTrait.php
│ │ │ ├── TraitThatUsesAnotherTrait.php
│ │ │ └── TraitWithSelfConstantReferenceTrait.php
│ │ └── functions.php
│ ├── PhpParserTest.php
│ ├── PsrCachedReaderTest.php
│ ├── ReservedKeywordsClasses.php
│ ├── Ticket/
│ │ ├── DCOM141Test.php
│ │ ├── DCOM55Test.php
│ │ ├── DCOM58Entity.php
│ │ └── DCOM58Test.php
│ └── TopLevelAnnotation.php
├── DoctrineTestCase.php
└── TestInit.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .doctrine-project.json
================================================
{
"active": false,
"name": "Annotations",
"slug": "annotations",
"docsSlug": "doctrine-annotations",
"versions": [
{
"name": "2.0",
"branchName": "2.0.x",
"aliases": [
"current",
"stable"
],
"current": true,
"maintained": true
},
{
"name": "1.14",
"branchName": "1.14.x",
"maintained": false
},
{
"name": "1.13",
"branchName": "1.13.x",
"slug": "1.13",
"maintained": false
},
{
"name": "1.12",
"branchName": "1.12.x",
"slug": "1.12",
"maintained": false
},
{
"name": "1.11",
"branchName": "1.11.x",
"slug": "1.11",
"maintained": false
},
{
"name": "1.10",
"branchName": "1.10.x",
"slug": "1.10",
"maintained": false
},
{
"name": "1.9",
"branchName": "1.9.x",
"slug": "1.9",
"maintained": false
},
{
"name": "1.8",
"branchName": "1.8",
"slug": "1.8",
"maintained": false
},
{
"name": "1.7",
"branchName": "1.7",
"slug": "1.7",
"maintained": false
},
{
"name": "1.6",
"branchName": "1.6",
"slug": "1.6",
"maintained": false
}
]
}
================================================
FILE: .gitattributes
================================================
/.* export-ignore
/tests export-ignore
/phpbench.json.dist export-ignore
/phpcs.xml.dist export-ignore
/phpstan.neon export-ignore
/phpunit.xml.dist export-ignore
/psalm.xml export-ignore
================================================
FILE: .github/workflows/coding-standards.yml
================================================
name: "Coding Standards"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
coding-standards:
name: "Coding Standards"
uses: "doctrine/.github/.github/workflows/coding-standards.yml@13.1.0"
================================================
FILE: .github/workflows/composer-lint.yml
================================================
name: "Composer Lint"
on:
pull_request:
branches:
- "*.x"
paths:
- "composer.json"
push:
branches:
- "*.x"
paths:
- "composer.json"
jobs:
composer-lint:
name: "Composer Lint"
uses: "doctrine/.github/.github/workflows/composer-lint.yml@13.1.0"
================================================
FILE: .github/workflows/continuous-integration.yml
================================================
name: "Continuous Integration"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
env:
fail-fast: true
jobs:
phpunit:
name: "PHPUnit"
uses: "doctrine/.github/.github/workflows/continuous-integration.yml@13.1.0"
with:
php-versions: '["7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4", "8.5"]'
secrets:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"
================================================
FILE: .github/workflows/documentation.yml
================================================
name: "Documentation"
on:
pull_request:
branches:
- "*.x"
paths:
- ".github/workflows/documentation.yml"
- "docs/**"
push:
branches:
- "*.x"
paths:
- ".github/workflows/documentation.yml"
- "docs/**"
jobs:
documentation:
name: "Documentation"
uses: "doctrine/.github/.github/workflows/documentation.yml@13.1.0"
================================================
FILE: .github/workflows/release-on-milestone-closed.yml
================================================
name: "Automatic Releases"
on:
milestone:
types:
- "closed"
jobs:
release:
name: "Git tag, release & create merge-up PR"
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@13.1.0"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
ORGANIZATION_ADMIN_TOKEN: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}
================================================
FILE: .github/workflows/static-analysis.yml
================================================
name: "Static Analysis"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
phpstan:
name: "Static Analysis"
uses: "doctrine/.github/.github/workflows/phpstan.yml@13.1.0"
psalm:
name: "Psalm (PHP: 8.2)"
runs-on: "ubuntu-22.04"
steps:
- name: "Checkout code"
uses: "actions/checkout@v6"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.2"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)"
================================================
FILE: .gitignore
================================================
/vendor/
/composer.lock
/composer.phar
/phpbench.json
/phpunit.xml
/.phpcs-cache
/.phpunit.result.cache
================================================
FILE: LICENSE
================================================
Copyright (c) 2006-2013 Doctrine Project
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
⚠️ PHP 8 introduced
[attributes](https://www.php.net/manual/en/language.attributes.overview.php),
which are a native replacement for annotations. As such, this library is
considered feature complete, and should receive exclusively bugfixes and
security fixes.
We do not recommend using this library in new projects and encourage authors
of downstream libraries to offer support for attributes as an alternative to
Doctrine Annotations.
Have a look at [our blog](https://www.doctrine-project.org/2022/11/04/annotations-to-attributes.html)
to learn more.
# Doctrine Annotations
[](https://github.com/doctrine/persistence/actions)
[](https://www.versioneye.com/package/php--doctrine--annotations)
[](https://www.versioneye.com/php/doctrine:annotations/references)
[](https://packagist.org/packages/doctrine/annotations)
[](https://packagist.org/packages/doctrine/annotations)
Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)).
## Documentation
See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/stable/index.html).
## Contributing
When making a pull request, make sure your changes follow the
[Coding Standard Guidelines](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/current/reference/index.html#introduction).
================================================
FILE: UPGRADE.md
================================================
# Upgrade from 1.0.x to 2.0.x
- The `NamedArgumentConstructorAnnotation` has been removed. Use the `@NamedArgumentConstructor`
annotation instead.
- `SimpleAnnotationReader` has been removed.
- `DocLexer::peek()` and `DocLexer::glimpse` now return
`Doctrine\Common\Lexer\Token` objects. When using `doctrine/lexer` 2, these
implement `ArrayAccess` as a way for you to still be able to treat them as
arrays in some ways.
- `CachedReader` and `FileCacheReader` have been removed use `PsrCachedReader` instead.
- `AnnotationRegistry` methods related to registering annotations instead of
using autoloading have been removed.
- Parameter type declarations have been added to all methods of all classes. If
you have classes inheriting from classes inside this package, you should add
parameter and return type declarations.
- Support for PHP < 7.2 has been removed
- `PhpParser::parseClass()` has been removed. Use
`PhpParser::parseUseStatements()` instead.
================================================
FILE: composer.json
================================================
{
"name": "doctrine/annotations",
"description": "Docblock Annotations Parser",
"license": "MIT",
"type": "library",
"abandoned": true,
"keywords": [
"annotations",
"docblock",
"parser"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
"require": {
"php": "^7.2 || ^8.0",
"ext-tokenizer": "*",
"doctrine/lexer": "^2 || ^3",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/coding-standard": "^11.1 || ^14",
"phpstan/phpstan": "^1.11 || ^2.1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"symfony/cache": "^5.4 || ^6.4 || ^7.4 || ^8",
"vimeo/psalm": "^4.30 || ^5.14"
},
"suggest": {
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
},
"autoload": {
"psr-4": {
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
}
},
"autoload-dev": {
"psr-4": {
"Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations",
"Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations"
},
"files": [
"tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php",
"tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php"
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"sort-packages": true
}
}
================================================
FILE: docs/composer.json
================================================
{
"require": {
"doctrine/docs-builder": "^1.0"
}
}
================================================
FILE: docs/en/annotations.rst
================================================
Handling Annotations
====================
There are several different approaches to handling annotations in PHP.
Doctrine Annotations maps docblock annotations to PHP classes. Because
not all docblock annotations are used for metadata purposes a filter is
applied to ignore or skip classes that are not Doctrine annotations.
Take a look at the following code snippet:
.. code-block:: php
namespace MyProject\Entities;
use Doctrine\ORM\Mapping AS ORM;
use Symfony\Component\Validator\Constraints AS Assert;
/**
* @author Benjamin Eberlei
* @ORM\Entity
* @MyProject\Annotations\Foobarable
*/
class User
{
/**
* @ORM\Id @ORM\Column @ORM\GeneratedValue
* @dummy
* @var int
*/
private $id;
/**
* @ORM\Column(type="string")
* @Assert\NotEmpty
* @Assert\Email
* @var string
*/
private $email;
}
In this snippet you can see a variety of different docblock annotations:
- Documentation annotations such as ``@var`` and ``@author``. These
annotations are ignored and never considered for throwing an
exception due to wrongly used annotations.
- Annotations imported through use statements. The statement ``use
Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace
available as ``@ORM\ClassName``. Same goes for the import of
``@Assert``.
- The ``@dummy`` annotation. It is not a documentation annotation and
not ignored. For Doctrine Annotations it is not entirely clear how
to handle this annotation. Depending on the configuration an exception
(unknown annotation) will be thrown when parsing this annotation.
- The fully qualified annotation ``@MyProject\Annotations\Foobarable``.
This is transformed directly into the given class name.
How are these annotations loaded? From looking at the code you could
guess that the ORM Mapping, Assert Validation and the fully qualified
annotation can just be loaded using
the defined PHP autoloaders. This is not the case however: For error
handling reasons every check for class existence inside the
``AnnotationReader`` sets the second parameter $autoload
of ``class_exists($name, $autoload)`` to false. To work flawlessly the
``AnnotationReader`` requires silent autoloaders which many autoloaders are
not. Silent autoloading is NOT part of the `PSR-0 specification
<https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md>`_
for autoloading.
This is why Doctrine Annotations uses its own autoloading mechanism
through a global registry. If you are wondering about the annotation
registry being global, there is no other way to solve the architectural
problems of autoloading annotation classes in a straightforward fashion.
Additionally if you think about PHP autoloading then you recognize it is
a global as well.
To anticipate the configuration section, making the above PHP class work
with Doctrine Annotations requires this setup:
.. code-block:: php
use Doctrine\Common\Annotations\AnnotationReader;
$reader = new AnnotationReader();
AnnotationReader::addGlobalIgnoredName('dummy');
We create the actual ``AnnotationReader`` instance.
Note that we also add ``dummy`` to the global list of ignored
annotations for which we do not throw exceptions. Setting this is
necessary in our example case, otherwise ``@dummy`` would trigger an
exception to be thrown during the parsing of the docblock of
``MyProject\Entities\User#id``.
Setup and Configuration
-----------------------
To use the annotations library is simple, you just need to create a new
``AnnotationReader`` instance:
.. code-block:: php
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
This creates a simple annotation reader with no caching other than in
memory (in php arrays). Since parsing docblocks can be expensive you
should cache this process by using a caching reader.
To cache annotations, you can create a ``Doctrine\Common\Annotations\PsrCachedReader``.
This reader decorates the original reader and stores all annotations in a PSR-6
cache:
.. code-block:: php
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\PsrCachedReader;
$cache = ... // instantiate a PSR-6 Cache pool
$reader = new PsrCachedReader(
new AnnotationReader(),
$cache,
$debug = true
);
The ``debug`` flag is used here as well to invalidate the cache files
when the PHP class with annotations changed and should be used during
development.
.. warning ::
The ``AnnotationReader`` works and caches under the
assumption that all annotations of a doc-block are processed at
once. That means that annotation classes that do not exist and
aren't loaded and cannot be autoloaded (using the
AnnotationRegistry) would never be visible and not accessible if a
cache is used unless the cache is cleared and the annotations
requested again, this time with all annotations defined.
By default the annotation reader returns a list of annotations with
numeric indexes. If you want your annotations to be indexed by their
class name you can wrap the reader in an ``IndexedReader``:
.. code-block:: php
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\IndexedReader;
$reader = new IndexedReader(new AnnotationReader());
.. warning::
You should never wrap the indexed reader inside a cached reader,
only the other way around. This way you can re-use the cache with
indexed or numeric keys, otherwise your code may experience failures
due to caching in a numerical or indexed format.
Ignoring missing exceptions
~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default an exception is thrown from the ``AnnotationReader`` if an
annotation was found that:
- is not part of the list of ignored "documentation annotations";
- was not imported through a use statement;
- is not a fully qualified class that exists.
You can disable this behavior for specific names if your docblocks do
not follow strict requirements:
.. code-block:: php
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
AnnotationReader::addGlobalIgnoredName('foo');
PHP Imports
~~~~~~~~~~~
By default the annotation reader parses the use-statement of a php file
to gain access to the import rules and register them for the annotation
processing. Only if you are using PHP Imports can you validate the
correct usage of annotations and throw exceptions if you misspelled an
annotation. This mechanism is enabled by default.
To ease the upgrade path, we still allow you to disable this mechanism.
Note however that we will remove this in future versions:
.. code-block:: php
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$reader->setEnabledPhpImports(false);
================================================
FILE: docs/en/custom.rst
================================================
Custom Annotation Classes
=========================
If you want to define your own annotations, you just have to group them
in a namespace.
Annotation classes have to contain a class-level docblock with the text
``@Annotation``:
.. code-block:: php
namespace MyCompany\Annotations;
/** @Annotation */
class Bar
{
// some code
}
Inject annotation values
------------------------
The annotation parser checks if the annotation constructor has arguments,
if so then it will pass the value array, otherwise it will try to inject
values into public properties directly:
.. code-block:: php
namespace MyCompany\Annotations;
/**
* @Annotation
*
* Some Annotation using a constructor
*/
class Bar
{
private $foo;
public function __construct(array $values)
{
$this->foo = $values['foo'];
}
}
/**
* @Annotation
*
* Some Annotation without a constructor
*/
class Foo
{
public $bar;
}
Optional: Constructors with Named Parameters
--------------------------------------------
Starting with Annotations v1.11 a new annotation instantiation strategy
is available that aims at compatibility of Annotation classes with the PHP 8
attribute feature. You need to declare a constructor with regular parameter
names that match the named arguments in the annotation syntax.
To enable this feature, you can tag your annotation class with
``@NamedArgumentConstructor`` (available from v1.12) or implement the
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface
(available from v1.11 and deprecated as of v1.12).
When using the ``@NamedArgumentConstructor`` tag, the first argument of the
constructor is considered as the default one.
Usage with the ``@NamedArgumentConstructor`` tag
.. code-block:: php
namespace MyCompany\Annotations;
/**
* @Annotation
* @NamedArgumentConstructor
*/
class Bar implements NamedArgumentConstructorAnnotation
{
private $foo;
public function __construct(string $foo)
{
$this->foo = $foo;
}
}
/** Usable with @Bar(foo="baz") */
/** Usable with @Bar("baz") */
In combination with PHP 8's constructor property promotion feature
you can simplify this to:
.. code-block:: php
namespace MyCompany\Annotations;
/**
* @Annotation
* @NamedArgumentConstructor
*/
class Bar implements NamedArgumentConstructorAnnotation
{
public function __construct(private string $foo) {}
}
Usage with the
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation``
interface (v1.11, deprecated as of v1.12):
.. code-block:: php
namespace MyCompany\Annotations;
use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation;
/** @Annotation */
class Bar implements NamedArgumentConstructorAnnotation
{
private $foo;
public function __construct(private string $foo) {}
}
/** Usable with @Bar(foo="baz") */
Annotation Target
-----------------
``@Target`` indicates the kinds of class elements to which an annotation
type is applicable. Then you could define one or more targets:
- ``CLASS`` Allowed in class docblocks
- ``PROPERTY`` Allowed in property docblocks
- ``METHOD`` Allowed in the method docblocks
- ``FUNCTION`` Allowed in function docblocks
- ``ALL`` Allowed in class, property, method and function docblocks
- ``ANNOTATION`` Allowed inside other annotations
If the annotations is not allowed in the current context, an
``AnnotationException`` is thrown.
.. code-block:: php
namespace MyCompany\Annotations;
/**
* @Annotation
* @Target({"METHOD","PROPERTY"})
*/
class Bar
{
// some code
}
/**
* @Annotation
* @Target("CLASS")
*/
class Foo
{
// some code
}
Attribute types
---------------
The annotation parser checks the given parameters using the phpdoc
annotation ``@var``, The data type could be validated using the ``@var``
annotation on the annotation properties or using the ``@Attributes`` and
``@Attribute`` annotations.
If the data type does not match you get an ``AnnotationException``
.. code-block:: php
namespace MyCompany\Annotations;
/**
* @Annotation
* @Target({"METHOD","PROPERTY"})
*/
class Bar
{
/** @var mixed */
public $mixed;
/** @var boolean */
public $boolean;
/** @var bool */
public $bool;
/** @var float */
public $float;
/** @var string */
public $string;
/** @var integer */
public $integer;
/** @var array */
public $array;
/** @var SomeAnnotationClass */
public $annotation;
/** @var array<integer> */
public $arrayOfIntegers;
/** @var array<SomeAnnotationClass> */
public $arrayOfAnnotations;
}
/**
* @Annotation
* @Target({"METHOD","PROPERTY"})
* @Attributes({
* @Attribute("stringProperty", type = "string"),
* @Attribute("annotProperty", type = "SomeAnnotationClass"),
* })
*/
class Foo
{
public function __construct(array $values)
{
$this->stringProperty = $values['stringProperty'];
$this->annotProperty = $values['annotProperty'];
}
// some code
}
Annotation Required
-------------------
``@Required`` indicates that the field must be specified when the
annotation is used. If it is not used you get an ``AnnotationException``
stating that this value can not be null.
Declaring a required field:
.. code-block:: php
/**
* @Annotation
* @Target("ALL")
*/
class Foo
{
/** @Required */
public $requiredField;
}
Usage:
.. code-block:: php
/** @Foo(requiredField="value") */
public $direction; // Valid
/** @Foo */
public $direction; // Required field missing, throws an AnnotationException
Enumerated values
-----------------
- An annotation property marked with ``@Enum`` is a field that accepts a
fixed set of scalar values.
- You should use ``@Enum`` fields any time you need to represent fixed
values.
- The annotation parser checks the given value and throws an
``AnnotationException`` if the value does not match.
Declaring an enumerated property:
.. code-block:: php
/**
* @Annotation
* @Target("ALL")
*/
class Direction
{
/**
* @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
*/
public $value;
}
Annotation usage:
.. code-block:: php
/** @Direction("NORTH") */
public $direction; // Valid value
/** @Direction("NORTHEAST") */
public $direction; // Invalid value, throws an AnnotationException
Constants
---------
The use of constants and class constants is available on the annotations
parser.
The following usages are allowed:
.. code-block:: php
namespace MyCompany\Entity;
use MyCompany\Annotations\Foo;
use MyCompany\Annotations\Bar;
use MyCompany\Entity\SomeClass;
/**
* @Foo(PHP_EOL)
* @Bar(Bar::FOO)
* @Foo({SomeClass::FOO, SomeClass::BAR})
* @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE})
*/
class User
{
}
Be careful with constants and the cache !
.. note::
The cached reader will not re-evaluate each time an annotation is
loaded from cache. When a constant is changed the cache must be
cleaned.
Usage
-----
Using the library API is simple. Using the annotations described in the
previous section, you can now annotate other classes with your
annotations:
.. code-block:: php
namespace MyCompany\Entity;
use MyCompany\Annotations\Foo;
use MyCompany\Annotations\Bar;
/**
* @Foo(bar="foo")
* @Bar(foo="bar")
*/
class User
{
}
Now we can write a script to get the annotations above:
.. code-block:: php
$reflClass = new ReflectionClass('MyCompany\Entity\User');
$classAnnotations = $reader->getClassAnnotations($reflClass);
foreach ($classAnnotations AS $annot) {
if ($annot instanceof \MyCompany\Annotations\Foo) {
echo $annot->bar; // prints "foo";
} else if ($annot instanceof \MyCompany\Annotations\Bar) {
echo $annot->foo; // prints "bar";
}
}
You have a complete API for retrieving annotation class instances from a
class, property or method docblock:
Reader API
~~~~~~~~~~
Access all annotations of a class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getClassAnnotations(\ReflectionClass $class);
Access one annotation of a class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getClassAnnotation(\ReflectionClass $class, $annotationName);
Access all annotations of a method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getMethodAnnotations(\ReflectionMethod $method);
Access one annotation of a method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
Access all annotations of a property
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getPropertyAnnotations(\ReflectionProperty $property);
Access one annotation of a property
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
Access all annotations of a function
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getFunctionAnnotations(\ReflectionFunction $property);
Access one annotation of a function
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName);
================================================
FILE: docs/en/index.rst
================================================
Getting Started
===============
Deprecation notice
------------------
PHP 8 introduced `attributes
<https://www.php.net/manual/en/language.attributes.overview.php>`_,
which are a native replacement for annotations. As such, this library is
considered feature complete, and should receive exclusively bugfixes and
security fixes.
We do not recommend using this library in new projects and encourage authors
of downstream libraries to offer support for attributes as an alternative to
Doctrine Annotations.
Have a look at `our blog <https://www.doctrine-project.org/2022/11/04/annotations-to-attributes.html>`_
to learn more.
Introduction
------------
Doctrine Annotations allows to implement custom annotation
functionality for PHP classes and functions.
.. code-block:: php
class Foo
{
/**
* @MyAnnotation(myProperty="value")
*/
private $bar;
}
Annotations aren't implemented in PHP itself which is why this component
offers a way to use the PHP doc-blocks as a place for the well known
annotation syntax using the ``@`` char.
Annotations in Doctrine are used for the ORM configuration to build the
class mapping, but it can be used in other projects for other purposes
too.
Installation
------------
You can install the Annotation component with composer:
.. code-block::
$ composer require doctrine/annotations
Create an annotation class
--------------------------
An annotation class is a representation of the later used annotation
configuration in classes. The annotation class of the previous example
looks like this:
.. code-block:: php
/**
* @Annotation
*/
final class MyAnnotation
{
public $myProperty;
}
The annotation class is declared as an annotation by ``@Annotation``.
:doc:`Read more about custom annotations. <custom>`
Reading annotations
-------------------
The access to the annotations happens by reflection of the class or function
containing them. There are multiple reader-classes implementing the
``Doctrine\Common\Annotations\Reader`` interface, that can access the
annotations of a class. A common one is
``Doctrine\Common\Annotations\AnnotationReader``:
.. code-block:: php
use Doctrine\Common\Annotations\AnnotationReader;
$reflectionClass = new ReflectionClass(Foo::class);
$property = $reflectionClass->getProperty('bar');
$reader = new AnnotationReader();
$myAnnotation = $reader->getPropertyAnnotation(
$property,
MyAnnotation::class
);
echo $myAnnotation->myProperty; // result: "value"
A reader has multiple methods to access the annotations of a class or
function.
:doc:`Read more about handling annotations. <annotations>`
IDE Support
^^^^^^^^^^^
Some IDEs already provide support for annotations:
- Eclipse via the `Symfony2 Plugin <https://github.com/pulse00/Symfony-2-Eclipse-Plugin>`_
- PhpStorm via the `PHP Annotations Plugin <https://plugins.jetbrains.com/plugin/7320-php-annotations>`_ or the `Symfony Plugin <https://plugins.jetbrains.com/plugin/7219-symfony-support>`_
================================================
FILE: docs/en/sidebar.rst
================================================
:orphan:
.. toctree::
:depth: 3
index
annotations
custom
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/Attribute.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the attribute type during the parsing process.
*
* @Annotation
*/
final class Attribute
{
/** @var string */
public $name;
/** @var string */
public $type;
/** @var bool */
public $required = false;
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/Attributes.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the types of all declared attributes during the parsing process.
*
* @Annotation
*/
final class Attributes
{
/** @var array<Attribute> */
public $value;
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/Enum.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
use InvalidArgumentException;
use function get_class;
use function gettype;
use function in_array;
use function is_object;
use function is_scalar;
use function sprintf;
/**
* Annotation that can be used to signal to the parser
* to check the available values during the parsing process.
*
* @Annotation
* @Attributes({
* @Attribute("value", required = true, type = "array"),
* @Attribute("literal", required = false, type = "array")
* })
*/
final class Enum
{
/** @phpstan-var list<scalar> */
public $value;
/**
* Literal target declaration.
*
* @var mixed[]
*/
public $literal;
/**
* @phpstan-param array{literal?: mixed[], value: list<scalar>} $values
*
* @throws InvalidArgumentException
*/
public function __construct(array $values)
{
if (! isset($values['literal'])) {
$values['literal'] = [];
}
foreach ($values['value'] as $var) {
if (! is_scalar($var)) {
throw new InvalidArgumentException(sprintf(
'@Enum supports only scalar values "%s" given.',
is_object($var) ? get_class($var) : gettype($var)
));
}
}
foreach ($values['literal'] as $key => $var) {
if (! in_array($key, $values['value'])) {
throw new InvalidArgumentException(sprintf(
'Undefined enumerator value "%s" for literal "%s".',
$key,
$var
));
}
}
$this->value = $values['value'];
$this->literal = $values['literal'];
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
use RuntimeException;
use function is_array;
use function is_string;
use function json_encode;
use function sprintf;
/**
* Annotation that can be used to signal to the parser to ignore specific
* annotations during the parsing process.
*
* @Annotation
*/
final class IgnoreAnnotation
{
/** @phpstan-var list<string> */
public $names;
/**
* @phpstan-param array{value: string|list<string>} $values
*
* @throws RuntimeException
*/
public function __construct(array $values)
{
if (is_string($values['value'])) {
$values['value'] = [$values['value']];
}
if (! is_array($values['value'])) {
throw new RuntimeException(sprintf(
'@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.',
json_encode($values['value'])
));
}
$this->names = $values['value'];
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that indicates that the annotated class should be constructed with a named argument call.
*
* @Annotation
* @Target("CLASS")
*/
final class NamedArgumentConstructor
{
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/Required.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check if that attribute is required during the parsing process.
*
* @Annotation
*/
final class Required
{
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation/Target.php
================================================
<?php
namespace Doctrine\Common\Annotations\Annotation;
use InvalidArgumentException;
use function array_keys;
use function get_class;
use function gettype;
use function implode;
use function is_array;
use function is_object;
use function is_string;
use function sprintf;
/**
* Annotation that can be used to signal to the parser
* to check the annotation target during the parsing process.
*
* @Annotation
*/
final class Target
{
public const TARGET_CLASS = 1;
public const TARGET_METHOD = 2;
public const TARGET_PROPERTY = 4;
public const TARGET_ANNOTATION = 8;
public const TARGET_FUNCTION = 16;
public const TARGET_ALL = 31;
/** @var array<string, int> */
private static $map = [
'ALL' => self::TARGET_ALL,
'CLASS' => self::TARGET_CLASS,
'METHOD' => self::TARGET_METHOD,
'PROPERTY' => self::TARGET_PROPERTY,
'FUNCTION' => self::TARGET_FUNCTION,
'ANNOTATION' => self::TARGET_ANNOTATION,
];
/** @phpstan-var list<string> */
public $value;
/**
* Targets as bitmask.
*
* @var int
*/
public $targets;
/**
* Literal target declaration.
*
* @var string
*/
public $literal;
/**
* @phpstan-param array{value?: string|list<string>} $values
*
* @throws InvalidArgumentException
*/
public function __construct(array $values)
{
if (! isset($values['value'])) {
$values['value'] = null;
}
if (is_string($values['value'])) {
$values['value'] = [$values['value']];
}
if (! is_array($values['value'])) {
throw new InvalidArgumentException(
sprintf(
'@Target expects either a string value, or an array of strings, "%s" given.',
is_object($values['value']) ? get_class($values['value']) : gettype($values['value'])
)
);
}
$bitmask = 0;
foreach ($values['value'] as $literal) {
if (! isset(self::$map[$literal])) {
throw new InvalidArgumentException(
sprintf(
'Invalid Target "%s". Available targets: [%s]',
$literal,
implode(', ', array_keys(self::$map))
)
);
}
$bitmask |= self::$map[$literal];
}
$this->targets = $bitmask;
$this->value = $values['value'];
$this->literal = implode(', ', $this->value);
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/Annotation.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use BadMethodCallException;
use function sprintf;
/**
* Annotations class.
*/
class Annotation
{
/**
* Value property. Common among all derived classes.
*
* @var mixed
*/
public $value;
/** @param array<string, mixed> $data Key-value for properties to be defined in this class. */
final public function __construct(array $data)
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
/**
* Error handler for unknown property accessor in Annotation class.
*
* @throws BadMethodCallException
*/
public function __get(string $name)
{
throw new BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class)
);
}
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param mixed $value Property value.
*
* @throws BadMethodCallException
*/
public function __set(string $name, $value)
{
throw new BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class)
);
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/AnnotationException.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use Exception;
use Throwable;
use function get_class;
use function gettype;
use function implode;
use function is_object;
use function sprintf;
/**
* Description of AnnotationException
*/
class AnnotationException extends Exception
{
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @return AnnotationException
*/
public static function syntaxError(string $message)
{
return new self('[Syntax Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @return AnnotationException
*/
public static function semanticalError(string $message)
{
return new self('[Semantical Error] ' . $message);
}
/**
* Creates a new AnnotationException describing an error which occurred during
* the creation of the annotation.
*
* @return AnnotationException
*/
public static function creationError(string $message, ?Throwable $previous = null)
{
return new self('[Creation Error] ' . $message, 0, $previous);
}
/**
* Creates a new AnnotationException describing a type error.
*
* @return AnnotationException
*/
public static function typeError(string $message)
{
return new self('[Type Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a constant semantical error.
*
* @return AnnotationException
*/
public static function semanticalErrorConstants(string $identifier, ?string $context = null)
{
return self::semanticalError(sprintf(
"Couldn't find constant %s%s.",
$identifier,
$context ? ', ' . $context : ''
));
}
/**
* Creates a new AnnotationException describing an type error of an attribute.
*
* @param mixed $actual
*
* @return AnnotationException
*/
public static function attributeTypeError(
string $attributeName,
string $annotationName,
string $context,
string $expected,
$actual
) {
return self::typeError(sprintf(
'Attribute "%s" of @%s declared on %s expects %s, but got %s.',
$attributeName,
$annotationName,
$context,
$expected,
is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual)
));
}
/**
* Creates a new AnnotationException describing an required error of an attribute.
*
* @return AnnotationException
*/
public static function requiredError(
string $attributeName,
string $annotationName,
string $context,
string $expected
) {
return self::typeError(sprintf(
'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.',
$attributeName,
$annotationName,
$context,
$expected
));
}
/**
* Creates a new AnnotationException describing a invalid enummerator.
*
* @param mixed $given
* @phpstan-param list<string> $available
*
* @return AnnotationException
*/
public static function enumeratorError(
string $attributeName,
string $annotationName,
string $context,
array $available,
$given
) {
return new self(sprintf(
'[Enum Error] Attribute "%s" of @%s declared on %s accepts only [%s], but got %s.',
$attributeName,
$annotationName,
$context,
implode(', ', $available),
is_object($given) ? get_class($given) : $given
));
}
/** @return AnnotationException */
public static function optimizerPlusSaveComments()
{
return new self(
'You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.'
);
}
/** @return AnnotationException */
public static function optimizerPlusLoadComments()
{
return new self(
'You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1.'
);
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/AnnotationReader.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\Annotation\Target;
use ReflectionClass;
use ReflectionFunction;
use ReflectionMethod;
use ReflectionProperty;
use function array_merge;
use function class_exists;
use function extension_loaded;
use function filter_var;
use function ini_get;
use const FILTER_VALIDATE_BOOLEAN;
/**
* A reader for docblock annotations.
*/
class AnnotationReader implements Reader
{
/**
* Global map for imports.
*
* @var array<string, class-string>
*/
private static $globalImports = [
'ignoreannotation' => Annotation\IgnoreAnnotation::class,
];
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names are case sensitive.
*
* @var array<string, true>
*/
private static $globalIgnoredNames = ImplicitlyIgnoredAnnotationNames::LIST;
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names are case sensitive.
*
* @var array<string, true>
*/
private static $globalIgnoredNamespaces = [];
/**
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
*/
public static function addGlobalIgnoredName(string $name)
{
self::$globalIgnoredNames[$name] = true;
}
/**
* Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
*/
public static function addGlobalIgnoredNamespace(string $namespace)
{
self::$globalIgnoredNamespaces[$namespace] = true;
}
/**
* Annotations parser.
*
* @var DocParser
*/
private $parser;
/**
* Annotations parser used to collect parsing metadata.
*
* @var DocParser
*/
private $preParser;
/**
* PHP parser used to collect imports.
*
* @var PhpParser
*/
private $phpParser;
/**
* In-memory cache mechanism to store imported annotations per class.
*
* @psalm-var array<'class'|'function', array<string, array<string, class-string>>>
*/
private $imports = [];
/**
* In-memory cache mechanism to store ignored annotations per class.
*
* @psalm-var array<'class'|'function', array<string, array<string, true>>>
*/
private $ignoredAnnotationNames = [];
/**
* Initializes a new AnnotationReader.
*
* @throws AnnotationException
*/
public function __construct(?DocParser $parser = null)
{
if (
extension_loaded('Zend Optimizer+') &&
(filter_var(ini_get('zend_optimizerplus.save_comments'), FILTER_VALIDATE_BOOLEAN) === false ||
filter_var(ini_get('opcache.save_comments'), FILTER_VALIDATE_BOOLEAN) === false)
) {
throw AnnotationException::optimizerPlusSaveComments();
}
if (
extension_loaded('Zend OPcache') &&
filter_var(ini_get('opcache.save_comments'), FILTER_VALIDATE_BOOLEAN) === false
) {
throw AnnotationException::optimizerPlusSaveComments();
}
// Make sure that the IgnoreAnnotation annotation is loaded
class_exists(IgnoreAnnotation::class);
$this->parser = $parser ?: new DocParser();
$this->preParser = new DocParser();
$this->preParser->setImports(self::$globalImports);
$this->preParser->setIgnoreNotImportedAnnotations(true);
$this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames);
$this->phpParser = new PhpParser();
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$context = 'property ' . $class->getName() . '::$' . $property->getName();
$this->parser->setTarget(Target::TARGET_PROPERTY);
$this->parser->setImports($this->getPropertyImports($property));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($property->getDocComment(), $context);
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
$annotations = $this->getPropertyAnnotations($property);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
$this->parser->setTarget(Target::TARGET_METHOD);
$this->parser->setImports($this->getMethodImports($method));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($method->getDocComment(), $context);
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
$annotations = $this->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets the annotations applied to a function.
*
* @phpstan-return list<object> An array of Annotations.
*/
public function getFunctionAnnotations(ReflectionFunction $function): array
{
$context = 'function ' . $function->getName();
$this->parser->setTarget(Target::TARGET_FUNCTION);
$this->parser->setImports($this->getImports($function));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($function->getDocComment(), $context);
}
/**
* Gets a function annotation.
*
* @return object|null The Annotation or NULL, if the requested annotation does not exist.
*/
public function getFunctionAnnotation(ReflectionFunction $function, string $annotationName)
{
$annotations = $this->getFunctionAnnotations($function);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Returns the ignored annotations for the given class or function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @return array<string, true>
*/
private function getIgnoredAnnotationNames($reflection): array
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
if (isset($this->ignoredAnnotationNames[$type][$name])) {
return $this->ignoredAnnotationNames[$type][$name];
}
$this->collectParsingMetadata($reflection);
return $this->ignoredAnnotationNames[$type][$name];
}
/**
* Retrieves imports for a class or a function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @return array<string, class-string>
*/
private function getImports($reflection): array
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
if (isset($this->imports[$type][$name])) {
return $this->imports[$type][$name];
}
$this->collectParsingMetadata($reflection);
return $this->imports[$type][$name];
}
/**
* Retrieves imports for methods.
*
* @return array<string, class-string>
*/
private function getMethodImports(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$classImports = $this->getImports($class);
$traitImports = [];
foreach ($class->getTraits() as $trait) {
if (
! $trait->hasMethod($method->getName())
|| $trait->getFileName() !== $method->getFileName()
) {
continue;
}
$traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
}
return array_merge($classImports, $traitImports);
}
/**
* Retrieves imports for properties.
*
* @return array<string, class-string>
*/
private function getPropertyImports(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$classImports = $this->getImports($class);
$traitImports = [];
foreach ($class->getTraits() as $trait) {
if (! $trait->hasProperty($property->getName())) {
continue;
}
$traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
}
return array_merge($classImports, $traitImports);
}
/**
* Collects parsing metadata for a given class or function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*/
private function collectParsingMetadata($reflection): void
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
$ignoredAnnotationNames = self::$globalIgnoredNames;
$annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name);
foreach ($annotations as $annotation) {
if (! ($annotation instanceof IgnoreAnnotation)) {
continue;
}
foreach ($annotation->names as $annot) {
$ignoredAnnotationNames[$annot] = true;
}
}
$this->imports[$type][$name] = array_merge(
self::$globalImports,
$this->phpParser->parseUseStatements($reflection),
[
'__NAMESPACE__' => $reflection->getNamespaceName(),
'self' => $name,
]
);
$this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames;
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/AnnotationRegistry.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use function array_key_exists;
use function class_exists;
final class AnnotationRegistry
{
/**
* An array of classes which cannot be found
*
* @var null[] indexed by class name
*/
private static $failedToAutoload = [];
public static function reset(): void
{
self::$failedToAutoload = [];
}
/**
* Autoloads an annotation class silently.
*/
public static function loadAnnotationClass(string $class): bool
{
if (class_exists($class, false)) {
return true;
}
if (array_key_exists($class, self::$failedToAutoload)) {
return false;
}
if (class_exists($class)) {
return true;
}
self::$failedToAutoload[$class] = null;
return false;
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/DocLexer.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Lexer\AbstractLexer;
use function ctype_alpha;
use function is_numeric;
use function str_replace;
use function stripos;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
/**
* Simple lexer for docblock annotations.
*
* @template-extends AbstractLexer<DocLexer::T_*, string>
*/
final class DocLexer extends AbstractLexer
{
public const T_NONE = 1;
public const T_INTEGER = 2;
public const T_STRING = 3;
public const T_FLOAT = 4;
// All tokens that are also identifiers should be >= 100
public const T_IDENTIFIER = 100;
public const T_AT = 101;
public const T_CLOSE_CURLY_BRACES = 102;
public const T_CLOSE_PARENTHESIS = 103;
public const T_COMMA = 104;
public const T_EQUALS = 105;
public const T_FALSE = 106;
public const T_NAMESPACE_SEPARATOR = 107;
public const T_OPEN_CURLY_BRACES = 108;
public const T_OPEN_PARENTHESIS = 109;
public const T_TRUE = 110;
public const T_NULL = 111;
public const T_COLON = 112;
public const T_MINUS = 113;
/** @var array<string, self::T*> */
protected $noCase = [
'@' => self::T_AT,
',' => self::T_COMMA,
'(' => self::T_OPEN_PARENTHESIS,
')' => self::T_CLOSE_PARENTHESIS,
'{' => self::T_OPEN_CURLY_BRACES,
'}' => self::T_CLOSE_CURLY_BRACES,
'=' => self::T_EQUALS,
':' => self::T_COLON,
'-' => self::T_MINUS,
'\\' => self::T_NAMESPACE_SEPARATOR,
];
/** @var array<string, self::T*> */
protected $withCase = [
'true' => self::T_TRUE,
'false' => self::T_FALSE,
'null' => self::T_NULL,
];
/**
* Whether the next token starts immediately, or if there were
* non-captured symbols before that
*/
public function nextTokenIsAdjacent(): bool
{
return $this->token === null
|| ($this->lookahead !== null
&& ($this->lookahead->position - $this->token->position) === strlen($this->token->value));
}
/**
* {@inheritDoc}
*/
protected function getCatchablePatterns()
{
return [
'[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*',
'(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?',
'"(?:""|[^"])*+"',
];
}
/**
* {@inheritDoc}
*/
protected function getNonCatchablePatterns()
{
return ['\s+', '\*+', '(.)'];
}
/**
* {@inheritDoc}
*/
protected function getType(&$value)
{
$type = self::T_NONE;
if ($value[0] === '"') {
$value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));
return self::T_STRING;
}
if (isset($this->noCase[$value])) {
return $this->noCase[$value];
}
if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) {
return self::T_IDENTIFIER;
}
$lowerValue = strtolower($value);
if (isset($this->withCase[$lowerValue])) {
return $this->withCase[$lowerValue];
}
// Checking numeric value
if (is_numeric($value)) {
return strpos($value, '.') !== false || stripos($value, 'e') !== false
? self::T_FLOAT : self::T_INTEGER;
}
return $type;
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/DocParser.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
use Doctrine\Common\Annotations\Annotation\Enum;
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
use Doctrine\Common\Annotations\Annotation\Target;
use ReflectionClass;
use ReflectionException;
use ReflectionProperty;
use RuntimeException;
use stdClass;
use Throwable;
use function array_keys;
use function array_map;
use function array_pop;
use function array_values;
use function class_exists;
use function constant;
use function count;
use function defined;
use function explode;
use function gettype;
use function implode;
use function in_array;
use function interface_exists;
use function is_array;
use function is_object;
use function json_encode;
use function ltrim;
use function preg_match;
use function reset;
use function rtrim;
use function sprintf;
use function stripos;
use function strlen;
use function strpos;
use function strrpos;
use function strtolower;
use function substr;
use function trim;
use const PHP_VERSION_ID;
/**
* A parser for docblock annotations.
*
* It is strongly discouraged to change the default annotation parsing process.
*
* @psalm-type Arguments = array{positional_arguments?: array<int, mixed>, named_arguments?: array<string, mixed>}
*/
final class DocParser
{
/**
* An array of all valid tokens for a class name.
*
* @phpstan-var list<int>
*/
private static $classIdentifiers = [
DocLexer::T_IDENTIFIER,
DocLexer::T_TRUE,
DocLexer::T_FALSE,
DocLexer::T_NULL,
];
/**
* The lexer.
*
* @var DocLexer
*/
private $lexer;
/**
* Current target context.
*
* @var int
*/
private $target;
/**
* Doc parser used to collect annotation target.
*
* @var DocParser
*/
private static $metadataParser;
/**
* Flag to control if the current annotation is nested or not.
*
* @var bool
*/
private $isNestedAnnotation = false;
/**
* Hashmap containing all use-statements that are to be used when parsing
* the given doc block.
*
* @var array<string, class-string>
*/
private $imports = [];
/**
* This hashmap is used internally to cache results of class_exists()
* look-ups.
*
* @var array<class-string, bool>
*/
private $classExists = [];
/**
* Whether annotations that have not been imported should be ignored.
*
* @var bool
*/
private $ignoreNotImportedAnnotations = false;
/**
* An array of default namespaces if operating in simple mode.
*
* @var string[]
*/
private $namespaces = [];
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names must be the raw names as used in the class, not the fully qualified
*
* @var bool[] indexed by annotation name
*/
private $ignoredAnnotationNames = [];
/**
* A list with annotations in namespaced format
* that are not causing exceptions when not resolved to an annotation class.
*
* @var bool[] indexed by namespace name
*/
private $ignoredAnnotationNamespaces = [];
/** @var string */
private $context = '';
/**
* Hash-map for caching annotation metadata.
*
* @var array<class-string, mixed[]>
*/
private static $annotationMetadata = [
Annotation\Target::class => [
'is_annotation' => true,
'has_constructor' => true,
'has_named_argument_constructor' => false,
'properties' => [],
'targets_literal' => 'ANNOTATION_CLASS',
'targets' => Target::TARGET_CLASS,
'default_property' => 'value',
'attribute_types' => [
'value' => [
'required' => false,
'type' => 'array',
'array_type' => 'string',
'value' => 'array<string>',
],
],
],
Annotation\Attribute::class => [
'is_annotation' => true,
'has_constructor' => false,
'has_named_argument_constructor' => false,
'targets_literal' => 'ANNOTATION_ANNOTATION',
'targets' => Target::TARGET_ANNOTATION,
'default_property' => 'name',
'properties' => [
'name' => 'name',
'type' => 'type',
'required' => 'required',
],
'attribute_types' => [
'value' => [
'required' => true,
'type' => 'string',
'value' => 'string',
],
'type' => [
'required' => true,
'type' => 'string',
'value' => 'string',
],
'required' => [
'required' => false,
'type' => 'boolean',
'value' => 'boolean',
],
],
],
Annotation\Attributes::class => [
'is_annotation' => true,
'has_constructor' => false,
'has_named_argument_constructor' => false,
'targets_literal' => 'ANNOTATION_CLASS',
'targets' => Target::TARGET_CLASS,
'default_property' => 'value',
'properties' => ['value' => 'value'],
'attribute_types' => [
'value' => [
'type' => 'array',
'required' => true,
'array_type' => Annotation\Attribute::class,
'value' => 'array<' . Annotation\Attribute::class . '>',
],
],
],
Annotation\Enum::class => [
'is_annotation' => true,
'has_constructor' => true,
'has_named_argument_constructor' => false,
'targets_literal' => 'ANNOTATION_PROPERTY',
'targets' => Target::TARGET_PROPERTY,
'default_property' => 'value',
'properties' => ['value' => 'value'],
'attribute_types' => [
'value' => [
'type' => 'array',
'required' => true,
],
'literal' => [
'type' => 'array',
'required' => false,
],
],
],
Annotation\NamedArgumentConstructor::class => [
'is_annotation' => true,
'has_constructor' => false,
'has_named_argument_constructor' => false,
'targets_literal' => 'ANNOTATION_CLASS',
'targets' => Target::TARGET_CLASS,
'default_property' => null,
'properties' => [],
'attribute_types' => [],
],
];
/**
* Hash-map for handle types declaration.
*
* @var array<string, string>
*/
private static $typeMap = [
'float' => 'double',
'bool' => 'boolean',
// allow uppercase Boolean in honor of George Boole
'Boolean' => 'boolean',
'int' => 'integer',
];
/**
* Constructs a new DocParser.
*/
public function __construct()
{
$this->lexer = new DocLexer();
}
/**
* Sets the annotation names that are ignored during the parsing process.
*
* The names are supposed to be the raw names as used in the class, not the
* fully qualified class names.
*
* @param bool[] $names indexed by annotation name
*
* @return void
*/
public function setIgnoredAnnotationNames(array $names)
{
$this->ignoredAnnotationNames = $names;
}
/**
* Sets the annotation namespaces that are ignored during the parsing process.
*
* @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name
*
* @return void
*/
public function setIgnoredAnnotationNamespaces(array $ignoredAnnotationNamespaces)
{
$this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces;
}
/**
* Sets ignore on not-imported annotations.
*
* @return void
*/
public function setIgnoreNotImportedAnnotations(bool $bool)
{
$this->ignoreNotImportedAnnotations = $bool;
}
/**
* Sets the default namespaces.
*
* @return void
*
* @throws RuntimeException
*/
public function addNamespace(string $namespace)
{
if ($this->imports) {
throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
}
$this->namespaces[] = $namespace;
}
/**
* Sets the imports.
*
* @param array<string, class-string> $imports
*
* @return void
*
* @throws RuntimeException
*/
public function setImports(array $imports)
{
if ($this->namespaces) {
throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
}
$this->imports = $imports;
}
/**
* Sets current target context as bitmask.
*
* @return void
*/
public function setTarget(int $target)
{
$this->target = $target;
}
/**
* Parses the given docblock string for annotations.
*
* @phpstan-return list<object> Array of annotations. If no annotations are found, an empty array is returned.
*
* @throws AnnotationException
* @throws ReflectionException
*/
public function parse(string $input, string $context = '')
{
$pos = $this->findInitialTokenPosition($input);
if ($pos === null) {
return [];
}
$this->context = $context;
$this->lexer->setInput(trim(substr($input, $pos), '* /'));
$this->lexer->moveNext();
return $this->Annotations();
}
/**
* Finds the first valid annotation
*/
private function findInitialTokenPosition(string $input): ?int
{
$pos = 0;
// search for first valid annotation
while (($pos = strpos($input, '@', $pos)) !== false) {
$preceding = substr($input, $pos - 1, 1);
// if the @ is preceded by a space, a tab or * it is valid
if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") {
return $pos;
}
$pos++;
}
return null;
}
/**
* Attempts to match the given token with the current lookahead token.
* If they match, updates the lookahead token; otherwise raises a syntax error.
*
* @param int $token Type of token.
*
* @return bool True if tokens match; false otherwise.
*
* @throws AnnotationException
*/
private function match(int $token): bool
{
if (! $this->lexer->isNextToken($token)) {
throw $this->syntaxError($this->lexer->getLiteral($token));
}
return $this->lexer->moveNext();
}
/**
* Attempts to match the current lookahead token with any of the given tokens.
*
* If any of them matches, this method updates the lookahead token; otherwise
* a syntax error is raised.
*
* @phpstan-param list<mixed[]> $tokens
*
* @throws AnnotationException
*/
private function matchAny(array $tokens): bool
{
if (! $this->lexer->isNextTokenAny($tokens)) {
throw $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens)));
}
return $this->lexer->moveNext();
}
/**
* Generates a new syntax error.
*
* @param string $expected Expected string.
* @param mixed[]|null $token Optional token.
*/
private function syntaxError(string $expected, ?array $token = null): AnnotationException
{
if ($token === null) {
$token = $this->lexer->lookahead;
}
$message = sprintf('Expected %s, got ', $expected);
$message .= $this->lexer->lookahead === null
? 'end of string'
: sprintf("'%s' at position %s", $token->value, $token->position);
if (strlen($this->context)) {
$message .= ' in ' . $this->context;
}
$message .= '.';
return AnnotationException::syntaxError($message);
}
/**
* Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism
* but uses the {@link AnnotationRegistry} to load classes.
*
* @param class-string $fqcn
*/
private function classExists(string $fqcn): bool
{
if (isset($this->classExists[$fqcn])) {
return $this->classExists[$fqcn];
}
// first check if the class already exists, maybe loaded through another AnnotationReader
if (class_exists($fqcn, false)) {
return $this->classExists[$fqcn] = true;
}
// final check, does this class exist?
return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn);
}
/**
* Collects parsing metadata for a given annotation class
*
* @param class-string $name The annotation name
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function collectAnnotationMetadata(string $name): void
{
if (self::$metadataParser === null) {
self::$metadataParser = new self();
self::$metadataParser->setIgnoreNotImportedAnnotations(true);
self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames);
self::$metadataParser->setImports([
'enum' => Enum::class,
'target' => Target::class,
'attribute' => Attribute::class,
'attributes' => Attributes::class,
'namedargumentconstructor' => NamedArgumentConstructor::class,
]);
// Make sure that annotations from metadata are loaded
class_exists(Enum::class);
class_exists(Target::class);
class_exists(Attribute::class);
class_exists(Attributes::class);
class_exists(NamedArgumentConstructor::class);
}
$class = new ReflectionClass($name);
$docComment = $class->getDocComment();
// Sets default values for annotation metadata
$constructor = $class->getConstructor();
$metadata = [
'default_property' => null,
'has_constructor' => $constructor !== null && $constructor->getNumberOfParameters() > 0,
'constructor_args' => [],
'properties' => [],
'property_types' => [],
'attribute_types' => [],
'targets_literal' => null,
'targets' => Target::TARGET_ALL,
'is_annotation' => strpos($docComment, '@Annotation') !== false,
];
$metadata['has_named_argument_constructor'] = false;
// verify that the class is really meant to be an annotation
if ($metadata['is_annotation']) {
self::$metadataParser->setTarget(Target::TARGET_CLASS);
foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) {
if ($annotation instanceof Target) {
$metadata['targets'] = $annotation->targets;
$metadata['targets_literal'] = $annotation->literal;
continue;
}
if ($annotation instanceof NamedArgumentConstructor) {
$metadata['has_named_argument_constructor'] = $metadata['has_constructor'];
if ($metadata['has_named_argument_constructor']) {
// choose the first argument as the default property
$metadata['default_property'] = $constructor->getParameters()[0]->getName();
}
}
if (! ($annotation instanceof Attributes)) {
continue;
}
foreach ($annotation->value as $attribute) {
$this->collectAttributeTypeMetadata($metadata, $attribute);
}
}
// if not has a constructor will inject values into public properties
if ($metadata['has_constructor'] === false) {
// collect all public properties
foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
$metadata['properties'][$property->name] = $property->name;
$propertyComment = $property->getDocComment();
if ($propertyComment === false) {
continue;
}
$attribute = new Attribute();
$attribute->required = (strpos($propertyComment, '@Required') !== false);
$attribute->name = $property->name;
$attribute->type = (strpos($propertyComment, '@var') !== false &&
preg_match('/@var\s+([^\s]+)/', $propertyComment, $matches))
? $matches[1]
: 'mixed';
$this->collectAttributeTypeMetadata($metadata, $attribute);
// checks if the property has @Enum
if (strpos($propertyComment, '@Enum') === false) {
continue;
}
$context = 'property ' . $class->name . '::$' . $property->name;
self::$metadataParser->setTarget(Target::TARGET_PROPERTY);
foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) {
if (! $annotation instanceof Enum) {
continue;
}
$metadata['enum'][$property->name]['value'] = $annotation->value;
$metadata['enum'][$property->name]['literal'] = (! empty($annotation->literal))
? $annotation->literal
: $annotation->value;
}
}
// choose the first property as default property
$metadata['default_property'] = reset($metadata['properties']);
} elseif ($metadata['has_named_argument_constructor']) {
foreach ($constructor->getParameters() as $parameter) {
if ($parameter->isVariadic()) {
break;
}
$metadata['constructor_args'][$parameter->getName()] = [
'position' => $parameter->getPosition(),
'default' => $parameter->isOptional() ? $parameter->getDefaultValue() : null,
];
}
}
}
self::$annotationMetadata[$name] = $metadata;
}
/**
* Collects parsing metadata for a given attribute.
*
* @param mixed[] $metadata
*/
private function collectAttributeTypeMetadata(array &$metadata, Attribute $attribute): void
{
// handle internal type declaration
$type = self::$typeMap[$attribute->type] ?? $attribute->type;
// handle the case if the property type is mixed
if ($type === 'mixed') {
return;
}
// Evaluate type
$pos = strpos($type, '<');
if ($pos !== false) {
// Checks if the property has array<type>
$arrayType = substr($type, $pos + 1, -1);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType;
} else {
// Checks if the property has type[]
$pos = strrpos($type, '[');
if ($pos !== false) {
$arrayType = substr($type, 0, $pos);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType;
}
}
$metadata['attribute_types'][$attribute->name]['type'] = $type;
$metadata['attribute_types'][$attribute->name]['value'] = $attribute->type;
$metadata['attribute_types'][$attribute->name]['required'] = $attribute->required;
}
/**
* Annotations ::= Annotation {[ "*" ]* [Annotation]}*
*
* @phpstan-return list<object>
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function Annotations(): array
{
$annotations = [];
while ($this->lexer->lookahead !== null) {
if ($this->lexer->lookahead->type !== DocLexer::T_AT) {
$this->lexer->moveNext();
continue;
}
// make sure the @ is preceded by non-catchable pattern
if (
$this->lexer->token !== null &&
$this->lexer->lookahead->position === $this->lexer->token->position + strlen(
$this->lexer->token->value
)
) {
$this->lexer->moveNext();
continue;
}
// make sure the @ is followed by either a namespace separator, or
// an identifier token
$peek = $this->lexer->glimpse();
if (
($peek === null)
|| ($peek->type !== DocLexer::T_NAMESPACE_SEPARATOR && ! in_array(
$peek->type,
self::$classIdentifiers,
true
))
|| $peek->position !== $this->lexer->lookahead->position + 1
) {
$this->lexer->moveNext();
continue;
}
$this->isNestedAnnotation = false;
$annot = $this->Annotation();
if ($annot === false) {
continue;
}
$annotations[] = $annot;
}
return $annotations;
}
/**
* Annotation ::= "@" AnnotationName MethodCall
* AnnotationName ::= QualifiedName | SimpleName
* QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
* NameSpacePart ::= identifier | null | false | true
* SimpleName ::= identifier | null | false | true
*
* @return object|false False if it is not a valid annotation.
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function Annotation()
{
$this->match(DocLexer::T_AT);
// check if we have an annotation
$name = $this->Identifier();
if (
$this->lexer->isNextToken(DocLexer::T_MINUS)
&& $this->lexer->nextTokenIsAdjacent()
) {
// Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded
return false;
}
// only process names which are not fully qualified, yet
// fully qualified names must start with a \
$originalName = $name;
if ($name[0] !== '\\') {
$pos = strpos($name, '\\');
$alias = ($pos === false) ? $name : substr($name, 0, $pos);
$found = false;
$loweredAlias = strtolower($alias);
if ($this->namespaces) {
foreach ($this->namespaces as $namespace) {
if ($this->classExists($namespace . '\\' . $name)) {
$name = $namespace . '\\' . $name;
$found = true;
break;
}
}
} elseif (isset($this->imports[$loweredAlias])) {
$namespace = ltrim($this->imports[$loweredAlias], '\\');
$name = ($pos !== false)
? $namespace . substr($name, $pos)
: $namespace;
$found = $this->classExists($name);
} elseif (
! isset($this->ignoredAnnotationNames[$name])
&& isset($this->imports['__NAMESPACE__'])
&& $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name)
) {
$name = $this->imports['__NAMESPACE__'] . '\\' . $name;
$found = true;
} elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) {
$found = true;
}
if (! $found) {
if ($this->isIgnoredAnnotation($name)) {
return false;
}
throw AnnotationException::semanticalError(sprintf(
<<<'EXCEPTION'
The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?
EXCEPTION
,
$name,
$this->context
));
}
}
$name = ltrim($name, '\\');
if (! $this->classExists($name)) {
throw AnnotationException::semanticalError(sprintf(
'The annotation "@%s" in %s does not exist, or could not be auto-loaded.',
$name,
$this->context
));
}
// at this point, $name contains the fully qualified class name of the
// annotation, and it is also guaranteed that this class exists, and
// that it is loaded
// collects the metadata annotation only if there is not yet
if (! isset(self::$annotationMetadata[$name])) {
$this->collectAnnotationMetadata($name);
}
// verify that the class is really meant to be an annotation and not just any ordinary class
if (self::$annotationMetadata[$name]['is_annotation'] === false) {
if ($this->isIgnoredAnnotation($originalName) || $this->isIgnoredAnnotation($name)) {
return false;
}
throw AnnotationException::semanticalError(sprintf(
<<<'EXCEPTION'
The class "%s" is not annotated with @Annotation.
Are you sure this class can be used as annotation?
If so, then you need to add @Annotation to the _class_ doc comment of "%s".
If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.
EXCEPTION
,
$name,
$name,
$originalName,
$this->context
));
}
//if target is nested annotation
$target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target;
// Next will be nested
$this->isNestedAnnotation = true;
//if annotation does not support current target
if ((self::$annotationMetadata[$name]['targets'] & $target) === 0 && $target) {
throw AnnotationException::semanticalError(
sprintf(
<<<'EXCEPTION'
Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.
EXCEPTION
,
$originalName,
$this->context,
self::$annotationMetadata[$name]['targets_literal']
)
);
}
$arguments = $this->MethodCall();
$values = $this->resolvePositionalValues($arguments, $name);
if (isset(self::$annotationMetadata[$name]['enum'])) {
// checks all declared attributes
foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) {
// checks if the attribute is a valid enumerator
if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) {
throw AnnotationException::enumeratorError(
$property,
$name,
$this->context,
$enum['literal'],
$values[$property]
);
}
}
}
// checks all declared attributes
foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) {
if (
$property === self::$annotationMetadata[$name]['default_property']
&& ! isset($values[$property]) && isset($values['value'])
) {
$property = 'value';
}
// handle a not given attribute or null value
if (! isset($values[$property])) {
if ($type['required']) {
throw AnnotationException::requiredError(
$property,
$originalName,
$this->context,
'a(n) ' . $type['value']
);
}
continue;
}
if ($type['type'] === 'array') {
// handle the case of a single value
if (! is_array($values[$property])) {
$values[$property] = [$values[$property]];
}
// checks if the attribute has array type declaration, such as "array<string>"
if (isset($type['array_type'])) {
foreach ($values[$property] as $item) {
if (gettype($item) !== $type['array_type'] && ! $item instanceof $type['array_type']) {
throw AnnotationException::attributeTypeError(
$property,
$originalName,
$this->context,
'either a(n) ' . $type['array_type'] . ', or an array of ' . $type['array_type'] . 's',
$item
);
}
}
}
} elseif (gettype($values[$property]) !== $type['type'] && ! $values[$property] instanceof $type['type']) {
throw AnnotationException::attributeTypeError(
$property,
$originalName,
$this->context,
'a(n) ' . $type['value'],
$values[$property]
);
}
}
if (self::$annotationMetadata[$name]['has_named_argument_constructor']) {
if (PHP_VERSION_ID >= 80000) {
foreach ($values as $property => $value) {
if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) {
throw AnnotationException::creationError(sprintf(
<<<'EXCEPTION'
The annotation @%s declared on %s does not have a property named "%s"
that can be set through its named arguments constructor.
Available named arguments: %s
EXCEPTION
,
$originalName,
$this->context,
$property,
implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args']))
));
}
}
return $this->instantiateAnnotiation($originalName, $this->context, $name, $values);
}
$positionalValues = [];
foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) {
$positionalValues[$parameter['position']] = $parameter['default'];
}
foreach ($values as $property => $value) {
if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) {
throw AnnotationException::creationError(sprintf(
<<<'EXCEPTION'
The annotation @%s declared on %s does not have a property named "%s"
that can be set through its named arguments constructor.
Available named arguments: %s
EXCEPTION
,
$originalName,
$this->context,
$property,
implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args']))
));
}
$positionalValues[self::$annotationMetadata[$name]['constructor_args'][$property]['position']] = $value;
}
return $this->instantiateAnnotiation($originalName, $this->context, $name, $positionalValues);
}
// check if the annotation expects values via the constructor,
// or directly injected into public properties
if (self::$annotationMetadata[$name]['has_constructor'] === true) {
return $this->instantiateAnnotiation($originalName, $this->context, $name, [$values]);
}
$instance = $this->instantiateAnnotiation($originalName, $this->context, $name, []);
foreach ($values as $property => $value) {
if (! isset(self::$annotationMetadata[$name]['properties'][$property])) {
if ($property !== 'value') {
throw AnnotationException::creationError(sprintf(
<<<'EXCEPTION'
The annotation @%s declared on %s does not have a property named "%s".
Available properties: %s
EXCEPTION
,
$originalName,
$this->context,
$property,
implode(', ', self::$annotationMetadata[$name]['properties'])
));
}
// handle the case if the property has no annotations
$property = self::$annotationMetadata[$name]['default_property'];
if (! $property) {
throw AnnotationException::creationError(sprintf(
'The annotation @%s declared on %s does not accept any values, but got %s.',
$originalName,
$this->context,
json_encode($values)
));
}
}
$instance->{$property} = $value;
}
return $instance;
}
/**
* MethodCall ::= ["(" [Values] ")"]
*
* @psalm-return Arguments
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function MethodCall(): array
{
$values = [];
if (! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) {
return $values;
}
$this->match(DocLexer::T_OPEN_PARENTHESIS);
if (! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
$values = $this->Values();
}
$this->match(DocLexer::T_CLOSE_PARENTHESIS);
return $values;
}
/**
* Values ::= Array | Value {"," Value}* [","]
*
* @psalm-return Arguments
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function Values(): array
{
$values = [$this->Value()];
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
$this->match(DocLexer::T_COMMA);
if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
break;
}
$token = $this->lexer->lookahead;
$value = $this->Value();
$values[] = $value;
}
$namedArguments = [];
$positionalArguments = [];
foreach ($values as $k => $value) {
if (is_object($value) && $value instanceof stdClass) {
$namedArguments[$value->name] = $value->value;
} else {
$positionalArguments[$k] = $value;
}
}
return ['named_arguments' => $namedArguments, 'positional_arguments' => $positionalArguments];
}
/**
* Constant ::= integer | string | float | boolean
*
* @return mixed
*
* @throws AnnotationException
*/
private function Constant()
{
$identifier = $this->Identifier();
if (! defined($identifier) && strpos($identifier, '::') !== false && $identifier[0] !== '\\') {
[$className, $const] = explode('::', $identifier);
$pos = strpos($className, '\\');
$alias = ($pos === false) ? $className : substr($className, 0, $pos);
$found = false;
$loweredAlias = strtolower($alias);
switch (true) {
case ! empty($this->namespaces):
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]):
$found = true;
$className = ($pos !== false)
? $this->imports[$loweredAlias] . substr($className, $pos)
: $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;
}
}
/**
* Checks if identifier ends with ::class and remove the leading backslash if it exists.
*/
if (
$this->identifierEndsWithClassConstant($identifier) &&
! $this->identifierStartsWithBackslash($identifier)
) {
return substr($identifier, 0, $this->getClassConstantPositionInIdentifier($identifier));
}
if ($this->identifierEndsWithClassConstant($identifier) && $this->identifierStartsWithBackslash($identifier)) {
return substr($identifier, 1, $this->getClassConstantPositionInIdentifier($identifier) - 1);
}
if (! defined($identifier)) {
throw AnnotationException::semanticalErrorConstants($identifier, $this->context);
}
return constant($identifier);
}
private function identifierStartsWithBackslash(string $identifier): bool
{
return $identifier[0] === '\\';
}
private function identifierEndsWithClassConstant(string $identifier): bool
{
return $this->getClassConstantPositionInIdentifier($identifier) === strlen($identifier) - strlen('::class');
}
/** @return int|false */
private function getClassConstantPositionInIdentifier(string $identifier)
{
return stripos($identifier, '::class');
}
/**
* Identifier ::= string
*
* @throws AnnotationException
*/
private function Identifier(): string
{
// check if we have an annotation
if (! $this->lexer->isNextTokenAny(self::$classIdentifiers)) {
throw $this->syntaxError('namespace separator or identifier');
}
$this->lexer->moveNext();
$className = $this->lexer->token->value;
while (
$this->lexer->lookahead !== null &&
$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
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function Value()
{
$peek = $this->lexer->glimpse();
if ($peek->type === DocLexer::T_EQUALS) {
return $this->FieldAssignment();
}
return $this->PlainValue();
}
/**
* PlainValue ::= integer | string | float | boolean | Array | Annotation
*
* @return mixed
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function PlainValue()
{
if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
return $this->Arrayx();
}
if ($this->lexer->isNextToken(DocLexer::T_AT)) {
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);
return $this->lexer->token->value;
case DocLexer::T_INTEGER:
$this->match(DocLexer::T_INTEGER);
return (int) $this->lexer->token->value;
case DocLexer::T_FLOAT:
$this->match(DocLexer::T_FLOAT);
return (float) $this->lexer->token->value;
case DocLexer::T_TRUE:
$this->match(DocLexer::T_TRUE);
return true;
case DocLexer::T_FALSE:
$this->match(DocLexer::T_FALSE);
return false;
case DocLexer::T_NULL:
$this->match(DocLexer::T_NULL);
return null;
default:
throw $this->syntaxError('PlainValue');
}
}
/**
* FieldAssignment ::= FieldName "=" PlainValue
* FieldName ::= identifier
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function FieldAssignment(): stdClass
{
$this->match(DocLexer::T_IDENTIFIER);
$fieldName = $this->lexer->token->value;
$this->match(DocLexer::T_EQUALS);
$item = new stdClass();
$item->name = $fieldName;
$item->value = $this->PlainValue();
return $item;
}
/**
* Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}"
*
* @return mixed[]
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function Arrayx(): array
{
$array = $values = [];
$this->match(DocLexer::T_OPEN_CURLY_BRACES);
// If the array is empty, stop parsing and return.
if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
$this->match(DocLexer::T_CLOSE_CURLY_BRACES);
return $array;
}
$values[] = $this->ArrayEntry();
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
$this->match(DocLexer::T_COMMA);
// optional trailing comma
if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
break;
}
$values[] = $this->ArrayEntry();
}
$this->match(DocLexer::T_CLOSE_CURLY_BRACES);
foreach ($values as $value) {
[$key, $val] = $value;
if ($key !== null) {
$array[$key] = $val;
} else {
$array[] = $val;
}
}
return $array;
}
/**
* ArrayEntry ::= Value | KeyValuePair
* KeyValuePair ::= Key ("=" | ":") PlainValue | Constant
* Key ::= string | integer | Constant
*
* @phpstan-return array{mixed, mixed}
*
* @throws AnnotationException
* @throws ReflectionException
*/
private function ArrayEntry(): array
{
$peek = $this->lexer->glimpse();
if (
$peek->type === DocLexer::T_EQUALS
|| $peek->type === DocLexer::T_COLON
) {
if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
$key = $this->Constant();
} else {
$this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]);
$key = $this->lexer->token->value;
}
$this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]);
return [$key, $this->PlainValue()];
}
return [null, $this->Value()];
}
/**
* Checks whether the given $name matches any ignored annotation name or namespace
*/
private function isIgnoredAnnotation(string $name): bool
{
if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
return true;
}
foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) {
$ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\';
if (stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace) === 0) {
return true;
}
}
return false;
}
/**
* Resolve positional arguments (without name) to named ones
*
* @psalm-param Arguments $arguments
*
* @return array<string,mixed>
*/
private function resolvePositionalValues(array $arguments, string $name): array
{
$positionalArguments = $arguments['positional_arguments'] ?? [];
$values = $arguments['named_arguments'] ?? [];
if (
self::$annotationMetadata[$name]['has_named_argument_constructor']
&& self::$annotationMetadata[$name]['default_property'] !== null
) {
// We must ensure that we don't have positional arguments after named ones
$positions = array_keys($positionalArguments);
$lastPosition = null;
foreach ($positions as $position) {
if (
($lastPosition === null && $position !== 0) ||
($lastPosition !== null && $position !== $lastPosition + 1)
) {
throw $this->syntaxError('Positional arguments after named arguments is not allowed');
}
$lastPosition = $position;
}
foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) {
$position = $parameter['position'];
if (isset($values[$property]) || ! isset($positionalArguments[$position])) {
continue;
}
$values[$property] = $positionalArguments[$position];
}
} else {
if (count($positionalArguments) > 0 && ! isset($values['value'])) {
if (count($positionalArguments) === 1) {
$value = array_pop($positionalArguments);
} else {
$value = array_values($positionalArguments);
}
$values['value'] = $value;
}
}
return $values;
}
/**
* Try to instantiate the annotation and catch and process any exceptions related to failure
*
* @param class-string $name
* @param array<string,mixed> $arguments
*
* @return object
*
* @throws AnnotationException
*/
private function instantiateAnnotiation(string $originalName, string $context, string $name, array $arguments)
{
try {
return new $name(...$arguments);
} catch (Throwable $exception) {
throw AnnotationException::creationError(
sprintf(
'An error occurred while instantiating the annotation @%s declared on %s: "%s".',
$originalName,
$context,
$exception->getMessage()
),
$exception
);
}
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Common\Annotations;
/**
* A list of annotations that are implicitly ignored during the parsing process.
*
* All names are case sensitive.
*/
final class ImplicitlyIgnoredAnnotationNames
{
private const Reserved = [
'Annotation' => true,
'Attribute' => true,
'Attributes' => true,
/* Can we enable this? 'Enum' => true, */
'Required' => true,
'Target' => true,
'NamedArgumentConstructor' => true,
];
private const WidelyUsedNonStandard = [
'fix' => true,
'fixme' => true,
'override' => true,
];
private const PhpDocumentor1 = [
'abstract' => true,
'access' => true,
'code' => true,
'deprec' => true,
'endcode' => true,
'exception' => true,
'final' => true,
'ingroup' => true,
'inheritdoc' => true,
'inheritDoc' => true,
'magic' => true,
'name' => true,
'private' => true,
'static' => true,
'staticvar' => true,
'staticVar' => true,
'toc' => true,
'tutorial' => true,
'throw' => true,
];
private const PhpDocumentor2 = [
'api' => true,
'author' => true,
'category' => true,
'copyright' => true,
'deprecated' => true,
'example' => true,
'filesource' => true,
'global' => true,
'ignore' => true,
/* Can we enable this? 'index' => true, */
'internal' => true,
'license' => true,
'link' => true,
'method' => true,
'package' => true,
'param' => true,
'property' => true,
'property-read' => true,
'property-write' => true,
'return' => true,
'see' => true,
'since' => true,
'source' => true,
'subpackage' => true,
'throws' => true,
'todo' => true,
'TODO' => true,
'usedby' => true,
'uses' => true,
'var' => true,
'version' => true,
];
private const PHPUnit = [
'author' => true,
'after' => true,
'afterClass' => true,
'backupGlobals' => true,
'backupStaticAttributes' => true,
'before' => true,
'beforeClass' => true,
'codeCoverageIgnore' => true,
'codeCoverageIgnoreStart' => true,
'codeCoverageIgnoreEnd' => true,
'covers' => true,
'coversDefaultClass' => true,
'coversNothing' => true,
'dataProvider' => true,
'depends' => true,
'doesNotPerformAssertions' => true,
'expectedException' => true,
'expectedExceptionCode' => true,
'expectedExceptionMessage' => true,
'expectedExceptionMessageRegExp' => true,
'group' => true,
'large' => true,
'medium' => true,
'preserveGlobalState' => true,
'requires' => true,
'runTestsInSeparateProcesses' => true,
'runInSeparateProcess' => true,
'small' => true,
'test' => true,
'testdox' => true,
'testWith' => true,
'ticket' => true,
'uses' => true,
];
private const PhpCheckStyle = ['SuppressWarnings' => true];
private const PhpStorm = ['noinspection' => true];
private const PEAR = ['package_version' => true];
private const PlainUML = [
'startuml' => true,
'enduml' => true,
];
private const Symfony = ['experimental' => true];
private const PhpCodeSniffer = [
'codingStandardsIgnoreStart' => true,
'codingStandardsIgnoreEnd' => true,
];
private const SlevomatCodingStandard = ['phpcsSuppress' => true];
private const Phan = ['suppress' => true];
private const Rector = ['noRector' => true];
private const StaticAnalysis = [
// PHPStan, Psalm
'extends' => true,
'implements' => true,
'readonly' => true,
'template' => true,
'use' => true,
// Psalm
'pure' => true,
'immutable' => true,
];
public const LIST = self::Reserved
+ self::WidelyUsedNonStandard
+ self::PhpDocumentor1
+ self::PhpDocumentor2
+ self::PHPUnit
+ self::PhpCheckStyle
+ self::PhpStorm
+ self::PEAR
+ self::PlainUML
+ self::Symfony
+ self::SlevomatCodingStandard
+ self::PhpCodeSniffer
+ self::Phan
+ self::Rector
+ self::StaticAnalysis;
private function __construct()
{
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/IndexedReader.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use function call_user_func_array;
use function get_class;
/**
* Allows the reader to be used in-place of Doctrine's reader.
*/
class IndexedReader implements Reader
{
/** @var Reader */
private $delegate;
public function __construct(Reader $reader)
{
$this->delegate = $reader;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$annotations = [];
foreach ($this->delegate->getClassAnnotations($class) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
return $this->delegate->getClassAnnotation($class, $annotationName);
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$annotations = [];
foreach ($this->delegate->getMethodAnnotations($method) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
return $this->delegate->getMethodAnnotation($method, $annotationName);
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$annotations = [];
foreach ($this->delegate->getPropertyAnnotations($property) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
return $this->delegate->getPropertyAnnotation($property, $annotationName);
}
/**
* Proxies all methods to the delegate.
*
* @param mixed[] $args
*
* @return mixed
*/
public function __call(string $method, array $args)
{
return call_user_func_array([$this->delegate, $method], $args);
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/PhpParser.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionFunction;
use SplFileObject;
use function is_file;
use function method_exists;
use function preg_quote;
use function preg_replace;
/**
* Parses a file for namespaces/use/class declarations.
*/
final class PhpParser
{
/**
* Parse a class or function for use statements.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @psalm-return array<string, string> a list with use statements in the form (Alias => FQN).
*/
public function parseUseStatements($reflection): array
{
if (method_exists($reflection, 'getUseStatements')) {
return $reflection->getUseStatements();
}
$filename = $reflection->getFileName();
if ($filename === false) {
return [];
}
$content = $this->getFileContent($filename, $reflection->getStartLine());
if ($content === null) {
return [];
}
$namespace = preg_quote($reflection->getNamespaceName());
$content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
$tokenizer = new TokenParser('<?php ' . $content);
return $tokenizer->parseUseStatements($reflection->getNamespaceName());
}
/**
* Gets the content of the file right up to the given line number.
*
* @param string $filename The name of the file to load.
* @param int $lineNumber The number of lines to read from file.
*
* @return string|null The content of the file or null if the file does not exist.
*/
private function getFileContent(string $filename, $lineNumber)
{
if (! is_file($filename)) {
return null;
}
$content = '';
$lineCnt = 0;
$file = new SplFileObject($filename);
while (! $file->eof()) {
if ($lineCnt++ === $lineNumber) {
break;
}
$content .= $file->fgets();
}
return $content;
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/PsrCachedReader.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use Psr\Cache\CacheItemPoolInterface;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use Reflector;
use function array_map;
use function array_merge;
use function assert;
use function filemtime;
use function is_file;
use function max;
use function rawurlencode;
use function time;
/**
* A cache aware annotation reader.
*/
final class PsrCachedReader implements Reader
{
/** @var Reader */
private $delegate;
/** @var CacheItemPoolInterface */
private $cache;
/** @var bool */
private $debug;
/** @var array<string, array<object>> */
private $loadedAnnotations = [];
/** @var int[] */
private $loadedFilemtimes = [];
public function __construct(Reader $reader, CacheItemPoolInterface $cache, bool $debug = false)
{
$this->delegate = $reader;
$this->cache = $cache;
$this->debug = (bool) $debug;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$cacheKey = $class->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getClassAnnotations', $class);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$cacheKey = $class->getName() . '$' . $property->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getPropertyAnnotations', $property);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$cacheKey = $class->getName() . '#' . $method->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getMethodAnnotations', $method);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
public function clearLoadedAnnotations(): void
{
$this->loadedAnnotations = [];
$this->loadedFilemtimes = [];
}
/** @return mixed[] */
private function fetchFromCache(
string $cacheKey,
ReflectionClass $class,
string $method,
Reflector $reflector
): array {
$cacheKey = rawurlencode($cacheKey);
$item = $this->cache->getItem($cacheKey);
if (($this->debug && ! $this->refresh($cacheKey, $class)) || ! $item->isHit()) {
$this->cache->save($item->set($this->delegate->{$method}($reflector)));
}
return $item->get();
}
/**
* Used in debug mode to check if the cache is fresh.
*
* @return bool Returns true if the cache was fresh, or false if the class
* being read was modified since writing to the cache.
*/
private function refresh(string $cacheKey, ReflectionClass $class): bool
{
$lastModification = $this->getLastModification($class);
if ($lastModification === 0) {
return true;
}
$item = $this->cache->getItem('[C]' . $cacheKey);
if ($item->isHit() && $item->get() >= $lastModification) {
return true;
}
$this->cache->save($item->set(time()));
return false;
}
/**
* Returns the time the class was last modified, testing traits and parents
*/
private function getLastModification(ReflectionClass $class): int
{
$filename = $class->getFileName();
if (isset($this->loadedFilemtimes[$filename])) {
return $this->loadedFilemtimes[$filename];
}
$parent = $class->getParentClass();
$lastModification = max(array_merge(
[$filename !== false && is_file($filename) ? filemtime($filename) : 0],
array_map(function (ReflectionClass $reflectionTrait): int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $class->getTraits()),
array_map(function (ReflectionClass $class): int {
return $this->getLastModification($class);
}, $class->getInterfaces()),
$parent ? [$this->getLastModification($parent)] : []
));
assert($lastModification !== false);
return $this->loadedFilemtimes[$filename] = $lastModification;
}
private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): int
{
$fileName = $reflectionTrait->getFileName();
if (isset($this->loadedFilemtimes[$fileName])) {
return $this->loadedFilemtimes[$fileName];
}
$lastModificationTime = max(array_merge(
[$fileName !== false && is_file($fileName) ? filemtime($fileName) : 0],
array_map(function (ReflectionClass $reflectionTrait): int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $reflectionTrait->getTraits())
));
assert($lastModificationTime !== false);
return $this->loadedFilemtimes[$fileName] = $lastModificationTime;
}
}
================================================
FILE: lib/Doctrine/Common/Annotations/Reader.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
/**
* Interface for annotation readers.
*/
interface Reader
{
/**
* Gets the annotations applied to a class.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getClassAnnotations(ReflectionClass $class);
/**
* Gets a class annotation.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName);
/**
* Gets the annotations applied to a method.
*
* @param ReflectionMethod $method The ReflectionMethod of the method from which
* the annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getMethodAnnotations(ReflectionMethod $method);
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method The ReflectionMethod to read the annotations from.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName);
/**
* Gets the annotations applied to a property.
*
* @param ReflectionProperty $property The ReflectionProperty of the property
* from which the annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getPropertyAnnotations(ReflectionProperty $property);
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property The ReflectionProperty to read the annotations from.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName);
}
================================================
FILE: lib/Doctrine/Common/Annotations/TokenParser.php
================================================
<?php
namespace Doctrine\Common\Annotations;
use function array_merge;
use function count;
use function explode;
use function strtolower;
use function token_get_all;
use const PHP_VERSION_ID;
use const T_AS;
use const T_COMMENT;
use const T_DOC_COMMENT;
use const T_NAME_FULLY_QUALIFIED;
use const T_NAME_QUALIFIED;
use const T_NAMESPACE;
use const T_NS_SEPARATOR;
use const T_STRING;
use const T_USE;
use const T_WHITESPACE;
/**
* Parses a file for namespaces/use/class declarations.
*/
class TokenParser
{
/**
* The token list.
*
* @phpstan-var list<mixed[]>
*/
private $tokens;
/**
* The number of tokens.
*
* @var int
*/
private $numTokens;
/**
* The current array pointer.
*
* @var int
*/
private $pointer = 0;
public function __construct(string $contents)
{
$this->tokens = token_get_all($contents);
// The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
// saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
// doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
// docblock. If the first thing in the file is a class without a doc block this would cause calls to
// getDocBlock() on said class to return our long lost doc_comment. Argh.
// To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
// it's harmless to us.
token_get_all("<?php\n/**\n *\n */");
$this->numTokens = count($this->tokens);
}
/**
* Gets the next non whitespace and non comment token.
*
* @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
* If FALSE then only whitespace and normal comments are skipped.
*
* @return mixed[]|string|null The token if exists, null otherwise.
*/
public function next(bool $docCommentIsComment = true)
{
for ($i = $this->pointer; $i < $this->numTokens; $i++) {
$this->pointer++;
if (
$this->tokens[$i][0] === T_WHITESPACE ||
$this->tokens[$i][0] === T_COMMENT ||
($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)
) {
continue;
}
return $this->tokens[$i];
}
return null;
}
/**
* Parses a single use statement.
*
* @return array<string, string> A list with all found class names for a use statement.
*/
public function parseUseStatement()
{
$groupRoot = '';
$class = '';
$alias = '';
$statements = [];
$explicitAlias = false;
while (($token = $this->next())) {
if (! $explicitAlias && $token[0] === T_STRING) {
$class .= $token[1];
$alias = $token[1];
} elseif ($explicitAlias && $token[0] === T_STRING) {
$alias = $token[1];
} elseif (
PHP_VERSION_ID >= 80000 &&
($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)
) {
$class .= $token[1];
$classSplit = explode('\\', $token[1]);
$alias = $classSplit[count($classSplit) - 1];
} elseif ($token[0] === T_NS_SEPARATOR) {
$class .= '\\';
$alias = '';
} elseif ($token[0] === T_AS) {
$explicitAlias = true;
$alias = '';
} elseif ($token === ',') {
$statements[strtolower($alias)] = $groupRoot . $class;
$class = '';
$alias = '';
$explicitAlias = false;
} elseif ($token === ';') {
$statements[strtolower($alias)] = $groupRoot . $class;
break;
} elseif ($token === '{') {
$groupRoot = $class;
$class = '';
} elseif ($token === '}') {
continue;
} else {
break;
}
}
return $statements;
}
/**
* Gets all use statements.
*
* @param string $namespaceName The namespace name of the reflected class.
*
* @return array<string, string> A list with all found use statements.
*/
public function parseUseStatements(string $namespaceName)
{
$statements = [];
while (($token = $this->next())) {
if ($token[0] === T_USE) {
$statements = array_merge($statements, $this->parseUseStatement());
continue;
}
if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) {
continue;
}
// Get fresh array for new namespace. This is to prevent the parser to collect the use statements
// for a previous namespace with the same name. This is the case if a namespace is defined twice
// or if a namespace with the same name is commented out.
$statements = [];
}
return $statements;
}
/**
* Gets the namespace.
*
* @return string The found namespace.
*/
public function parseNamespace()
{
$name = '';
while (
($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || (
PHP_VERSION_ID >= 80000 &&
($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)
))
) {
$name .= $token[1];
}
return $name;
}
/**
* Gets the class name.
*
* @return string The found class name.
*/
public function parseClass()
{
// Namespaces and class names are tokenized the same: T_STRINGs
// separated by T_NS_SEPARATOR so we can use one function to provide
// both.
return $this->parseNamespace();
}
}
================================================
FILE: phpbench.json.dist
================================================
{
"bootstrap": "tests/Doctrine/Performance/Common/bootstrap.php",
"path": "tests/Doctrine/Performance/Common/Annotations"
}
================================================
FILE: phpcs.xml.dist
================================================
<?xml version="1.0"?>
<ruleset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd"
>
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<!-- Show progress of the run and show sniff names -->
<arg value="ps"/>
<config name="php_version" value="70100"/>
<file>lib</file>
<file>tests</file>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint"/>
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint"/>
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousTraitNaming.SuperfluousSuffix"/>
<exclude name="SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants.DisallowedLateStaticBindingForConstant"/>
<exclude name="SlevomatCodingStandard.ControlStructures.ControlStructureSpacing.IncorrectLinesCountAfterLastControlStructure"/>
<exclude name="PSR2.Methods.MethodDeclaration.Underscore"/>
<!-- https://github.com/slevomat/coding-standard/issues/867 -->
<exclude name="SlevomatCodingStandard.ControlStructures.JumpStatementsSpacing.IncorrectLinesCountAfterLastControlStructure"/>
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/issues/2937 -->
<exclude name="Squiz.Arrays.ArrayDeclaration.ValueNoNewline"/>
<exclude name="Squiz.NamingConventions.ValidVariableName.PublicHasUnderscore"/>
</rule>
<!-- Disable the rules that will require PHP 7.4 -->
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<properties>
<property name="enableNativeTypeHint" value="false"/>
</properties>
</rule>
<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
<exclude-pattern>*/lib/Doctrine/Common/Annotations/DocParser.php</exclude-pattern>
</rule>
<rule ref="Squiz.Classes.ValidClassName.NotCamelCaps">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassNoNamespaceNoComment.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations.AnnotationForbidden">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.DocCommentSpacing">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/SimpleAnnotationReaderTest.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash.UseStartsWithBackslash">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="PSR12.Files.ImportStatement.LeadingSlash">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.LongTypeHints.UsedLongTypeHint">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UseFromSameNamespace.UseFromSameNamespace">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash.UseStartsWithBackslash">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UseSpacing.IncorrectLinesCountBetweenSameTypeOfUse">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.MultipleUsesPerLine.MultipleUsesPerLine">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="Generic.WhiteSpace.LanguageConstructSpacing">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="Squiz.Classes.ValidClassName">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/*</exclude-pattern>
</rule>
<!-- https://github.com/slevomat/coding-standard/issues/1066 -->
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses">
<exclude-pattern>*/lib/Doctrine/Common/Annotations/DocParser.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/PhpParserTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM141Test.php</exclude-pattern>
</rule>
<!-- It is easier to understand tests that involve annotations if you can
declare several dummy classes with annotations in the same file -->
<rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
<exclude-pattern>*/tests/*</exclude-pattern>
</rule>
<rule ref="Squiz.Classes.ClassFileName.NoMatch">
<exclude-pattern>*/tests/*</exclude-pattern>
</rule>
<rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Test.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/PhpParserTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceWithClosureDeclaration.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithRequire.php</exclude-pattern>
</rule>
<!-- these classes do not have a namespace on purpose -->
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/NonNamespacedClass.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassNoNamespaceNoComment.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/TopLevelAnnotation.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingAnyTypeHint">
<!-- there is a class property with an empty var annotation on purpose -->
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/DummyClass.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithValidAnnotationTarget.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.DisallowGroupUse.DisallowedGroupUse">
<!-- The name of the file alone explains this -->
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/GroupUseStatement.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithVarType.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/EmptyInterface.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceThatExtendsAnInterface.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousPrefix">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceThatExtendsAnInterface.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceWithConstants.php</exclude-pattern>
</rule>
<rule ref="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase">
<!-- Usage of mixed case constants seems pretty deliberate here -->
<exclude-pattern>*/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php</exclude-pattern>
</rule>
<rule ref="Squiz.Functions.GlobalFunction.Found">
<exclude-pattern>*/tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php</exclude-pattern>
</rule>
<!-- Single-line PHPDoc blocks will confuse PHPUnit 7.5 -->
<rule ref="SlevomatCodingStandard.Commenting.RequireOneLineDocComment.MultiLineDocComment">
<exclude-pattern>*/tests</exclude-pattern>
</rule>
</ruleset>
================================================
FILE: phpstan.neon
================================================
parameters:
level: 3
phpVersion: 80500
paths:
- lib
- tests
scanFiles:
- tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsFirst.php
- tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsLast.php
- tests/Doctrine/Tests/Common/Annotations/Fixtures/NonNamespacedClass.php
- tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php
excludePaths:
- tests/*/Fixtures/*
- tests/Doctrine/Tests/Common/Annotations/ReservedKeywordsClasses.php
- tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php
- tests/Doctrine/Tests/DoctrineTestCase.php
polluteScopeWithLoopInitialAssignments: true
ignoreErrors:
- '#Instantiated class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#'
- '#Property Doctrine\\Tests\\Common\\Annotations\\DummyClassNonAnnotationProblem::\$foo has unknown class#'
- '#Call to an undefined static method PHPUnit\\Framework\\TestCase::expectExceptionMessageRegExp\(\)#'
-
identifier: phpDoc.parseError
path: tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php
================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="utf-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="true"
bootstrap="./tests/Doctrine/Tests/TestInit.php"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Doctrine Annotations Test Suite">
<directory>./tests/Doctrine/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./lib/Doctrine/</directory>
</whitelist>
</filter>
</phpunit>
================================================
FILE: psalm.xml
================================================
<?xml version="1.0"?>
<psalm
errorLevel="7"
phpVersion="8.2"
resolveFromConfigFile="true"
findUnusedBaselineEntry="true"
findUnusedCode="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="lib/Doctrine/Common/Annotations" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<NoValue>
<errorLevel type="suppress">
<file name="lib/Doctrine/Common/Annotations/Annotation/Enum.php" />
<file name="lib/Doctrine/Common/Annotations/Annotation/Target.php" />
</errorLevel>
</NoValue>
</issueHandlers>
</psalm>
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/CachedReadPerformanceWithInMemoryBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\PsrCachedReader;
use Doctrine\Tests\Common\Annotations\Fixtures\Controller;
use ReflectionMethod;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
/**
* @BeforeMethods({"initialize"})
*/
final class CachedReadPerformanceWithInMemoryBench
{
/** @var PsrCachedReader */
private $reader;
/** @var ReflectionMethod */
private $method;
public function initialize(): void
{
$this->reader = new PsrCachedReader(new AnnotationReader(), new ArrayAdapter());
$this->method = new ReflectionMethod(Controller::class, 'helloAction');
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function bench(): void
{
$this->reader->getMethodAnnotations($this->method);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/DocLexerPerformanceBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\DocLexer;
/**
* @BeforeMethods({"initializeMethod", "initialize"})
*/
final class DocLexerPerformanceBench
{
use MethodInitializer;
/** @var DocLexer */
private $lexer;
public function initialize(): void
{
$this->lexer = new DocLexer();
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function benchMethod(): void
{
$this->lexer->setInput($this->methodDocBlock);
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function benchClass(): void
{
$this->lexer->setInput($this->classDocBlock);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/DocParserPerformanceBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\DocParser;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;
use function array_fill_keys;
/**
* @BeforeMethods({"initializeMethod", "initialize"})
*/
final class DocParserPerformanceBench
{
use MethodInitializer;
private const IMPORTS = [
'ignorephpdoc' => 'Annotations\Annotation\IgnorePhpDoc',
'ignoreannotation' => 'Annotations\Annotation\IgnoreAnnotation',
'route' => Route::class,
'template' => Template::class,
'__NAMESPACE__' => 'Doctrine\Tests\Common\Annotations\Fixtures',
];
private const IGNORED = [
'access', 'author', 'copyright', 'deprecated', 'example', 'ignore',
'internal', 'link', 'see', 'since', 'tutorial', 'version', 'package',
'subpackage', 'name', 'global', 'param', 'return', 'staticvar',
'static', 'var', 'throws', 'inheritdoc',
];
/** @var DocParser */
private $parser;
public function initialize(): void
{
$this->parser = new DocParser();
$this->parser->setImports(self::IMPORTS);
$this->parser->setIgnoredAnnotationNames(array_fill_keys(self::IGNORED, true));
$this->parser->setIgnoreNotImportedAnnotations(true);
}
/**
* @Revs(200)
* @Iterations(5)
*/
public function benchMethodParsing(): void
{
$this->parser->parse($this->methodDocBlock);
}
/**
* @Revs(200)
* @Iterations(5)
*/
public function benchClassParsing(): void
{
$this->parser->parse($this->classDocBlock);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/MethodInitializer.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Tests\Common\Annotations\Fixtures\Controller;
use ReflectionMethod;
trait MethodInitializer
{
/** @var ReflectionMethod */
private $method;
/** @var string */
private $methodDocBlock;
/** @var string */
private $classDocBlock;
public function initializeMethod(): void
{
$this->method = new ReflectionMethod(Controller::class, 'helloAction');
$this->methodDocBlock = $this->method->getDocComment();
$this->classDocBlock = $this->method->getDeclaringClass()->getDocComment();
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithShortCutBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\PhpParser;
use Doctrine\Tests\Common\Annotations\Fixtures\NamespacedSingleClassLOC1000;
use ReflectionClass;
/**
* @BeforeMethods({"initialize"})
*/
final class PhpParserPerformanceWithShortCutBench
{
/** @var ReflectionClass */
private $class;
/** @var PhpParser */
private $parser;
public function initialize(): void
{
$this->class = new ReflectionClass(NamespacedSingleClassLOC1000::class);
$this->parser = new PhpParser();
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function bench(): void
{
$this->parser->parseUseStatements($this->class);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithoutShortCutBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\PhpParser;
use ReflectionClass;
use SingleClassLOC1000;
/**
* @BeforeMethods({"initialize"})
*/
final class PhpParserPerformanceWithoutShortCutBench
{
/** @var ReflectionClass */
private $class;
/** @var PhpParser */
private $parser;
public function initialize(): void
{
$this->class = new ReflectionClass(SingleClassLOC1000::class);
$this->parser = new PhpParser();
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function bench(): void
{
$this->parser->parseUseStatements($this->class);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/Annotations/ReadPerformanceBench.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Performance\Common\Annotations;
use Doctrine\Common\Annotations\AnnotationReader;
/**
* @BeforeMethods({"initializeMethod", "initialize"})
*/
final class ReadPerformanceBench
{
use MethodInitializer;
/** @var AnnotationReader */
private $reader;
public function initialize(): void
{
$this->reader = new AnnotationReader();
}
/**
* @Revs(500)
* @Iterations(5)
*/
public function bench(): void
{
$this->reader->getMethodAnnotations($this->method);
}
}
================================================
FILE: tests/Doctrine/Performance/Common/bootstrap.php
================================================
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../../../vendor/autoload.php';
require_once __DIR__ . '/../../Tests/Common/Annotations/Fixtures/Annotation/Route.php';
require_once __DIR__ . '/../../Tests/Common/Annotations/Fixtures/Annotation/Secure.php';
require_once __DIR__ . '/../../Tests/Common/Annotations/Fixtures/Annotation/Template.php';
================================================
FILE: tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php
================================================
<?php
namespace Doctrine\Tests\Common\Annotations;
use Doctrine\Common\Annotations\Annotation;
use Doctrine\Common\Annotations\AnnotationException;
use Doctrine\Common\Annotations\Reader;
use Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use Test;
use TopLevelAnnotation;
use function class_exists;
use function reset;
require_once __DIR__ . '/TopLevelAnnotation.php';
abstract class AbstractReaderTest extends TestCase
{
/** @var bool */
private $expectException = true;
final protected function ignoreIssues(): void
{
$this->expectException = false;
}
public function getReflectionClass(): ReflectionClass
{
return new ReflectionClass(DummyClass::class);
}
public function testAnnotations(): void
{
$class = $this->getReflectionClass();
$reader = $this->getReader();
self::assertCount(1, $reader->getClassAnnotations($class));
self::assertInstanceOf(
$annotName = DummyAnnotation::class,
$annot = $reader->getClassAnnotation($class, $annotName)
);
self::assertEquals('hello', $annot->dummyValue);
$field1Prop = $class->getProperty('field1');
$propAnnots = $reader->getPropertyAnnotations($field1Prop);
self::assertCount(1, $propAnnots);
self::assertInstanceOf($annotName, $annot = $reader->getPropertyAnnotation($field1Prop, $annotName));
self::assertEquals('fieldHello', $annot->dummyValue);
$getField1Method = $class->getMethod('getField1');
$methodAnnots = $reader->getMethodAnnotations($getField1Method);
self::assertCount(1, $methodAnnots);
self::assertInstanceOf($annotName, $annot = $reader->getMethodAnnotation($getField1Method, $annotName));
self::assertEquals([1, 2, 'three'], $annot->value);
$field2Prop = $class->getProperty('field2');
$propAnnots = $reader->getPropertyAnnotations($field2Prop);
self::assertCount(1, $propAnnots);
self::assertInstanceOf(
$annotName = DummyJoinTable::class,
$joinTableAnnot = $reader->getPropertyAnnotation($field2Prop, $annotName)
);
self::assertCount(1, $joinTableAnnot->joinColumns);
self::assertCount(1, $joinTableAnnot->inverseJoinColumns);
self::assertInstanceOf(DummyJoinColumn::class, $joinTableAnnot->joinColumns[0]);
self::assertInstanceOf(DummyJoinColumn::class, $joinTableAnnot->inverseJoinColumns[0]);
self::assertEquals('col1', $joinTableAnnot->joinColumns[0]->name);
self::assertEquals('col2', $joinTableAnnot->joinColumns[0]->referencedColumnName);
self::assertEquals('col3', $joinTableAnnot->inverseJoinColumns[0]->name);
self::assertEquals('col4', $joinTableAnnot->inverseJoinColumns[0]->referencedColumnName);
$dummyAnnot = $reader->getMethodAnnotation($class->getMethod('getField1'), DummyAnnotation::class);
self::assertEquals('', $dummyAnnot->dummyValue);
self::assertEquals([1, 2, 'three'], $dummyAnnot->value);
$dummyAnnot = $reader->getMethodAnnotation($class->getMethod('getField3'), DummyAnnotation::class);
self::assertEquals('\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d', $dummyAnnot->value);
$dummyAnnot = $reader->getPropertyAnnotation($class->getProperty('field1'), DummyAnnotation::class);
self::assertEquals('fieldHello', $dummyAnnot->dummyValue);
$classAnnot = $reader->getClassAnnotation($class, DummyAnnotation::class);
self::assertEquals('hello', $classAnnot->dummyValue);
}
public function testAnnotationsWithValidTargets(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithValidAnnotationTarget::class);
self::assertCount(1, $reader->getClassAnnotations($class));
self::assertCount(1, $reader->getPropertyAnnotations($class->getProperty('foo')));
self::assertCount(1, $reader->getMethodAnnotations($class->getMethod('someFunction')));
self::assertCount(1, $reader->getPropertyAnnotations($class->getProperty('nested')));
}
public function testAnnotationsWithVarType(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithAnnotationWithVarType::class);
self::assertCount(1, $fooAnnot = $reader->getPropertyAnnotations($class->getProperty('foo')));
self::assertCount(1, $barAnnot = $reader->getMethodAnnotations($class->getMethod('bar')));
self::assertIsString($fooAnnot[0]->string);
self::assertInstanceOf(Fixtures\AnnotationTargetAll::class, $barAnnot[0]->annotation);
}
public function testAtInDescription(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithAtInDescriptionAndAnnotation::class);
self::assertCount(1, $fooAnnot = $reader->getPropertyAnnotations($class->getProperty('foo')));
self::assertCount(1, $barAnnot = $reader->getPropertyAnnotations($class->getProperty('bar')));
self::assertInstanceOf(Fixtures\AnnotationTargetPropertyMethod::class, $fooAnnot[0]);
self::assertInstanceOf(Fixtures\AnnotationTargetPropertyMethod::class, $barAnnot[0]);
}
public function testClassWithWithDanglingComma(): void
{
$reader = $this->getReader();
$annots = $reader->getClassAnnotations(new ReflectionClass(DummyClassWithDanglingComma::class));
self::assertCount(1, $annots);
}
public function testClassWithInvalidAnnotationTargetAtClassDocBlock(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Semantical Error] Annotation @AnnotationTargetPropertyMethod is not allowed to be declared on class' .
' Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtClass.' .
' You may only use this annotation on these code elements: METHOD, PROPERTY'
);
}
$reader->getClassAnnotations(new ReflectionClass(Fixtures\ClassWithInvalidAnnotationTargetAtClass::class));
}
public function testClassWithWithInclude(): void
{
$reader = $this->getReader();
$annots = $reader->getClassAnnotations(new ReflectionClass(Fixtures\ClassWithRequire::class));
self::assertCount(1, $annots);
}
public function testClassWithInvalidAnnotationTargetAtPropertyDocBlock(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Semantical Error] Annotation @AnnotationTargetClass is not allowed to be declared on property' .
' Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty::$foo. ' .
'You may only use this annotation on these code elements: CLASS'
);
}
$reader->getPropertyAnnotations(new ReflectionProperty(
Fixtures\ClassWithInvalidAnnotationTargetAtProperty::class,
'foo'
));
}
public function testClassWithInvalidNestedAnnotationTargetAtPropertyDocBlock(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Semantical Error] Annotation @AnnotationTargetAnnotation is not allowed to be declared on property' .
' Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty::$bar.' .
' You may only use this annotation on these code elements: ANNOTATION'
);
}
$reader->getPropertyAnnotations(new ReflectionProperty(
Fixtures\ClassWithInvalidAnnotationTargetAtProperty::class,
'bar'
));
}
public function testClassWithInvalidAnnotationTargetAtMethodDocBlock(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Semantical Error] Annotation @AnnotationTargetClass is not allowed to be declared on method' .
' Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtMethod' .
'::functionName(). You may only use this annotation on these code elements: CLASS'
);
}
$reader->getMethodAnnotations(new ReflectionMethod(
Fixtures\ClassWithInvalidAnnotationTargetAtMethod::class,
'functionName'
));
}
public function testClassWithAnnotationWithTargetSyntaxErrorAtClassDocBlock(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')' at position 24" .
' in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.'
);
$reader->getClassAnnotations(new ReflectionClass(
Fixtures\ClassWithAnnotationWithTargetSyntaxError::class
));
}
public function testClassWithAnnotationWithTargetSyntaxErrorAtPropertyDocBlock(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')' at position 24" .
' in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.'
);
$reader->getPropertyAnnotations(new ReflectionProperty(
Fixtures\ClassWithAnnotationWithTargetSyntaxError::class,
'foo'
));
}
public function testClassWithAnnotationWithTargetSyntaxErrorAtMethodDocBlock(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')' at position 24" .
' in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.'
);
$reader->getMethodAnnotations(new ReflectionMethod(
Fixtures\ClassWithAnnotationWithTargetSyntaxError::class,
'bar'
));
}
public function testClassWithPropertyInvalidVarTypeError(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithAnnotationWithVarType::class);
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Type Error] Attribute "string" of @AnnotationWithVarType declared on property' .
' Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType::$invalidProperty' .
' expects a(n) string, but got integer.'
);
$reader->getPropertyAnnotations($class->getProperty('invalidProperty'));
}
public function testClassWithMethodInvalidVarTypeError(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithAnnotationWithVarType::class);
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'[Type Error] Attribute "annotation" of @AnnotationWithVarType declared' .
' on method Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType::invalidMethod()' .
' expects a(n) \Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,' .
' but got an instance of Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation.'
);
$reader->getMethodAnnotations($class->getMethod('invalidMethod'));
}
public function testClassSyntaxErrorContext(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')' at position 18" .
' in class Doctrine\Tests\Common\Annotations\DummyClassSyntaxError.'
);
$reader->getClassAnnotations(new ReflectionClass(DummyClassSyntaxError::class));
}
public function testMethodSyntaxErrorContext(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')' at position 18" .
' in method Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError::foo().'
);
$reader->getMethodAnnotations(new ReflectionMethod(DummyClassMethodSyntaxError::class, 'foo'));
}
public function testPropertySyntaxErrorContext(): void
{
$reader = $this->getReader();
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
"Expected namespace separator or identifier, got ')'" .
' at position 36 in property Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError::$foo.'
);
$reader->getPropertyAnnotations(new ReflectionProperty(DummyClassPropertySyntaxError::class, 'foo'));
}
/**
* @group regression
*/
public function testMultipleAnnotationsOnSameLine(): void
{
$reader = $this->getReader();
$annots = $reader->getPropertyAnnotations(new ReflectionProperty(DummyClass2::class, 'id'));
self::assertCount(3, $annots);
}
public function testNonAnnotationProblem(): void
{
$reader = $this->getReader();
self::assertNotNull($annot = $reader->getPropertyAnnotation(
new ReflectionProperty(DummyClassNonAnnotationProblem::class, 'foo'),
$name = DummyAnnotation::class
));
self::assertInstanceOf($name, $annot);
}
public function testIncludeIgnoreAnnotation(): void
{
$reader = $this->getReader();
$reader->getPropertyAnnotations(new ReflectionProperty(Fixtures\ClassWithIgnoreAnnotation::class, 'foo'));
self::assertFalse(class_exists(Fixtures\IgnoreAnnotationClass::class, false));
}
public function testImportWithConcreteAnnotation(): void
{
$reader = $this->getReader();
$property = new ReflectionProperty(TestImportWithConcreteAnnotation::class, 'field');
$annotations = $reader->getPropertyAnnotations($property);
self::assertCount(1, $annotations);
self::assertNotNull($reader->getPropertyAnnotation($property, DummyAnnotation::class));
}
public function testImportWithInheritance(): void
{
$reader = $this->getReader();
$class = new TestParentClass();
$ref = new ReflectionClass($class);
$childAnnotations = $reader->getPropertyAnnotations($ref->getProperty('child'));
self::assertCount(1, $childAnnotations);
self::assertInstanceOf(Foo\Name::class, reset($childAnnotations));
$parentAnnotations = $reader->getPropertyAnnotations($ref->getProperty('parent'));
self::assertCount(1, $parentAnnotations);
self::assertInstanceOf(Bar\Name::class, reset($parentAnnotations));
}
public function testImportDetectsNotImportedAnnotation(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'The annotation "@NameFoo" in property' .
' Doctrine\Tests\Common\Annotations\TestAnnotationNotImportedClass::$field was never imported.'
);
}
$reader->getPropertyAnnotations(new ReflectionProperty(TestAnnotationNotImportedClass::class, 'field'));
}
public function testImportDetectsNonExistentAnnotation(): void
{
$reader = $this->getReader();
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'The annotation "@Foo\Bar\Name" in property' .
' Doctrine\Tests\Common\Annotations\TestNonExistentAnnotationClass::$field was never imported.'
);
}
$reader->getPropertyAnnotations(new ReflectionProperty(TestNonExistentAnnotationClass::class, 'field'));
}
public function testTopLevelAnnotation(): void
{
$reader = $this->getReader();
$annotations = $reader->getPropertyAnnotations(new ReflectionProperty(
TestTopLevelAnnotationClass::class,
'field'
));
self::assertCount(1, $annotations);
self::assertInstanceOf(TopLevelAnnotation::class, reset($annotations));
}
public function testIgnoresAnnotationsNotPrefixedWithWhitespace(): void
{
$reader = $this->getReader();
$annotation = $reader->getClassAnnotation(
new ReflectionClass(new TestIgnoresNonAnnotationsClass()),
NameBar::class
);
self::assertInstanceOf(NameBar::class, $annotation);
}
private static $testResetsPhpParserAfterUseRun = false;
/**
* When getUseStatements isn't available on ReflectionClass the PhpParser has to use token_get_all(). If that
* happens various PHP compiler globals get set, and these can have seriously bad effects on the next file to be
* parsed.
* Notably the doc_comment compiler global can end up containing a docblock comment. The next file to be parsed
* on an include() will have this docblock comment attached to the first thing in the file that the compiler
* considers to own comments. If this is a class then any later calls to getDocComment() for that class will have
* undesirable effects. *sigh*
*/
public function testResetsPhpParserAfterUse(): void
{
// If someone has already included our main test fixture this test is invalid. It's important that our require
// causes this file to be parsed and compiled at a certain point.
self::assertFalse(! self::$testResetsPhpParserAfterUseRun && class_exists(
Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment::class
), 'Test invalid if class has already been compiled');
self::$testResetsPhpParserAfterUseRun = true;
$reader = $this->getReader();
// First make sure the annotation cache knows about the annotations we want to use.
// If we don't do this then loading of annotations into the cache will cause the parser to get out of the bad
// state we want to test.
$class = new ReflectionClass(Fixtures\ClassWithValidAnnotationTarget::class);
$reader->getClassAnnotations($class);
// Now import an incredibly dull class which makes use of the same
// class level annotation that the previous class does.
$class = new ReflectionClass(Fixtures\ClassWithClassAnnotationOnly::class);
$annotations = $reader->getClassAnnotations($class);
// This include needs to be here since we need the PHP compiler to run over it as the next thing the PHP
// parser sees since PhpParser called token_get_all() on the intro to ClassWithClassAnnotationOnly.
// Our test class cannot be in a namespace (some versions of PHP reset the doc_comment compiler global when
// you hit a namespace declaration), so cannot be autoloaded.
require_once __DIR__ . '/Fixtures/ClassNoNamespaceNoComment.php';
// So, hopefully, if all has gone OK, our class with class annotations should actually have them.
// If this fails then something is quite badly wrong elsewhere.
// Note that if this happens before the require it can cause other PHP files to be included, resetting the
// compiler global state, and invalidating this test case.
self::assertNotEmpty($annotations);
$annotations = $reader->getClassAnnotations(new ReflectionClass(
new Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment()
));
// And if our workaround for this bug is OK, our class with no doc
// comment should not have any class annotations.
self::assertEmpty($annotations);
}
public function testErrorWhenInvalidAnnotationIsUsed(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\InvalidAnnotationUsageClass::class);
if ($this->expectException) {
$this->expectException(AnnotationException::class);
$this->expectExceptionMessage(
'The class "Doctrine\Tests\Common\Annotations\Fixtures\NoAnnotation" is not annotated with @Annotation.
Are you sure this class can be used as annotation?
If so, then you need to add @Annotation to the _class_ doc comment of' .
' "Doctrine\Tests\Common\Annotations\Fixtures\NoAnnotation".
If it is indeed no annotation, then you need to add @IgnoreAnnotation("NoAnnotation") to the _class_ doc comment' .
' of class Doctrine\Tests\Common\Annotations\Fixtures\InvalidAnnotationUsageClass.'
);
}
$reader->getClassAnnotations($ref);
}
public function testInvalidAnnotationUsageButIgnoredClass(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\InvalidAnnotationUsageButIgnoredClass::class);
$annots = $reader->getClassAnnotations($ref);
self::assertCount(2, $annots);
}
/**
* @group DDC-1660
* @group regression
*/
public function testInvalidAnnotationButIgnored(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassDDC1660::class);
self::assertTrue(class_exists(Fixtures\Annotation\Version::class));
self::assertEmpty($reader->getClassAnnotations($class));
self::assertEmpty($reader->getMethodAnnotations($class->getMethod('bar')));
self::assertEmpty($reader->getPropertyAnnotations($class->getProperty('foo')));
}
public function testAnnotationEnumeratorException(): void
{
$reader = $this->getReader();
$class = new ReflectionClass(Fixtures\ClassWithAnnotationEnum::class);
self::assertCount(1, $bar = $reader->getMethodAnnotations($class->getMethod('bar')));
self::assertCount(1, $foo = $reader->getPropertyAnnotations($class->getProperty('foo')));
self::assertInstanceOf(Fixtures\AnnotationEnum::class, $bar[0]);
self::assertInstanceOf(Fixtures\AnnotationEnum::class, $foo[0]);
try {
$reader->getPropertyAnnotations($class->getProperty('invalidProperty'));
$this->fail();
} catch (AnnotationException $exc) {
self::assertEquals(
'[Enum Error] Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum' .
' declared on property Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationEnum' .
'::$invalidProperty accepts only [ONE, TWO, THREE], but got FOUR.',
$exc->getMessage()
);
}
try {
$reader->getMethodAnnotations($class->getMethod('invalidMethod'));
$this->fail();
} catch (AnnotationException $exc) {
self::assertEquals(
'[Enum Error] Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum' .
' declared on method Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationEnum' .
'::invalidMethod() accepts only [ONE, TWO, THREE], but got 5.',
$exc->getMessage()
);
}
}
/**
* @group DCOM-106
*/
public function testIgnoreFixMeAndUpperCaseToDo(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(DCOM106::class);
self::assertEmpty($reader->getClassAnnotations($ref));
}
public function testWillSkipAnnotationsContainingDashes(): void
{
self::assertEmpty(
$this
->getReader()
->getClassAnnotations(new ReflectionClass(
Fixtures\ClassWithInvalidAnnotationContainingDashes::class
))
);
}
public function testWillFailOnAnnotationConstantReferenceContainingDashes(): void
{
$reader = $this->getReader();
$reflection = new ReflectionClass(Fixtures\ClassWithAnnotationConstantReferenceWithDashes::class);
$this->expectExceptionMessage(
'[Syntax Error] Expected Doctrine\Common\Annotations\DocLexer::T_CLOSE_PARENTHESIS, got \'-\' at'
. ' position 14 in class ' . Fixtures\ClassWithAnnotationConstantReferenceWithDashes::class . '.'
);
$reader->getClassAnnotations($reflection);
}
abstract protected function getReader(): Reader;
}
/**
* @parseAnnotation("var")
*/
class TestParseAnnotationClass
{
/** @var */
public $field;
}
/**
* @NameBar
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class TestIgnoresNonAnnotationsClass
{
}
class TestTopLevelAnnotationClass
{
/**
* @var mixed
* @\TopLevelAnnotation
*/
public $field;
}
class TestNonExistentAnnotationClass
{
/**
* @var mixed
* @Foo\Bar\Name
*/
public $field;
}
class TestAnnotationNotImportedClass
{
/**
* @var mixed
* @NameFoo
*/
public $field;
}
class TestChildClass
{
/**
* @var mixed
* @\Doctrine\Tests\Common\Annotations\Foo\Name(name = "foo")
*/
protected $child;
}
class TestParentClass extends TestChildClass
{
/**
* @var mixed
* @\Doctrine\Tests\Common\Annotations\Bar\Name(name = "bar")
*/
public $parent;
}
class TestImportWithConcreteAnnotation
{
/**
* @var mixed
* @DummyAnnotation(dummyValue = "bar")
*/
public $field;
}
/**
* @ignoreAnnotation("var")
*/
class DummyClass2
{
/**
* @DummyId
* @DummyColumn(type="integer")
* @DummyGeneratedValue
* @var int
*/
public $id;
}
/** @Annotation */
class NameBar extends Annotation
{
}
/** @Annotation */
class DummyId extends Annotation
{
}
/** @Annotation */
class DummyColumn extends Annotation
{
/** @var mixed */
public $type;
}
/** @Annotation */
class DummyGeneratedValue extends Annotation
{
}
/** @Annotation */
class DummyAnnotation extends Annotation
{
/** @var mixed */
public $dummyValue;
}
/**
* @Annotation
*/
class DummyAnnotationWithIgnoredAnnotation extends Annotation
{
/** @var mixed */
public $dummyValue;
}
/** @Annotation */
class DummyJoinColumn extends Annotation
{
/** @var mixed */
public $name;
/** @var mixed */
public $referencedColumnName;
}
/** @Annotation */
class DummyJoinTable extends Annotation
{
/** @var mixed */
public $name;
/** @var mixed */
public $joinColumns;
/** @var mixed */
public $inverseJoinColumns;
}
/**
* @DummyAnnotation(dummyValue = "bar",)
*/
class DummyClassWithDanglingComma
{
}
/**
* @DummyAnnotation(@)
*/
class DummyClassSyntaxError
{
}
class DummyClassMethodSyntaxError
{
/**
* @DummyAnnotation(@)
*/
public function foo(): void
{
}
}
class DummyClassPropertySyntaxError
{
/**
* @var mixed
* @DummyAnnotation(@)
*/
public $foo;
}
/**
* @ignoreAnnotation({"since", "var"})
*/
class DummyClassNonAnnotationProblem
{
/**
* @DummyAnnotation
* @var Test
*/
public $foo;
}
/**
* @DummyAnnotation Foo bar <foobar@1domain.com>
*/
class DummyClassWithEmail
{
}
/**
* @fixme public
* @TODO
*/
class DCOM106
{
}
namespace Doctrine\Tests\Common\Annotations\Foo;
use Doctrine\Common\Annotations\Annotation;
/** @Annotation */
class Name extends Annotation
{
/** @var mixed */
public $name;
}
namespace Doctrine\Tests\Common\Annotations\Bar;
use Doctrine\Common\Annotations\Annotation;
/** @Annotation */
class Name extends Annotation
{
/** @var mixed */
public $name;
}
================================================
FILE: tests/Doctrine/Tests/Common/Annotations/Annotation/TargetTest.php
================================================
<?php
namespace Doctrine\Tests\Common\Annotations\Annotation;
use Doctrine\Common\Annotations\Annotation\Target;
use PHPUnit\Framework\TestCase;
/**
* Tests for {@see \Doctrine\Common\Annotations\Annotation\Target}
*
* @covers \Doctrine\Common\Annotations\Annotation\Target
*/
class TargetTest extends TestCase
{
/**
* @group DDC-3006
*/
public function testValidMixedTargets(): void
{
$target = new Target(['value' => ['ALL']]);
self::assertEquals(Target::TARGET_ALL, $target->targets);
$target = new Target(['value' => ['METHOD', 'METHOD']]);
self::assertEquals(Target::TARGET_METHOD, $target->targets);
self::assertNotEquals(Target::TARGET_PROPERTY, $target->targets);
$target = new Target(['value' => ['PROPERTY', 'METHOD']]);
self::assertEquals(Target::TARGET_METHOD | Target::TARGET_PROPERTY, $target->targets);
}
}
================================================
FILE: tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php
================================================
<?php
namespace Doctrine\Tests\Common\Annotations;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\DocParser;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\SingleUseAnnotation;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithEnumProperty;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithEnumAnnotations;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithFullPathUseStatement;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithImportedIgnoredAnnotation;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithPHPCodeSnifferAnnotation;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithPhpCsSuppressAnnotation;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithPHPStanGenericsAnnotations;
use Doctrine\Tests\Common\Annotations\Fixtures\IgnoredNamespaces\AnnotatedAtClassLevel;
use Doctrine\Tests\Common\Annotations\Fixtures\IgnoredNamespaces\AnnotatedAtMethodLevel;
use Doctrine\Tests\Common\Annotations\Fixtures\IgnoredNamespaces\AnnotatedAtPropertyLevel;
use Doctrine\Tests\Common\Annotations\Fixtures\IgnoredNamespaces\AnnotatedWithAlias;
use Doctrine\Tests\Common\Annotations\Fixtures\Suit;
use InvalidArgumentException;
use LogicException;
use ReflectionClass;
use ReflectionFunction;
use function class_exists;
use function spl_autoload_register;
use function spl_autoload_unregister;
use const PHP_VERSION_ID;
class AnnotationReaderTest extends AbstractReaderTest
{
/**
* @return AnnotationReader
*/
protected function getReader(?DocParser $parser = null): Reader
{
return new AnnotationReader($parser);
}
public function testMethodAnnotationFromTrait(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassUsesTrait::class);
$annotations = $reader->getMethodAnnotations($ref->getMethod('someMethod'));
self::assertInstanceOf(Bar\Autoload::class, $annotations[0]);
$annotations = $reader->getMethodAnnotations($ref->getMethod('traitMethod'));
self::assertInstanceOf(Fixtures\Annotation\Autoload::class, $annotations[0]);
}
public function testMethodAnnotationFromOverwrittenTrait(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassOverwritesTrait::class);
$annotations = $reader->getMethodAnnotations($ref->getMethod('traitMethod'));
self::assertInstanceOf(Bar2\Autoload::class, $annotations[0]);
}
public function testPropertyAnnotationFromTrait(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassUsesTrait::class);
$annotations = $reader->getPropertyAnnotations($ref->getProperty('aProperty'));
self::assertInstanceOf(Bar\Autoload::class, $annotations[0]);
$annotations = $reader->getPropertyAnnotations($ref->getProperty('traitProperty'));
self::assertInstanceOf(Fixtures\Annotation\Autoload::class, $annotations[0]);
}
public function testOmitNotRegisteredAnnotation(): void
{
$parser = new DocParser();
$parser->setIgnoreNotImportedAnnotations(true);
$reader = $this->getReader($parser);
$ref = new ReflectionClass(Fixtures\ClassWithNotRegisteredAnnotationUsed::class);
$annotations = $reader->getMethodAnnotations($ref->getMethod('methodWithNotRegisteredAnnotation'));
self::assertEquals([], $annotations);
}
public function testClassAnnotationSupportsSelfAccessorForConstants(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassWithAnnotationWithSelfConstantReference::class);
$annotations = $reader->getClassAnnotations($ref);
self::assertCount(1, $annotations);
$annotation = $annotations[0];
self::assertInstanceOf(Fixtures\AnnotationWithConstants::class, $annotation);
self::assertEquals(
$annotation->value,
Fixtures\ClassWithAnnotationWithSelfConstantReference::VALUE_FOR_CLASS
);
}
public function testPropertyAnnotationSupportsSelfAccessorForConstants(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassWithAnnotationWithSelfConstantReference::class);
$classProperty = $ref->getProperty('classProperty');
$classAnnotation = $reader->getPropertyAnnotation($classProperty, Fixtures\AnnotationWithConstants::class);
self::assertNotNull($classAnnotation);
self::assertEquals(
$classAnnotation->value,
Fixtures\ClassWithAnnotationWithSelfConstantReference::VALUE_FOR_CLASS
);
$traitProperty = $ref->getProperty('traitProperty');
$traitAnnotation = $reader->getPropertyAnnotation($traitProperty, Fixtures\AnnotationWithConstants::class);
self::assertNotNull($traitAnnotation);
self::assertEquals(
$traitAnnotation->value,
Fixtures\ClassWithAnnotationWithSelfConstantReference::VALUE_FOR_TRAIT
);
}
public function testMethodAnnotationSupportsSelfAccessorForConstants(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(Fixtures\ClassWithAnnotationWithSelfConstantReference::class);
$classMethod = $ref->getMethod('classMethod');
$classAnnotation = $reader->getMethodAnnotation($classMethod, Fixtures\AnnotationWithConstants::class);
self::assertNotNull($classAnnotation);
self::assertEquals(
$classAnnotation->value,
Fixtures\ClassWithAnnotationWithSelfConstantReference::VALUE_FOR_CLASS
);
$traitMethod = $ref->getMethod('traitMethod');
$traitAnnotation = $reader->getMethodAnnotation($traitMethod, Fixtures\AnnotationWithConstants::class);
self::assertNotNull($traitAnnotation);
self::assertEquals(
$traitAnnotation->value,
Fixtures\ClassWithAnnotationWithSelfConstantReference::VALUE_FOR_TRAIT
);
}
/**
* @group 45
* @runInSeparateProcess
*/
public function testClassAnnotationIsIgnored(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(AnnotatedAtClassLevel::class);
$reader::addGlobalIgnoredNamespace('SomeClassAnnotationNamespace');
self::assertEmpty($reader->getClassAnnotations($ref));
}
/**
* @group 45
* @runInSeparateProcess
*/
public function testMethodAnnotationIsIgnored(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(AnnotatedAtMethodLevel::class);
$reader::addGlobalIgnoredNamespace('SomeMethodAnnotationNamespace');
self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('test')));
}
/**
* @group 45
* @runInSeparateProcess
*/
public function testPropertyAnnotationIsIgnored(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(AnnotatedAtPropertyLevel::class);
$reader::addGlobalIgnoredNamespace('SomePropertyAnnotationNamespace');
self::assertEmpty($reader->getPropertyAnnotations($ref->getProperty('property')));
}
/**
* @group 244
* @runInSeparateProcess
*/
public function testAnnotationWithAliasIsIgnored(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(AnnotatedWithAlias::class);
$reader::addGlobalIgnoredNamespace('SomePropertyAnnotationNamespace');
self::assertEmpty($reader->getPropertyAnnotations($ref->getProperty('property')));
}
public function testClassWithFullPathUseStatement(): void
{
if (class_exists(SingleUseAnnotation::class, false)) {
throw new LogicException(
'The SingleUseAnnotation must not be used in other tests for this test to be useful.' .
'If the class is already loaded then the code path that finds the class to load is not used and ' .
'this test becomes useless.'
);
}
$reader = $this->getReader();
$ref = new ReflectionClass(ClassWithFullPathUseStatement::class);
$annotations = $reader->getClassAnnotations($ref);
self::assertInstanceOf(SingleUseAnnotation::class, $annotations[0]);
}
public function testPhpCsSuppressAnnotationIsIgnored(): void
{
$reader = $this->getReader();
$ref = new ReflectionClass(ClassWithPhpCsSuppressAnnotation::class);
self::assertEmpty($reader->getMethodAnnotations($ref->getMethod('foo')));
}
public function testG
gitextract_dxqf29h2/
├── .doctrine-project.json
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── coding-standards.yml
│ ├── composer-lint.yml
│ ├── continuous-integration.yml
│ ├── documentation.yml
│ ├── release-on-milestone-closed.yml
│ └── static-analysis.yml
├── .gitignore
├── LICENSE
├── README.md
├── UPGRADE.md
├── composer.json
├── docs/
│ ├── composer.json
│ └── en/
│ ├── annotations.rst
│ ├── custom.rst
│ ├── index.rst
│ └── sidebar.rst
├── lib/
│ └── Doctrine/
│ └── Common/
│ └── Annotations/
│ ├── Annotation/
│ │ ├── Attribute.php
│ │ ├── Attributes.php
│ │ ├── Enum.php
│ │ ├── IgnoreAnnotation.php
│ │ ├── NamedArgumentConstructor.php
│ │ ├── Required.php
│ │ └── Target.php
│ ├── Annotation.php
│ ├── AnnotationException.php
│ ├── AnnotationReader.php
│ ├── AnnotationRegistry.php
│ ├── DocLexer.php
│ ├── DocParser.php
│ ├── ImplicitlyIgnoredAnnotationNames.php
│ ├── IndexedReader.php
│ ├── PhpParser.php
│ ├── PsrCachedReader.php
│ ├── Reader.php
│ └── TokenParser.php
├── phpbench.json.dist
├── phpcs.xml.dist
├── phpstan.neon
├── phpunit.xml.dist
├── psalm.xml
└── tests/
└── Doctrine/
├── Performance/
│ └── Common/
│ ├── Annotations/
│ │ ├── CachedReadPerformanceWithInMemoryBench.php
│ │ ├── DocLexerPerformanceBench.php
│ │ ├── DocParserPerformanceBench.php
│ │ ├── MethodInitializer.php
│ │ ├── PhpParserPerformanceWithShortCutBench.php
│ │ ├── PhpParserPerformanceWithoutShortCutBench.php
│ │ └── ReadPerformanceBench.php
│ └── bootstrap.php
└── Tests/
├── Common/
│ └── Annotations/
│ ├── AbstractReaderTest.php
│ ├── Annotation/
│ │ └── TargetTest.php
│ ├── AnnotationReaderTest.php
│ ├── AnnotationRegistryTest.php
│ ├── AnnotationTest.php
│ ├── DocLexerTest.php
│ ├── DocParserTest.php
│ ├── DummyClass.php
│ ├── Fixtures/
│ │ ├── AbstractController.php
│ │ ├── Annotation/
│ │ │ ├── AnnotWithDefaultValue.php
│ │ │ ├── Autoload.php
│ │ │ ├── CanBeAutoLoaded.php
│ │ │ ├── LoadedUsingRegisterFile.php
│ │ │ ├── Param.php
│ │ │ ├── Route.php
│ │ │ ├── Secure.php
│ │ │ ├── ShouldNeverBeLoaded.php
│ │ │ ├── SingleUseAnnotation.php
│ │ │ ├── Template.php
│ │ │ └── Version.php
│ │ ├── AnnotationEnum.php
│ │ ├── AnnotationEnumInvalid.php
│ │ ├── AnnotationEnumLiteral.php
│ │ ├── AnnotationEnumLiteralInvalid.php
│ │ ├── AnnotationTargetAll.php
│ │ ├── AnnotationTargetAnnotation.php
│ │ ├── AnnotationTargetClass.php
│ │ ├── AnnotationTargetMethod.php
│ │ ├── AnnotationTargetPropertyMethod.php
│ │ ├── AnnotationWithAttributes.php
│ │ ├── AnnotationWithConstants.php
│ │ ├── AnnotationWithEnumProperty.php
│ │ ├── AnnotationWithRequiredAttributes.php
│ │ ├── AnnotationWithRequiredAttributesWithoutConstructor.php
│ │ ├── AnnotationWithTargetSyntaxError.php
│ │ ├── AnnotationWithVarType.php
│ │ ├── Api.php
│ │ ├── ClassDDC1660.php
│ │ ├── ClassNoNamespaceNoComment.php
│ │ ├── ClassOverwritesTrait.php
│ │ ├── ClassThatUsesTraitThatUsesAnotherTrait.php
│ │ ├── ClassThatUsesTraitThatUsesAnotherTraitWithMethods.php
│ │ ├── ClassUsesTrait.php
│ │ ├── ClassWithAnnotationConstantReferenceWithDashes.php
│ │ ├── ClassWithAnnotationEnum.php
│ │ ├── ClassWithAnnotationWithSelfConstantReference.php
│ │ ├── ClassWithAnnotationWithTargetSyntaxError.php
│ │ ├── ClassWithAnnotationWithVarType.php
│ │ ├── ClassWithAtInDescriptionAndAnnotation.php
│ │ ├── ClassWithClassAnnotationOnly.php
│ │ ├── ClassWithClosure.php
│ │ ├── ClassWithConstants.php
│ │ ├── ClassWithEnumAnnotations.php
│ │ ├── ClassWithFullPathUseStatement.php
│ │ ├── ClassWithFullyQualifiedUseStatements.php
│ │ ├── ClassWithIgnoreAnnotation.php
│ │ ├── ClassWithImportedIgnoredAnnotation.php
│ │ ├── ClassWithInvalidAnnotationContainingDashes.php
│ │ ├── ClassWithInvalidAnnotationTargetAtClass.php
│ │ ├── ClassWithInvalidAnnotationTargetAtMethod.php
│ │ ├── ClassWithInvalidAnnotationTargetAtProperty.php
│ │ ├── ClassWithNotRegisteredAnnotationUsed.php
│ │ ├── ClassWithPHPCodeSnifferAnnotation.php
│ │ ├── ClassWithPHPStanGenericsAnnotations.php
│ │ ├── ClassWithPhpCsSuppressAnnotation.php
│ │ ├── ClassWithRequire.php
│ │ ├── ClassWithValidAnnotationTarget.php
│ │ ├── Controller.php
│ │ ├── ControllerWithParentClass.php
│ │ ├── ControllerWithTrait.php
│ │ ├── DifferentNamespacesPerFileWithClassAsFirst.php
│ │ ├── DifferentNamespacesPerFileWithClassAsLast.php
│ │ ├── EmptyInterface.php
│ │ ├── EqualNamespacesPerFileWithClassAsFirst.php
│ │ ├── EqualNamespacesPerFileWithClassAsLast.php
│ │ ├── GlobalNamespacesPerFileWithClassAsFirst.php
│ │ ├── GlobalNamespacesPerFileWithClassAsLast.php
│ │ ├── GroupUseStatement.php
│ │ ├── HereForTesting.php
│ │ ├── IgnoreAnnotationClass.php
│ │ ├── IgnoredNamespaces/
│ │ │ ├── AnnotatedAtClassLevel.php
│ │ │ ├── AnnotatedAtMethodLevel.php
│ │ │ ├── AnnotatedAtPropertyLevel.php
│ │ │ └── AnnotatedWithAlias.php
│ │ ├── InterfaceThatExtendsAnInterface.php
│ │ ├── InterfaceWithConstants.php
│ │ ├── InvalidAnnotationUsageButIgnoredClass.php
│ │ ├── InvalidAnnotationUsageClass.php
│ │ ├── MultipleClassesInFile.php
│ │ ├── MultipleImportsInUseStatement.php
│ │ ├── NamespaceAndClassCommentedOut.php
│ │ ├── NamespaceWithClosureDeclaration.php
│ │ ├── NamespacedSingleClassLOC1000.php
│ │ ├── NoAnnotation.php
│ │ ├── NonNamespacedClass.php
│ │ ├── SingleClassLOC1000.php
│ │ ├── Suit.php
│ │ ├── TraitWithAnnotatedMethod.php
│ │ ├── Traits/
│ │ │ ├── EmptyTrait.php
│ │ │ ├── SecretRouteTrait.php
│ │ │ ├── TraitThatUsesAnotherTrait.php
│ │ │ └── TraitWithSelfConstantReferenceTrait.php
│ │ └── functions.php
│ ├── PhpParserTest.php
│ ├── PsrCachedReaderTest.php
│ ├── ReservedKeywordsClasses.php
│ ├── Ticket/
│ │ ├── DCOM141Test.php
│ │ ├── DCOM55Test.php
│ │ ├── DCOM58Entity.php
│ │ └── DCOM58Test.php
│ └── TopLevelAnnotation.php
├── DoctrineTestCase.php
└── TestInit.php
SYMBOL INDEX (651 symbols across 136 files)
FILE: lib/Doctrine/Common/Annotations/Annotation.php
class Annotation (line 12) | class Annotation
method __construct (line 22) | final public function __construct(array $data)
method __get (line 34) | public function __get(string $name)
method __set (line 48) | public function __set(string $name, $value)
FILE: lib/Doctrine/Common/Annotations/Annotation/Attribute.php
class Attribute (line 11) | final class Attribute
FILE: lib/Doctrine/Common/Annotations/Annotation/Attributes.php
class Attributes (line 11) | final class Attributes
FILE: lib/Doctrine/Common/Annotations/Annotation/Enum.php
class Enum (line 24) | final class Enum
method __construct (line 41) | public function __construct(array $values)
FILE: lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php
class IgnoreAnnotation (line 18) | final class IgnoreAnnotation
method __construct (line 28) | public function __construct(array $values)
FILE: lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php
class NamedArgumentConstructor (line 11) | final class NamedArgumentConstructor
FILE: lib/Doctrine/Common/Annotations/Annotation/Required.php
class Required (line 11) | final class Required
FILE: lib/Doctrine/Common/Annotations/Annotation/Target.php
class Target (line 22) | final class Target
method __construct (line 63) | public function __construct(array $values)
FILE: lib/Doctrine/Common/Annotations/AnnotationException.php
class AnnotationException (line 17) | class AnnotationException extends Exception
method syntaxError (line 24) | public static function syntaxError(string $message)
method semanticalError (line 34) | public static function semanticalError(string $message)
method creationError (line 45) | public static function creationError(string $message, ?Throwable $prev...
method typeError (line 55) | public static function typeError(string $message)
method semanticalErrorConstants (line 65) | public static function semanticalErrorConstants(string $identifier, ?s...
method attributeTypeError (line 81) | public static function attributeTypeError(
method requiredError (line 103) | public static function requiredError(
method enumeratorError (line 126) | public static function enumeratorError(
method optimizerPlusSaveComments (line 144) | public static function optimizerPlusSaveComments()
method optimizerPlusLoadComments (line 152) | public static function optimizerPlusLoadComments()
FILE: lib/Doctrine/Common/Annotations/AnnotationReader.php
class AnnotationReader (line 23) | class AnnotationReader implements Reader
method addGlobalIgnoredName (line 55) | public static function addGlobalIgnoredName(string $name)
method addGlobalIgnoredNamespace (line 63) | public static function addGlobalIgnoredNamespace(string $namespace)
method __construct (line 108) | public function __construct(?DocParser $parser = null)
method getClassAnnotations (line 142) | public function getClassAnnotations(ReflectionClass $class)
method getClassAnnotation (line 155) | public function getClassAnnotation(ReflectionClass $class, $annotation...
method getPropertyAnnotations (line 171) | public function getPropertyAnnotations(ReflectionProperty $property)
method getPropertyAnnotation (line 187) | public function getPropertyAnnotation(ReflectionProperty $property, $a...
method getMethodAnnotations (line 203) | public function getMethodAnnotations(ReflectionMethod $method)
method getMethodAnnotation (line 219) | public function getMethodAnnotation(ReflectionMethod $method, $annotat...
method getFunctionAnnotations (line 237) | public function getFunctionAnnotations(ReflectionFunction $function): ...
method getFunctionAnnotation (line 254) | public function getFunctionAnnotation(ReflectionFunction $function, st...
method getIgnoredAnnotationNames (line 274) | private function getIgnoredAnnotationNames($reflection): array
method getImports (line 295) | private function getImports($reflection): array
method getMethodImports (line 314) | private function getMethodImports(ReflectionMethod $method)
method getPropertyImports (line 340) | private function getPropertyImports(ReflectionProperty $property)
method collectParsingMetadata (line 363) | private function collectParsingMetadata($reflection): void
FILE: lib/Doctrine/Common/Annotations/AnnotationRegistry.php
class AnnotationRegistry (line 8) | final class AnnotationRegistry
method reset (line 17) | public static function reset(): void
method loadAnnotationClass (line 25) | public static function loadAnnotationClass(string $class): bool
FILE: lib/Doctrine/Common/Annotations/DocLexer.php
class DocLexer (line 21) | final class DocLexer extends AbstractLexer
method nextTokenIsAdjacent (line 69) | public function nextTokenIsAdjacent(): bool
method getCatchablePatterns (line 79) | protected function getCatchablePatterns()
method getNonCatchablePatterns (line 91) | protected function getNonCatchablePatterns()
method getType (line 99) | protected function getType(&$value)
FILE: lib/Doctrine/Common/Annotations/DocParser.php
class DocParser (line 55) | final class DocParser
method __construct (line 264) | public function __construct()
method setIgnoredAnnotationNames (line 279) | public function setIgnoredAnnotationNames(array $names)
method setIgnoredAnnotationNamespaces (line 291) | public function setIgnoredAnnotationNamespaces(array $ignoredAnnotatio...
method setIgnoreNotImportedAnnotations (line 301) | public function setIgnoreNotImportedAnnotations(bool $bool)
method addNamespace (line 313) | public function addNamespace(string $namespace)
method setImports (line 331) | public function setImports(array $imports)
method setTarget (line 345) | public function setTarget(int $target)
method parse (line 358) | public function parse(string $input, string $context = '')
method findInitialTokenPosition (line 376) | private function findInitialTokenPosition(string $input): ?int
method match (line 405) | private function match(int $token): bool
method matchAny (line 424) | private function matchAny(array $tokens): bool
method syntaxError (line 439) | private function syntaxError(string $expected, ?array $token = null): ...
method classExists (line 465) | private function classExists(string $fqcn): bool
method collectAnnotationMetadata (line 488) | private function collectAnnotationMetadata(string $name): void
method collectAttributeTypeMetadata (line 626) | private function collectAttributeTypeMetadata(array &$metadata, Attrib...
method Annotations (line 676) | private function Annotations(): array
method Annotation (line 737) | private function Annotation()
method MethodCall (line 1036) | private function MethodCall(): array
method Values (line 1063) | private function Values(): array
method Constant (line 1100) | private function Constant()
method identifierStartsWithBackslash (line 1170) | private function identifierStartsWithBackslash(string $identifier): bool
method identifierEndsWithClassConstant (line 1175) | private function identifierEndsWithClassConstant(string $identifier): ...
method getClassConstantPositionInIdentifier (line 1181) | private function getClassConstantPositionInIdentifier(string $identifier)
method Identifier (line 1191) | private function Identifier(): string
method Value (line 1225) | private function Value()
method PlainValue (line 1244) | private function PlainValue()
method FieldAssignment (line 1301) | private function FieldAssignment(): stdClass
method Arrayx (line 1323) | private function Arrayx(): array
method ArrayEntry (line 1374) | private function ArrayEntry(): array
method isIgnoredAnnotation (line 1400) | private function isIgnoredAnnotation(string $name): bool
method resolvePositionalValues (line 1424) | private function resolvePositionalValues(array $arguments, string $nam...
method instantiateAnnotiation (line 1480) | private function instantiateAnnotiation(string $originalName, string $...
FILE: lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
class ImplicitlyIgnoredAnnotationNames (line 12) | final class ImplicitlyIgnoredAnnotationNames
method __construct (line 175) | private function __construct()
FILE: lib/Doctrine/Common/Annotations/IndexedReader.php
class IndexedReader (line 15) | class IndexedReader implements Reader
method __construct (line 20) | public function __construct(Reader $reader)
method getClassAnnotations (line 28) | public function getClassAnnotations(ReflectionClass $class)
method getClassAnnotation (line 41) | public function getClassAnnotation(ReflectionClass $class, $annotation...
method getMethodAnnotations (line 49) | public function getMethodAnnotations(ReflectionMethod $method)
method getMethodAnnotation (line 62) | public function getMethodAnnotation(ReflectionMethod $method, $annotat...
method getPropertyAnnotations (line 70) | public function getPropertyAnnotations(ReflectionProperty $property)
method getPropertyAnnotation (line 83) | public function getPropertyAnnotation(ReflectionProperty $property, $a...
method __call (line 95) | public function __call(string $method, array $args)
FILE: lib/Doctrine/Common/Annotations/PhpParser.php
class PhpParser (line 17) | final class PhpParser
method parseUseStatements (line 26) | public function parseUseStatements($reflection): array
method getFileContent (line 59) | private function getFileContent(string $filename, $lineNumber)
FILE: lib/Doctrine/Common/Annotations/PsrCachedReader.php
class PsrCachedReader (line 23) | final class PsrCachedReader implements Reader
method __construct (line 40) | public function __construct(Reader $reader, CacheItemPoolInterface $ca...
method getClassAnnotations (line 50) | public function getClassAnnotations(ReflectionClass $class)
method getClassAnnotation (line 66) | public function getClassAnnotation(ReflectionClass $class, $annotation...
method getPropertyAnnotations (line 80) | public function getPropertyAnnotations(ReflectionProperty $property)
method getPropertyAnnotation (line 97) | public function getPropertyAnnotation(ReflectionProperty $property, $a...
method getMethodAnnotations (line 111) | public function getMethodAnnotations(ReflectionMethod $method)
method getMethodAnnotation (line 128) | public function getMethodAnnotation(ReflectionMethod $method, $annotat...
method clearLoadedAnnotations (line 139) | public function clearLoadedAnnotations(): void
method fetchFromCache (line 146) | private function fetchFromCache(
method refresh (line 168) | private function refresh(string $cacheKey, ReflectionClass $class): bool
method getLastModification (line 188) | private function getLastModification(ReflectionClass $class): int
method getTraitLastModificationTime (line 214) | private function getTraitLastModificationTime(ReflectionClass $reflect...
FILE: lib/Doctrine/Common/Annotations/Reader.php
type Reader (line 12) | interface Reader
method getClassAnnotations (line 22) | public function getClassAnnotations(ReflectionClass $class);
method getClassAnnotation (line 35) | public function getClassAnnotation(ReflectionClass $class, $annotation...
method getMethodAnnotations (line 45) | public function getMethodAnnotations(ReflectionMethod $method);
method getMethodAnnotation (line 57) | public function getMethodAnnotation(ReflectionMethod $method, $annotat...
method getPropertyAnnotations (line 67) | public function getPropertyAnnotations(ReflectionProperty $property);
method getPropertyAnnotation (line 79) | public function getPropertyAnnotation(ReflectionProperty $property, $a...
FILE: lib/Doctrine/Common/Annotations/TokenParser.php
class TokenParser (line 26) | class TokenParser
method __construct (line 49) | public function __construct(string $contents)
method next (line 73) | public function next(bool $docCommentIsComment = true)
method parseUseStatement (line 96) | public function parseUseStatement()
method parseUseStatements (line 151) | public function parseUseStatements(string $namespaceName)
method parseNamespace (line 178) | public function parseNamespace()
method parseClass (line 198) | public function parseClass()
FILE: tests/Doctrine/Performance/Common/Annotations/CachedReadPerformanceWithInMemoryBench.php
class CachedReadPerformanceWithInMemoryBench (line 16) | final class CachedReadPerformanceWithInMemoryBench
method initialize (line 24) | public function initialize(): void
method bench (line 34) | public function bench(): void
FILE: tests/Doctrine/Performance/Common/Annotations/DocLexerPerformanceBench.php
class DocLexerPerformanceBench (line 12) | final class DocLexerPerformanceBench
method initialize (line 19) | public function initialize(): void
method benchMethod (line 28) | public function benchMethod(): void
method benchClass (line 37) | public function benchClass(): void
FILE: tests/Doctrine/Performance/Common/Annotations/DocParserPerformanceBench.php
class DocParserPerformanceBench (line 16) | final class DocParserPerformanceBench
method initialize (line 38) | public function initialize(): void
method benchMethodParsing (line 51) | public function benchMethodParsing(): void
method benchClassParsing (line 60) | public function benchClassParsing(): void
FILE: tests/Doctrine/Performance/Common/Annotations/MethodInitializer.php
type MethodInitializer (line 10) | trait MethodInitializer
method initializeMethod (line 21) | public function initializeMethod(): void
FILE: tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithShortCutBench.php
class PhpParserPerformanceWithShortCutBench (line 14) | final class PhpParserPerformanceWithShortCutBench
method initialize (line 22) | public function initialize(): void
method bench (line 32) | public function bench(): void
FILE: tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithoutShortCutBench.php
class PhpParserPerformanceWithoutShortCutBench (line 14) | final class PhpParserPerformanceWithoutShortCutBench
method initialize (line 22) | public function initialize(): void
method bench (line 32) | public function bench(): void
FILE: tests/Doctrine/Performance/Common/Annotations/ReadPerformanceBench.php
class ReadPerformanceBench (line 12) | final class ReadPerformanceBench
method initialize (line 19) | public function initialize(): void
method bench (line 28) | public function bench(): void
FILE: tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php
class AbstractReaderTest (line 21) | abstract class AbstractReaderTest extends TestCase
method ignoreIssues (line 26) | final protected function ignoreIssues(): void
method getReflectionClass (line 31) | public function getReflectionClass(): ReflectionClass
method testAnnotations (line 36) | public function testAnnotations(): void
method testAnnotationsWithValidTargets (line 90) | public function testAnnotationsWithValidTargets(): void
method testAnnotationsWithVarType (line 101) | public function testAnnotationsWithVarType(): void
method testAtInDescription (line 113) | public function testAtInDescription(): void
method testClassWithWithDanglingComma (line 125) | public function testClassWithWithDanglingComma(): void
method testClassWithInvalidAnnotationTargetAtClassDocBlock (line 133) | public function testClassWithInvalidAnnotationTargetAtClassDocBlock():...
method testClassWithWithInclude (line 148) | public function testClassWithWithInclude(): void
method testClassWithInvalidAnnotationTargetAtPropertyDocBlock (line 155) | public function testClassWithInvalidAnnotationTargetAtPropertyDocBlock...
method testClassWithInvalidNestedAnnotationTargetAtPropertyDocBlock (line 173) | public function testClassWithInvalidNestedAnnotationTargetAtPropertyDo...
method testClassWithInvalidAnnotationTargetAtMethodDocBlock (line 191) | public function testClassWithInvalidAnnotationTargetAtMethodDocBlock()...
method testClassWithAnnotationWithTargetSyntaxErrorAtClassDocBlock (line 209) | public function testClassWithAnnotationWithTargetSyntaxErrorAtClassDoc...
method testClassWithAnnotationWithTargetSyntaxErrorAtPropertyDocBlock (line 222) | public function testClassWithAnnotationWithTargetSyntaxErrorAtProperty...
method testClassWithAnnotationWithTargetSyntaxErrorAtMethodDocBlock (line 236) | public function testClassWithAnnotationWithTargetSyntaxErrorAtMethodDo...
method testClassWithPropertyInvalidVarTypeError (line 250) | public function testClassWithPropertyInvalidVarTypeError(): void
method testClassWithMethodInvalidVarTypeError (line 264) | public function testClassWithMethodInvalidVarTypeError(): void
method testClassSyntaxErrorContext (line 279) | public function testClassSyntaxErrorContext(): void
method testMethodSyntaxErrorContext (line 290) | public function testMethodSyntaxErrorContext(): void
method testPropertySyntaxErrorContext (line 301) | public function testPropertySyntaxErrorContext(): void
method testMultipleAnnotationsOnSameLine (line 315) | public function testMultipleAnnotationsOnSameLine(): void
method testNonAnnotationProblem (line 322) | public function testNonAnnotationProblem(): void
method testIncludeIgnoreAnnotation (line 333) | public function testIncludeIgnoreAnnotation(): void
method testImportWithConcreteAnnotation (line 341) | public function testImportWithConcreteAnnotation(): void
method testImportWithInheritance (line 350) | public function testImportWithInheritance(): void
method testImportDetectsNotImportedAnnotation (line 366) | public function testImportDetectsNotImportedAnnotation(): void
method testImportDetectsNonExistentAnnotation (line 380) | public function testImportDetectsNonExistentAnnotation(): void
method testTopLevelAnnotation (line 394) | public function testTopLevelAnnotation(): void
method testIgnoresAnnotationsNotPrefixedWithWhitespace (line 406) | public function testIgnoresAnnotationsNotPrefixedWithWhitespace(): void
method testResetsPhpParserAfterUse (line 428) | public function testResetsPhpParserAfterUse(): void
method testErrorWhenInvalidAnnotationIsUsed (line 470) | public function testErrorWhenInvalidAnnotationIsUsed(): void
method testInvalidAnnotationUsageButIgnoredClass (line 489) | public function testInvalidAnnotationUsageButIgnoredClass(): void
method testInvalidAnnotationButIgnored (line 502) | public function testInvalidAnnotationButIgnored(): void
method testAnnotationEnumeratorException (line 513) | public function testAnnotationEnumeratorException(): void
method testIgnoreFixMeAndUpperCaseToDo (line 552) | public function testIgnoreFixMeAndUpperCaseToDo(): void
method testWillSkipAnnotationsContainingDashes (line 560) | public function testWillSkipAnnotationsContainingDashes(): void
method testWillFailOnAnnotationConstantReferenceContainingDashes (line 571) | public function testWillFailOnAnnotationConstantReferenceContainingDas...
method getReader (line 584) | abstract protected function getReader(): Reader;
class TestParseAnnotationClass (line 590) | class TestParseAnnotationClass
class TestIgnoresNonAnnotationsClass (line 600) | class TestIgnoresNonAnnotationsClass
class TestTopLevelAnnotationClass (line 604) | class TestTopLevelAnnotationClass
class TestNonExistentAnnotationClass (line 613) | class TestNonExistentAnnotationClass
class TestAnnotationNotImportedClass (line 622) | class TestAnnotationNotImportedClass
class TestChildClass (line 631) | class TestChildClass
class TestParentClass (line 640) | class TestParentClass extends TestChildClass
class TestImportWithConcreteAnnotation (line 649) | class TestImportWithConcreteAnnotation
class DummyClass2 (line 661) | class DummyClass2
class NameBar (line 673) | class NameBar extends Annotation
class DummyId (line 677) | class DummyId extends Annotation
class DummyColumn (line 681) | class DummyColumn extends Annotation
class DummyGeneratedValue (line 687) | class DummyGeneratedValue extends Annotation
class DummyAnnotation (line 691) | class DummyAnnotation extends Annotation
class DummyAnnotationWithIgnoredAnnotation (line 700) | class DummyAnnotationWithIgnoredAnnotation extends Annotation
class DummyJoinColumn (line 707) | class DummyJoinColumn extends Annotation
class DummyJoinTable (line 715) | class DummyJoinTable extends Annotation
class DummyClassWithDanglingComma (line 728) | class DummyClassWithDanglingComma
class DummyClassSyntaxError (line 735) | class DummyClassSyntaxError
class DummyClassMethodSyntaxError (line 739) | class DummyClassMethodSyntaxError
method foo (line 744) | public function foo(): void
class DummyClassPropertySyntaxError (line 749) | class DummyClassPropertySyntaxError
class DummyClassNonAnnotationProblem (line 761) | class DummyClassNonAnnotationProblem
class DummyClassWithEmail (line 774) | class DummyClassWithEmail
class DCOM106 (line 783) | class DCOM106
class Name (line 792) | class Name extends Annotation
class Name (line 803) | class Name extends Annotation
FILE: tests/Doctrine/Tests/Common/Annotations/Annotation/TargetTest.php
class TargetTest (line 13) | class TargetTest extends TestCase
method testValidMixedTargets (line 18) | public function testValidMixedTargets(): void
FILE: tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php
class AnnotationReaderTest (line 32) | class AnnotationReaderTest extends AbstractReaderTest
method getReader (line 37) | protected function getReader(?DocParser $parser = null): Reader
method testMethodAnnotationFromTrait (line 42) | public function testMethodAnnotationFromTrait(): void
method testMethodAnnotationFromOverwrittenTrait (line 54) | public function testMethodAnnotationFromOverwrittenTrait(): void
method testPropertyAnnotationFromTrait (line 63) | public function testPropertyAnnotationFromTrait(): void
method testOmitNotRegisteredAnnotation (line 75) | public function testOmitNotRegisteredAnnotation(): void
method testClassAnnotationSupportsSelfAccessorForConstants (line 87) | public function testClassAnnotationSupportsSelfAccessorForConstants():...
method testPropertyAnnotationSupportsSelfAccessorForConstants (line 104) | public function testPropertyAnnotationSupportsSelfAccessorForConstants...
method testMethodAnnotationSupportsSelfAccessorForConstants (line 126) | public function testMethodAnnotationSupportsSelfAccessorForConstants()...
method testClassAnnotationIsIgnored (line 152) | public function testClassAnnotationIsIgnored(): void
method testMethodAnnotationIsIgnored (line 166) | public function testMethodAnnotationIsIgnored(): void
method testPropertyAnnotationIsIgnored (line 180) | public function testPropertyAnnotationIsIgnored(): void
method testAnnotationWithAliasIsIgnored (line 194) | public function testAnnotationWithAliasIsIgnored(): void
method testClassWithFullPathUseStatement (line 204) | public function testClassWithFullPathUseStatement(): void
method testPhpCsSuppressAnnotationIsIgnored (line 222) | public function testPhpCsSuppressAnnotationIsIgnored(): void
method testGloballyIgnoredAnnotationNotIgnored (line 230) | public function testGloballyIgnoredAnnotationNotIgnored(): void
method testPHPCodeSnifferAnnotationsAreIgnored (line 251) | public function testPHPCodeSnifferAnnotationsAreIgnored(): void
method testPHPStanGenericsAnnotationsAreIgnored (line 259) | public function testPHPStanGenericsAnnotationsAreIgnored(): void
method testImportedIgnoredAnnotationIsStillIgnored (line 277) | public function testImportedIgnoredAnnotationIsStillIgnored(): void
method testFunctionsAnnotation (line 285) | public function testFunctionsAnnotation(): void
method testFunctionAnnotation (line 295) | public function testFunctionAnnotation(): void
method testAnnotationWithEnum (line 308) | public function testAnnotationWithEnum(string $property, Suit $expecte...
method provideEnumProperties (line 321) | public function provideEnumProperties(): array
FILE: tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php
class AnnotationRegistryTest (line 9) | class AnnotationRegistryTest extends TestCase
method testClassExistsFallback (line 14) | public function testClassExistsFallback(): void
FILE: tests/Doctrine/Tests/Common/Annotations/AnnotationTest.php
class AnnotationTest (line 11) | final class AnnotationTest extends TestCase
method testMagicGetThrowsBadMethodCallException (line 13) | public function testMagicGetThrowsBadMethodCallException(): void
method testMagicSetThrowsBadMethodCallException (line 30) | public function testMagicSetThrowsBadMethodCallException(): void
FILE: tests/Doctrine/Tests/Common/Annotations/DocLexerTest.php
class DocLexerTest (line 11) | class DocLexerTest extends TestCase
method testMarkerAnnotation (line 13) | public function testMarkerAnnotation(): void
method testScannerTokenizesDocBlockWhitConstants (line 34) | public function testScannerTokenizesDocBlockWhitConstants(): void
method testScannerTokenizesDocBlockWhitInvalidIdentifier (line 126) | public function testScannerTokenizesDocBlockWhitInvalidIdentifier(): void
method testWithinDoubleQuotesVeryVeryLongStringWillNotOverflowPregSplitStackLimit (line 170) | public function testWithinDoubleQuotesVeryVeryLongStringWillNotOverflo...
method testRecognizesDoubleQuotesEscapeSequence (line 182) | public function testRecognizesDoubleQuotesEscapeSequence(): void
method testDoesNotRecognizeFullAnnotationWithDashInIt (line 228) | public function testDoesNotRecognizeFullAnnotationWithDashInIt(): void
method testRecognizesNegativeNumbers (line 267) | public function testRecognizesNegativeNumbers(): void
method expectDocblockTokens (line 289) | private function expectDocblockTokens(string $docBlock, array $expecte...
method testTokenAdjacency (line 309) | public function testTokenAdjacency(): void
method testItReturnsNullWhenThereIsNothingToParse (line 325) | public function testItReturnsNullWhenThereIsNothingToParse(): void
FILE: tests/Doctrine/Tests/Common/Annotations/DocParserTest.php
class DocParserTest (line 33) | class DocParserTest extends TestCase
method testNestedArraysWithNestedAnnotation (line 35) | public function testNestedArraysWithNestedAnnotation(): void
method testBasicAnnotations (line 55) | public function testBasicAnnotations(): void
method testDefaultValueAnnotations (line 148) | public function testDefaultValueAnnotations(): void
method testNamespacedAnnotations (line 170) | public function testNamespacedAnnotations(): void
method testTypicalMethodDocBlock (line 197) | public function testTypicalMethodDocBlock(): void
method testAnnotationWithoutConstructor (line 226) | public function testAnnotationWithoutConstructor(): void
method testAnnotationTarget (line 338) | public function testAnnotationTarget(): void
method getAnnotationVarTypeProviderValid (line 409) | public function getAnnotationVarTypeProviderValid()
method getAnnotationVarTypeProviderInvalid (line 471) | public function getAnnotationVarTypeProviderInvalid(): array
method getAnnotationVarTypeArrayProviderInvalid (line 532) | public function getAnnotationVarTypeArrayProviderInvalid()
method testAnnotationWithVarType (line 586) | public function testAnnotationWithVarType(string $attribute, string $v...
method testAnnotationWithVarTypeError (line 607) | public function testAnnotationWithVarTypeError(
method testAnnotationWithVarTypeArrayError (line 639) | public function testAnnotationWithVarTypeArrayError(
method testAnnotationWithAttributes (line 671) | public function testAnnotationWithAttributes(string $attribute, string...
method testAnnotationWithAttributesError (line 693) | public function testAnnotationWithAttributesError(
method testAnnotationWithAttributesWithVarTypeArrayError (line 725) | public function testAnnotationWithAttributesWithVarTypeArrayError(
method testAnnotationWithRequiredAttributes (line 756) | public function testAnnotationWithRequiredAttributes(): void
method testAnnotationWithRequiredAttributesWithoutConstructor (line 804) | public function testAnnotationWithRequiredAttributesWithoutConstructor...
method testAnnotationEnumeratorException (line 852) | public function testAnnotationEnumeratorException(): void
method testAnnotationEnumeratorLiteralException (line 868) | public function testAnnotationEnumeratorLiteralException(): void
method testAnnotationEnumInvalidTypeDeclarationException (line 885) | public function testAnnotationEnumInvalidTypeDeclarationException(): void
method testAnnotationEnumInvalidLiteralDeclarationException (line 903) | public function testAnnotationEnumInvalidLiteralDeclarationException()...
method getConstantsProvider (line 927) | public function getConstantsProvider(): array
method testSupportClassConstants (line 1042) | public function testSupportClassConstants(string $docblock, $expected)...
method testWithoutConstructorWhenIsNotDefaultValue (line 1056) | public function testWithoutConstructorWhenIsNotDefaultValue(): void
method testWithoutConstructorWhenHasNoProperties (line 1074) | public function testWithoutConstructorWhenHasNoProperties(): void
method testAnnotationTargetSyntaxError (line 1092) | public function testAnnotationTargetSyntaxError(): void
method testAnnotationWithInvalidTargetDeclarationError (line 1111) | public function testAnnotationWithInvalidTargetDeclarationError(): void
method testAnnotationWithTargetEmptyError (line 1139) | public function testAnnotationWithTargetEmptyError(): void
method testRegressionDDC575 (line 1168) | public function testRegressionDDC575(): void
method testAnnotationWithoutClassIsIgnoredWithoutWarning (line 1201) | public function testAnnotationWithoutClassIsIgnoredWithoutWarning(): void
method testIgnoreWholeNamespaces (line 1219) | public function testIgnoreWholeNamespaces($ignoreAnnotationName, $inpu...
method provideTestIgnoreWholeNamespaces (line 1231) | public function provideTestIgnoreWholeNamespaces(): array
method testNotAnAnnotationClassIsIgnoredWithoutWarning (line 1257) | public function testNotAnAnnotationClassIsIgnoredWithoutWarning(): void
method testNotAnAnnotationClassIsIgnoredWithoutWarningWithoutCheating (line 1266) | public function testNotAnAnnotationClassIsIgnoredWithoutWarningWithout...
method testAnnotationDontAcceptSingleQuotes (line 1275) | public function testAnnotationDontAcceptSingleQuotes(): void
method testAnnotationDoesntThrowExceptionWhenAtSignIsNotFollowedByIdentifier (line 1286) | public function testAnnotationDoesntThrowExceptionWhenAtSignIsNotFollo...
method testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation (line 1297) | public function testAnnotationThrowsExceptionWhenAtSignIsNotFollowedBy...
method testAutoloadAnnotation (line 1307) | public function testAutoloadAnnotation(): void
method createTestParser (line 1325) | public function createTestParser(): DocParser
method testSyntaxErrorWithContextDescription (line 1340) | public function testSyntaxErrorWithContextDescription(): void
method testSyntaxErrorWithUnknownCharacters (line 1353) | public function testSyntaxErrorWithUnknownCharacters(): void
method testIgnorePHPDocThrowTag (line 1378) | public function testIgnorePHPDocThrowTag(): void
method testCastInt (line 1399) | public function testCastInt(): void
method testCastNegativeInt (line 1411) | public function testCastNegativeInt(): void
method testCastFloat (line 1423) | public function testCastFloat(): void
method testCastNegativeFloat (line 1435) | public function testCastNegativeFloat(): void
method testSetValuesException (line 1448) | public function testSetValuesException(): void
method testInvalidIdentifierInAnnotation (line 1465) | public function testInvalidIdentifierInAnnotation(): void
method testTrailingCommaIsAllowed (line 1476) | public function testTrailingCommaIsAllowed(): void
method testTabPrefixIsAllowed (line 1488) | public function testTabPrefixIsAllowed(): void
method testDefaultAnnotationValueIsNotOverwritten (line 1502) | public function testDefaultAnnotationValueIsNotOverwritten(): void
method testArrayWithColon (line 1511) | public function testArrayWithColon(): void
method testInvalidContantName (line 1520) | public function testInvalidContantName(): void
method testEmptyArray (line 1531) | public function testEmptyArray(): void
method testKeyHasNumber (line 1540) | public function testKeyHasNumber(): void
method testSupportsEscapedQuotedValues (line 1552) | public function testSupportsEscapedQuotedValues(): void
method testMultiByteAnnotation (line 1567) | public function testMultiByteAnnotation(): void
method testWillNotParseAnnotationSucceededByAnImmediateDash (line 1587) | public function testWillNotParseAnnotationSucceededByAnImmediateDash()...
method testWillParseAnnotationSucceededByANonImmediateDash (line 1594) | public function testWillParseAnnotationSucceededByANonImmediateDash():...
method testNamedArgumentsConstructorAnnotation (line 1604) | public function testNamedArgumentsConstructorAnnotation(): void
method testNamedReorderedArgumentsConstructorAnnotation (line 1616) | public function testNamedReorderedArgumentsConstructorAnnotation(): void
method testNamedArgumentsConstructorAnnotationWithDefaultValue (line 1628) | public function testNamedArgumentsConstructorAnnotationWithDefaultValu...
method testNamedArgumentsConstructorAnnotationWithDefaultProperty (line 1640) | public function testNamedArgumentsConstructorAnnotationWithDefaultProp...
method testNamedArgumentsConstructorAnnotationWithExtraArguments (line 1652) | public function testNamedArgumentsConstructorAnnotationWithExtraArgume...
method testNamedArgumentsConstructorAnnotationWithDefaultPropertyAsArray (line 1664) | public function testNamedArgumentsConstructorAnnotationWithDefaultProp...
method testNamedArgumentsConstructorAnnotationWithDefaultPropertySet (line 1676) | public function testNamedArgumentsConstructorAnnotationWithDefaultProp...
method testNamedArgumentsConstructorAnnotationWithInvalidArguments (line 1687) | public function testNamedArgumentsConstructorAnnotationWithInvalidArgu...
method testNamedArgumentsConstructorAnnotationWithWrongArgumentType (line 1697) | public function testNamedArgumentsConstructorAnnotationWithWrongArgume...
method testAnnotationWithConstructorWithVariadicParamAndExtraNamedArguments (line 1716) | public function testAnnotationWithConstructorWithVariadicParamAndExtra...
method testAnnotationWithConstructorWithVariadicParamAndExtraNamedArgumentsShuffled (line 1733) | public function testAnnotationWithConstructorWithVariadicParamAndExtra...
method testAnnotationWithConstructorWithVariadicParamAndCombinedNamedAndPositionalArguments (line 1750) | public function testAnnotationWithConstructorWithVariadicParamAndCombi...
method testAnnotationWithConstructorWithVariadicParamPassOneNamedArgument (line 1767) | public function testAnnotationWithConstructorWithVariadicParamPassOneN...
method testAnnotationWithConstructorWithVariadicParamPassPositionalArguments (line 1784) | public function testAnnotationWithConstructorWithVariadicParamPassPosi...
method testAnnotationWithConstructorWithVariadicParamNoArgs (line 1804) | public function testAnnotationWithConstructorWithVariadicParamNoArgs()...
method expectExceptionMessageMatches (line 1828) | public function expectExceptionMessageMatches(string $regularExpressio...
class AnotherNamedAnnotation (line 1842) | class AnotherNamedAnnotation
method __construct (line 1851) | public function __construct(string $foo, int $bar = 1234, string $baz ...
method getFoo (line 1858) | public function getFoo(): string
method getBar (line 1863) | public function getBar(): int
method getBaz (line 1868) | public function getBaz(): string
class NamedAnnotationWithArray (line 1878) | class NamedAnnotationWithArray
method __construct (line 1888) | public function __construct(array $foo, int $bar = 1234)
method getFoo (line 1895) | public function getFoo(): array
method getBar (line 1900) | public function getBar(): int
class SomeAnnotationWithConstructorWithVariadicParam (line 1910) | class SomeAnnotationWithConstructorWithVariadicParam
method __construct (line 1912) | public function __construct(string $name, string ...$data)
class SettingsAnnotation (line 1926) | class SettingsAnnotation
method __construct (line 1934) | public function __construct($settings)
class SomeAnnotationClassNameWithoutConstructor (line 1941) | class SomeAnnotationClassNameWithoutConstructor
class SomeAnnotationWithConstructorWithoutParams (line 1951) | class SomeAnnotationWithConstructorWithoutParams
method __construct (line 1953) | public function __construct()
class SomeAnnotationClassNameWithoutConstructorAndProperties (line 1966) | class SomeAnnotationClassNameWithoutConstructorAndProperties
class AnnotationWithInvalidTargetDeclaration (line 1974) | class AnnotationWithInvalidTargetDeclaration
class AnnotationWithTargetEmpty (line 1982) | class AnnotationWithTargetEmpty
class AnnotationExtendsAnnotationTargetAll (line 1987) | class AnnotationExtendsAnnotationTargetAll extends AnnotationTargetAll
class Name (line 1992) | class Name extends Annotation
class Marker (line 1999) | class Marker
class Name (line 2010) | class Name extends Annotation
FILE: tests/Doctrine/Tests/Common/Annotations/DummyClass.php
class DummyClass (line 13) | class DummyClass
method getField1 (line 40) | public function getField1()
method getField3 (line 49) | public function getField3(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AbstractController.php
class AbstractController (line 5) | abstract class AbstractController
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/AnnotWithDefaultValue.php
class AnnotWithDefaultValue (line 6) | class AnnotWithDefaultValue
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Autoload.php
class Autoload (line 8) | class Autoload
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/CanBeAutoLoaded.php
class CanBeAutoLoaded (line 6) | class CanBeAutoLoaded
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/LoadedUsingRegisterFile.php
class LoadedUsingRegisterFile (line 6) | class LoadedUsingRegisterFile
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Param.php
class Param (line 5) | class Param
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Route.php
class Route (line 6) | class Route
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Secure.php
class Secure (line 8) | class Secure
method __construct (line 16) | public function __construct(array $values)
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/ShouldNeverBeLoaded.php
class ShouldNeverBeLoaded (line 6) | class ShouldNeverBeLoaded
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/SingleUseAnnotation.php
class SingleUseAnnotation (line 8) | class SingleUseAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Template.php
class Template (line 6) | class Template
method __construct (line 14) | public function __construct(array $values)
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Version.php
class Version (line 9) | final class Version
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnum.php
class AnnotationEnum (line 9) | final class AnnotationEnum
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumInvalid.php
class AnnotationEnumInvalid (line 9) | final class AnnotationEnumInvalid
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteral.php
class AnnotationEnumLiteral (line 11) | final class AnnotationEnumLiteral
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteralInvalid.php
class AnnotationEnumLiteralInvalid (line 9) | final class AnnotationEnumLiteralInvalid
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAll.php
class AnnotationTargetAll (line 9) | class AnnotationTargetAll
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAnnotation.php
class AnnotationTargetAnnotation (line 9) | final class AnnotationTargetAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetClass.php
class AnnotationTargetClass (line 9) | final class AnnotationTargetClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetMethod.php
class AnnotationTargetMethod (line 9) | final class AnnotationTargetMethod
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetPropertyMethod.php
class AnnotationTargetPropertyMethod (line 9) | final class AnnotationTargetPropertyMethod
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithAttributes.php
class AnnotationWithAttributes (line 24) | final class AnnotationWithAttributes
method __construct (line 29) | public function __construct(array $data)
method getMixed (line 62) | public function getMixed()
method getBoolean (line 70) | public function getBoolean()
method getBool (line 78) | public function getBool()
method getFloat (line 86) | public function getFloat()
method getString (line 94) | public function getString()
method getInteger (line 99) | public function getInteger(): int
method getArray (line 107) | public function getArray()
method getAnnotation (line 115) | public function getAnnotation()
method getArrayOfStrings (line 123) | public function getArrayOfStrings()
method getArrayOfIntegers (line 131) | public function getArrayOfIntegers()
method getArrayOfAnnotations (line 139) | public function getArrayOfAnnotations()
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithConstants.php
class AnnotationWithConstants (line 9) | final class AnnotationWithConstants
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithEnumProperty.php
class AnnotationWithEnumProperty (line 12) | final class AnnotationWithEnumProperty
method __construct (line 14) | public function __construct(
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributes.php
class AnnotationWithRequiredAttributes (line 19) | final class AnnotationWithRequiredAttributes
method __construct (line 24) | public function __construct(array $data)
method getValue (line 40) | public function getValue()
method getAnnot (line 48) | public function getAnnot()
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributesWithoutConstructor.php
class AnnotationWithRequiredAttributesWithoutConstructor (line 9) | final class AnnotationWithRequiredAttributesWithoutConstructor
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithTargetSyntaxError.php
class AnnotationWithTargetSyntaxError (line 9) | final class AnnotationWithTargetSyntaxError
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithVarType.php
class AnnotationWithVarType (line 9) | final class AnnotationWithVarType
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Api.php
class Api (line 9) | class Api
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassDDC1660.php
class ClassDDC1660 (line 9) | class ClassDDC1660
method bar (line 26) | public function bar($param)
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassNoNamespaceNoComment.php
class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment (line 5) | class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassOverwritesTrait.php
class ClassOverwritesTrait (line 7) | class ClassOverwritesTrait
method traitMethod (line 14) | public function traitMethod(): void
class Autoload (line 22) | class Autoload
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassThatUsesTraitThatUsesAnotherTrait.php
class ClassThatUsesTraitThatUsesAnotherTrait (line 11) | class ClassThatUsesTraitThatUsesAnotherTrait
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassThatUsesTraitThatUsesAnotherTraitWithMethods.php
class ClassThatUsesTraitThatUsesAnotherTraitWithMethods (line 8) | class ClassThatUsesTraitThatUsesAnotherTraitWithMethods
method method1 (line 15) | public function method1(): void
method method2 (line 22) | public function method2(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassUsesTrait.php
class ClassUsesTrait (line 7) | class ClassUsesTrait
method someMethod (line 20) | public function someMethod(): void
class Autoload (line 28) | class Autoload
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationConstantReferenceWithDashes.php
class ClassWithAnnotationConstantReferenceWithDashes (line 8) | class ClassWithAnnotationConstantReferenceWithDashes
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationEnum.php
class ClassWithAnnotationEnum (line 7) | class ClassWithAnnotationEnum
method bar (line 18) | public function bar(): void
method invalidMethod (line 31) | public function invalidMethod(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithSelfConstantReference.php
class ClassWithAnnotationWithSelfConstantReference (line 8) | class ClassWithAnnotationWithSelfConstantReference
method classMethod (line 26) | public function classMethod()
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithTargetSyntaxError.php
class ClassWithAnnotationWithTargetSyntaxError (line 10) | class ClassWithAnnotationWithTargetSyntaxError
method bar (line 21) | public function bar(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithVarType.php
class ClassWithAnnotationWithVarType (line 9) | class ClassWithAnnotationWithVarType
method bar (line 20) | public function bar(): void
method invalidMethod (line 33) | public function invalidMethod(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAtInDescriptionAndAnnotation.php
class ClassWithAtInDescriptionAndAnnotation (line 7) | class ClassWithAtInDescriptionAndAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithClassAnnotationOnly.php
class ClassWithClassAnnotationOnly (line 10) | class ClassWithClassAnnotationOnly
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithClosure.php
class ClassWithClosure (line 11) | final class ClassWithClosure
method methodName (line 24) | public function methodName(\Closure $callback)
method getEventsForDate (line 38) | public function getEventsForDate($year, $month, $day)
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithConstants.php
class ClassWithConstants (line 5) | class ClassWithConstants
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithEnumAnnotations.php
class ClassWithEnumAnnotations (line 7) | class ClassWithEnumAnnotations
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithFullPathUseStatement.php
class ClassWithFullPathUseStatement (line 14) | class ClassWithFullPathUseStatement
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithFullyQualifiedUseStatements.php
class ClassWithFullyQualifiedUseStatements (line 10) | class ClassWithFullyQualifiedUseStatements
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithIgnoreAnnotation.php
class ClassWithIgnoreAnnotation (line 8) | class ClassWithIgnoreAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithImportedIgnoredAnnotation.php
class ClassWithImportedIgnoredAnnotation (line 7) | class ClassWithImportedIgnoredAnnotation
method something (line 12) | public function something($foo): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationContainingDashes.php
class ClassWithInvalidAnnotationContainingDashes (line 9) | class ClassWithInvalidAnnotationContainingDashes
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtClass.php
class ClassWithInvalidAnnotationTargetAtClass (line 10) | class ClassWithInvalidAnnotationTargetAtClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtMethod.php
class ClassWithInvalidAnnotationTargetAtMethod (line 10) | class ClassWithInvalidAnnotationTargetAtMethod
method functionName (line 17) | public function functionName($param): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtProperty.php
class ClassWithInvalidAnnotationTargetAtProperty (line 11) | class ClassWithInvalidAnnotationTargetAtProperty
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithNotRegisteredAnnotationUsed.php
class ClassWithNotRegisteredAnnotationUsed (line 8) | class ClassWithNotRegisteredAnnotationUsed
method methodWithNotRegisteredAnnotation (line 15) | public function methodWithNotRegisteredAnnotation()
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPHPCodeSnifferAnnotation.php
class ClassWithPHPCodeSnifferAnnotation (line 9) | class ClassWithPHPCodeSnifferAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPHPStanGenericsAnnotations.php
type WithPHPStanExtendsAnnotations (line 8) | interface WithPHPStanExtendsAnnotations
class ClassWithPHPStanExtendsAnnotationsGeneric (line 15) | class ClassWithPHPStanExtendsAnnotationsGeneric
type GenericPHPStanTrait (line 22) | trait GenericPHPStanTrait
class ClassWithPHPStanGenericsAnnotations (line 31) | class ClassWithPHPStanGenericsAnnotations extends ClassWithPHPStanExtend...
method foo (line 47) | public function foo($array)
method twigTemplateFunctionName (line 55) | public function twigTemplateFunctionName(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPhpCsSuppressAnnotation.php
class ClassWithPhpCsSuppressAnnotation (line 5) | class ClassWithPhpCsSuppressAnnotation
method foo (line 10) | public function foo($parameterWithoutTypehint): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithRequire.php
class ClassWithRequire (line 13) | class ClassWithRequire
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithValidAnnotationTarget.php
class ClassWithValidAnnotationTarget (line 12) | class ClassWithValidAnnotationTarget
method someFunction (line 23) | public function someFunction(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Controller.php
class Controller (line 12) | class Controller
method indexAction (line 20) | public function indexAction(): array
method helloAction (line 31) | public function helloAction(string $name): array
method contactAction (line 42) | public function contactAction(): array
method createObjectIdentity (line 61) | private function createObjectIdentity(ObjectIdentityInterface $oid): void
method createOrRetrieveClassId (line 77) | private function createOrRetrieveClassId($classType)
method createOrRetrieveSecurityIdentityId (line 97) | private function createOrRetrieveSecurityIdentityId(SecurityIdentityIn...
method deleteAccessControlEntries (line 114) | private function deleteAccessControlEntries($oidPK): void
method deleteObjectIdentity (line 124) | private function deleteObjectIdentity($pk): void
method deleteObjectIdentityRelations (line 134) | private function deleteObjectIdentityRelations($pk): void
method regenerateAncestorRelations (line 142) | private function regenerateAncestorRelations(AclInterface $acl): void
method updateFieldAceProperty (line 162) | private function updateFieldAceProperty($name, array $changes): void
method updateAceProperty (line 236) | private function updateAceProperty($name, array $changes): void
method updateAces (line 305) | private function updateAces(\SplObjectStorage $aces): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ControllerWithParentClass.php
class ControllerWithParentClass (line 12) | class ControllerWithParentClass extends AbstractController
method indexAction (line 20) | public function indexAction(): array
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/ControllerWithTrait.php
class ControllerWithTrait (line 13) | class ControllerWithTrait
method indexAction (line 23) | public function indexAction(): array
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsFirst.php
class DifferentNamespacesPerFileWithClassAsFirst (line 7) | class DifferentNamespacesPerFileWithClassAsFirst
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsLast.php
class DifferentNamespacesPerFileWithClassAsLast (line 19) | class DifferentNamespacesPerFileWithClassAsLast
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/EmptyInterface.php
type EmptyInterface (line 5) | interface EmptyInterface
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsFirst.php
class EqualNamespacesPerFileWithClassAsFirst (line 8) | class EqualNamespacesPerFileWithClassAsFirst
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsLast.php
class EqualNamespacesPerFileWithClassAsLast (line 12) | class EqualNamespacesPerFileWithClassAsLast
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsFirst.php
class GlobalNamespacesPerFileWithClassAsFirst (line 8) | class GlobalNamespacesPerFileWithClassAsFirst
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsLast.php
class GlobalNamespacesPerFileWithClassAsLast (line 14) | class GlobalNamespacesPerFileWithClassAsLast
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/GroupUseStatement.php
class GroupUseStatement (line 7) | class GroupUseStatement
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/HereForTesting.php
type HereForTesting (line 7) | interface HereForTesting
method foo (line 12) | public function foo();
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoreAnnotationClass.php
class IgnoreAnnotationClass (line 5) | class IgnoreAnnotationClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtClassLevel.php
class AnnotatedAtClassLevel (line 8) | class AnnotatedAtClassLevel
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtMethodLevel.php
class AnnotatedAtMethodLevel (line 5) | class AnnotatedAtMethodLevel
method test (line 10) | public function test(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtPropertyLevel.php
class AnnotatedAtPropertyLevel (line 5) | class AnnotatedAtPropertyLevel
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedWithAlias.php
class AnnotatedWithAlias (line 7) | class AnnotatedWithAlias
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceThatExtendsAnInterface.php
type InterfaceThatExtendsAnInterface (line 11) | interface InterfaceThatExtendsAnInterface extends EmptyInterface
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceWithConstants.php
type InterfaceWithConstants (line 5) | interface InterfaceWithConstants
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageButIgnoredClass.php
class InvalidAnnotationUsageButIgnoredClass (line 12) | class InvalidAnnotationUsageButIgnoredClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageClass.php
class InvalidAnnotationUsageClass (line 8) | class InvalidAnnotationUsageClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleClassesInFile.php
class AnotherClass (line 8) | class AnotherClass
class MultipleClassesInFile (line 11) | class MultipleClassesInFile
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleImportsInUseStatement.php
class MultipleImportsInUseStatement (line 9) | class MultipleImportsInUseStatement
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceAndClassCommentedOut.php
class NamespaceAndClassCommentedOut (line 19) | class NamespaceAndClassCommentedOut
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceWithClosureDeclaration.php
class NamespaceWithClosureDeclaration (line 13) | class NamespaceWithClosureDeclaration
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespacedSingleClassLOC1000.php
class NamespacedSingleClassLOC1000 (line 5) | class NamespacedSingleClassLOC1000
method test1 (line 36) | public function test1(): string
method test2 (line 61) | public function test2(): string
method test3 (line 86) | public function test3(): string
method test4 (line 111) | public function test4(): string
method test5 (line 136) | public function test5(): string
method test6 (line 161) | public function test6(): string
method test7 (line 186) | public function test7(): string
method test8 (line 211) | public function test8(): string
method test9 (line 236) | public function test9(): string
method test10 (line 261) | public function test10(): string
method test11 (line 286) | public function test11(): string
method test12 (line 311) | public function test12(): string
method test13 (line 336) | public function test13(): string
method test14 (line 361) | public function test14(): string
method test15 (line 386) | public function test15(): string
method test16 (line 411) | public function test16(): string
method test17 (line 436) | public function test17(): string
method test18 (line 461) | public function test18(): string
method test19 (line 486) | public function test19(): string
method test20 (line 511) | public function test20(): string
method test21 (line 536) | public function test21(): string
method test22 (line 561) | public function test22(): string
method test23 (line 586) | public function test23(): string
method test24 (line 611) | public function test24(): string
method test25 (line 636) | public function test25(): string
method test26 (line 661) | public function test26(): string
method test27 (line 686) | public function test27(): string
method test28 (line 711) | public function test28(): string
method test29 (line 736) | public function test29(): string
method test30 (line 761) | public function test30(): string
method test31 (line 786) | public function test31(): string
method test32 (line 811) | public function test32(): string
method test33 (line 836) | public function test33(): string
method test34 (line 861) | public function test34(): string
method test35 (line 886) | public function test35(): string
method test36 (line 911) | public function test36(): string
method test37 (line 936) | public function test37(): string
method test38 (line 961) | public function test38(): string
method test39 (line 986) | public function test39(): string
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/NoAnnotation.php
class NoAnnotation (line 5) | class NoAnnotation
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/NonNamespacedClass.php
class AnnotationsTestsFixturesNonNamespacedClass (line 10) | class AnnotationsTestsFixturesNonNamespacedClass
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php
class SingleClassLOC1000 (line 3) | class SingleClassLOC1000
method test1 (line 34) | public function test1(): string
method test2 (line 59) | public function test2(): string
method test3 (line 84) | public function test3(): string
method test4 (line 109) | public function test4(): string
method test5 (line 134) | public function test5(): string
method test6 (line 159) | public function test6(): string
method test7 (line 184) | public function test7(): string
method test8 (line 209) | public function test8(): string
method test9 (line 234) | public function test9(): string
method test10 (line 259) | public function test10(): string
method test11 (line 284) | public function test11(): string
method test12 (line 309) | public function test12(): string
method test13 (line 334) | public function test13(): string
method test14 (line 359) | public function test14(): string
method test15 (line 384) | public function test15(): string
method test16 (line 409) | public function test16(): string
method test17 (line 434) | public function test17(): string
method test18 (line 459) | public function test18(): string
method test19 (line 484) | public function test19(): string
method test20 (line 509) | public function test20(): string
method test21 (line 534) | public function test21(): string
method test22 (line 559) | public function test22(): string
method test23 (line 584) | public function test23(): string
method test24 (line 609) | public function test24(): string
method test25 (line 634) | public function test25(): string
method test26 (line 659) | public function test26(): string
method test27 (line 684) | public function test27(): string
method test28 (line 709) | public function test28(): string
method test29 (line 734) | public function test29(): string
method test30 (line 759) | public function test30(): string
method test31 (line 784) | public function test31(): string
method test32 (line 809) | public function test32(): string
method test33 (line 834) | public function test33(): string
method test34 (line 859) | public function test34(): string
method test35 (line 884) | public function test35(): string
method test36 (line 909) | public function test36(): string
method test37 (line 934) | public function test37(): string
method test38 (line 959) | public function test38(): string
method test39 (line 984) | public function test39(): string
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/TraitWithAnnotatedMethod.php
type TraitWithAnnotatedMethod (line 7) | trait TraitWithAnnotatedMethod
method traitMethod (line 18) | public function traitMethod(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/EmptyTrait.php
type EmptyTrait (line 5) | trait EmptyTrait
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/SecretRouteTrait.php
type SecretRouteTrait (line 8) | trait SecretRouteTrait
method secretAction (line 16) | public function secretAction(): array
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/TraitThatUsesAnotherTrait.php
type TraitThatUsesAnotherTrait (line 5) | trait TraitThatUsesAnotherTrait
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/TraitWithSelfConstantReferenceTrait.php
type TraitWithSelfConstantReferenceTrait (line 7) | trait TraitWithSelfConstantReferenceTrait
method traitMethod (line 16) | public function traitMethod(): void
FILE: tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php
function foo (line 10) | function foo()
FILE: tests/Doctrine/Tests/Common/Annotations/PhpParserTest.php
class PhpParserTest (line 14) | class PhpParserTest extends TestCase
method testParseClassWithMultipleClassesInFile (line 16) | public function testParseClassWithMultipleClassesInFile(): void
method testParseClassWithMultipleImportsInUseStatement (line 27) | public function testParseClassWithMultipleImportsInUseStatement(): void
method testParseClassWithGroupUseStatement (line 41) | public function testParseClassWithGroupUseStatement(): void
method testParseClassWhenNotUserDefined (line 53) | public function testParseClassWhenNotUserDefined(): void
method testClassFileDoesNotExist (line 59) | public function testClassFileDoesNotExist(): void
method testParseClassWhenClassIsNotNamespaced (line 70) | public function testParseClassWhenClassIsNotNamespaced(): void
method testParseClassWhenClassIsInterface (line 81) | public function testParseClassWhenClassIsInterface(): void
method testClassWithFullyQualifiedUseStatements (line 91) | public function testClassWithFullyQualifiedUseStatements(): void
method testNamespaceAndClassCommentedOut (line 103) | public function testNamespaceAndClassCommentedOut(): void
method testEqualNamespacesPerFileWithClassAsFirst (line 114) | public function testEqualNamespacesPerFileWithClassAsFirst(): void
method testEqualNamespacesPerFileWithClassAsLast (line 125) | public function testEqualNamespacesPerFileWithClassAsLast(): void
method testDifferentNamespacesPerFileWithClassAsFirst (line 136) | public function testDifferentNamespacesPerFileWithClassAsFirst(): void
method testDifferentNamespacesPerFileWithClassAsLast (line 146) | public function testDifferentNamespacesPerFileWithClassAsLast(): void
method testGlobalNamespacesPerFileWithClassAsFirst (line 156) | public function testGlobalNamespacesPerFileWithClassAsFirst(): void
method testGlobalNamespacesPerFileWithClassAsLast (line 167) | public function testGlobalNamespacesPerFileWithClassAsLast(): void
method testNamespaceWithClosureDeclaration (line 178) | public function testNamespaceWithClosureDeclaration(): void
method testIfPointerResetsOnMultipleParsingTries (line 190) | public function testIfPointerResetsOnMultipleParsingTries(): void
method testClassWithClosure (line 212) | public function testClassWithClosure(): void
FILE: tests/Doctrine/Tests/Common/Annotations/PsrCachedReaderTest.php
class PsrCachedReaderTest (line 25) | final class PsrCachedReaderTest extends AbstractReaderTest
method testIgnoresStaleCache (line 30) | public function testIgnoresStaleCache(): void
method testIgnoresStaleCacheWithParentClass (line 41) | public function testIgnoresStaleCacheWithParentClass(): void
method testIgnoresStaleCacheWithTraits (line 53) | public function testIgnoresStaleCacheWithTraits(): void
method testIgnoresStaleCacheWithTraitsThatUseOtherTraits (line 65) | public function testIgnoresStaleCacheWithTraitsThatUseOtherTraits(): void
method testIgnoresStaleCacheWithInterfacesThatExtendOtherInterfaces (line 81) | public function testIgnoresStaleCacheWithInterfacesThatExtendOtherInte...
method testUsesFreshCacheWithTraitsThatUseOtherTraits (line 98) | public function testUsesFreshCacheWithTraitsThatUseOtherTraits(): void
method testPurgeLoadedAnnotations (line 114) | public function testPurgeLoadedAnnotations(): void
method testAvoidCallingFilemtimeTooMuch (line 161) | public function testAvoidCallingFilemtimeTooMuch(): void
method testReaderIsNotHitIfCacheIsFresh (line 214) | public function testReaderIsNotHitIfCacheIsFresh(): void
method testReaderDoesNotCacheIfFileDoesNotExistSoLastModificationCannotBeDetermined (line 231) | public function testReaderDoesNotCacheIfFileDoesNotExistSoLastModifica...
method doTestCacheStale (line 253) | protected function doTestCacheStale(string $className, int $lastCacheM...
method doTestCacheFresh (line 282) | protected function doTestCacheFresh(string $className, int $lastCacheM...
method getReader (line 319) | protected function getReader(): Reader
method createCacheItem (line 327) | private function createCacheItem(string $key, bool $isHit, $value = nu...
FILE: tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM141Test.php
class DCOM141Test (line 13) | class DCOM141Test extends TestCase
method testAnnotationPrefixed (line 15) | public function testAnnotationPrefixed(): void
method testAnnotationNotPrefixed (line 26) | public function testAnnotationNotPrefixed(): void
class DCOM141Annotation (line 41) | class DCOM141Annotation
class DCOM141ConsumerPrefixed (line 50) | class DCOM141ConsumerPrefixed
class DCOM141ConsumerNotPrefixed (line 57) | class DCOM141ConsumerNotPrefixed
FILE: tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM55Test.php
class DCOM55Test (line 14) | class DCOM55Test extends TestCase
method testIssue (line 16) | public function testIssue(): void
method testAnnotation (line 33) | public function testAnnotation(): void
method testParseAnnotationDocblocks (line 43) | public function testParseAnnotationDocblocks(): void
class Dummy (line 56) | class Dummy
class DCOM55Annotation (line 63) | class DCOM55Annotation
class DCOM55Consumer (line 70) | class DCOM55Consumer
FILE: tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php
class Entity (line 6) | class Entity
FILE: tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Test.php
class DCOM58Test (line 19) | class DCOM58Test extends TestCase
method testIssue (line 21) | public function testIssue(): void
method testIssueGlobalNamespace (line 34) | public function testIssueGlobalNamespace(): void
method testIssueNamespaces (line 46) | public function testIssueNamespaces(): void
method testIssueMultipleNamespaces (line 58) | public function testIssueMultipleNamespaces(): void
method testIssueWithNamespacesOrImports (line 71) | public function testIssueWithNamespacesOrImports(): void
class MappedClass (line 85) | class MappedClass
class Entity (line 94) | class Entity
class Entity (line 103) | class Entity
FILE: tests/Doctrine/Tests/Common/Annotations/TopLevelAnnotation.php
class TopLevelAnnotation (line 6) | class TopLevelAnnotation extends Annotation
FILE: tests/Doctrine/Tests/DoctrineTestCase.php
class DoctrineTestCase (line 10) | abstract class DoctrineTestCase extends TestCase
Condensed preview — 163 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (435K chars).
[
{
"path": ".doctrine-project.json",
"chars": 1636,
"preview": "{\n \"active\": false,\n \"name\": \"Annotations\",\n \"slug\": \"annotations\",\n \"docsSlug\": \"doctrine-annotations\",\n "
},
{
"path": ".gitattributes",
"chars": 188,
"preview": "/.* export-ignore\n/tests export-ignore\n/phpbench.json.dist export-ignore\n/phpcs.xml.dist export-ignore\n/phpstan.neon exp"
},
{
"path": ".github/workflows/coding-standards.yml",
"chars": 242,
"preview": "\nname: \"Coding Standards\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\njobs:\n "
},
{
"path": ".github/workflows/composer-lint.yml",
"chars": 299,
"preview": "name: \"Composer Lint\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n paths:\n - \"composer.json\"\n push:\n br"
},
{
"path": ".github/workflows/continuous-integration.yml",
"chars": 420,
"preview": "name: \"Continuous Integration\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\nenv"
},
{
"path": ".github/workflows/documentation.yml",
"chars": 379,
"preview": "name: \"Documentation\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n paths:\n - \".github/workflows/documentati"
},
{
"path": ".github/workflows/release-on-milestone-closed.yml",
"chars": 482,
"preview": "name: \"Automatic Releases\"\n\non:\n milestone:\n types:\n - \"closed\"\n\njobs:\n release:\n name: \"Git tag, release &"
},
{
"path": ".github/workflows/static-analysis.yml",
"chars": 814,
"preview": "\nname: \"Static Analysis\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\njobs:\n p"
},
{
"path": ".gitignore",
"chars": 104,
"preview": "/vendor/\n/composer.lock\n/composer.phar\n/phpbench.json\n/phpunit.xml\n/.phpcs-cache\n/.phpunit.result.cache\n"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "Copyright (c) 2006-2013 Doctrine Project\n\nPermission is hereby granted, free of charge, to any person obtaining a copy o"
},
{
"path": "README.md",
"chars": 1822,
"preview": "⚠️ PHP 8 introduced\n[attributes](https://www.php.net/manual/en/language.attributes.overview.php),\nwhich are a native rep"
},
{
"path": "UPGRADE.md",
"chars": 960,
"preview": "# Upgrade from 1.0.x to 2.0.x\n\n- The `NamedArgumentConstructorAnnotation` has been removed. Use the `@NamedArgumentConst"
},
{
"path": "composer.json",
"chars": 2166,
"preview": "{\n \"name\": \"doctrine/annotations\",\n \"description\": \"Docblock Annotations Parser\",\n \"license\": \"MIT\",\n \"type\""
},
{
"path": "docs/composer.json",
"chars": 67,
"preview": "{\n \"require\": {\n \"doctrine/docs-builder\": \"^1.0\"\n }\n}\n"
},
{
"path": "docs/en/annotations.rst",
"chars": 6860,
"preview": "Handling Annotations\n====================\n\nThere are several different approaches to handling annotations in PHP.\nDoctri"
},
{
"path": "docs/en/custom.rst",
"chars": 10060,
"preview": "Custom Annotation Classes\n=========================\n\nIf you want to define your own annotations, you just have to group "
},
{
"path": "docs/en/index.rst",
"chars": 3075,
"preview": "Getting Started\n===============\n\nDeprecation notice\n------------------\n\nPHP 8 introduced `attributes\n<https://www.php.ne"
},
{
"path": "docs/en/sidebar.rst",
"chars": 75,
"preview": ":orphan:\n\n.. toctree::\n :depth: 3\n\n index\n annotations\n custom\n"
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/Attribute.php",
"chars": 359,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\n/**\n * Annotation that can be used to signal to the parser\n * "
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/Attributes.php",
"chars": 295,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\n/**\n * Annotation that can be used to signal to the parser\n * "
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/Enum.php",
"chars": 1738,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\nuse InvalidArgumentException;\n\nuse function get_class;\nuse fun"
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php",
"chars": 1002,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\nuse RuntimeException;\n\nuse function is_array;\nuse function is_"
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php",
"chars": 249,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\n/**\n * Annotation that indicates that the annotated class shou"
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/Required.php",
"chars": 234,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\n/**\n * Annotation that can be used to signal to the parser\n * "
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation/Target.php",
"chars": 2634,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations\\Annotation;\n\nuse InvalidArgumentException;\n\nuse function array_keys;\nuse fu"
},
{
"path": "lib/Doctrine/Common/Annotations/Annotation.php",
"chars": 1227,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse BadMethodCallException;\n\nuse function sprintf;\n\n/**\n * Annotations cl"
},
{
"path": "lib/Doctrine/Common/Annotations/AnnotationException.php",
"chars": 4262,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse Exception;\nuse Throwable;\n\nuse function get_class;\nuse function getty"
},
{
"path": "lib/Doctrine/Common/Annotations/AnnotationReader.php",
"chars": 11681,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Annotation\\IgnoreAnnotation;\nuse Doctrine"
},
{
"path": "lib/Doctrine/Common/Annotations/AnnotationRegistry.php",
"chars": 857,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse function array_key_exists;\nuse function class_exists;\n\nfinal class An"
},
{
"path": "lib/Doctrine/Common/Annotations/DocLexer.php",
"chars": 3575,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse Doctrine\\Common\\Lexer\\AbstractLexer;\n\nuse function ctype_alpha;\nuse f"
},
{
"path": "lib/Doctrine/Common/Annotations/DocParser.php",
"chars": 49791,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Annotation\\Attribute;\nuse Doctrine\\Common"
},
{
"path": "lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php",
"chars": 5549,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Common\\Annotations;\n\n/**\n * A list of annotations that are implicit"
},
{
"path": "lib/Doctrine/Common/Annotations/IndexedReader.php",
"chars": 2285,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse ReflectionClass;\nuse ReflectionMethod;\nuse ReflectionProperty;\n\nuse f"
},
{
"path": "lib/Doctrine/Common/Annotations/PhpParser.php",
"chars": 2086,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse ReflectionClass;\nuse ReflectionFunction;\nuse SplFileObject;\n\nuse func"
},
{
"path": "lib/Doctrine/Common/Annotations/PsrCachedReader.php",
"chars": 6571,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse Psr\\Cache\\CacheItemPoolInterface;\nuse ReflectionClass;\nuse Reflection"
},
{
"path": "lib/Doctrine/Common/Annotations/Reader.php",
"chars": 2538,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse ReflectionClass;\nuse ReflectionMethod;\nuse ReflectionProperty;\n\n/**\n "
},
{
"path": "lib/Doctrine/Common/Annotations/TokenParser.php",
"chars": 6292,
"preview": "<?php\n\nnamespace Doctrine\\Common\\Annotations;\n\nuse function array_merge;\nuse function count;\nuse function explode;\nuse f"
},
{
"path": "phpbench.json.dist",
"chars": 132,
"preview": "{\n \"bootstrap\": \"tests/Doctrine/Performance/Common/bootstrap.php\",\n \"path\": \"tests/Doctrine/Performance/Common/Ann"
},
{
"path": "phpcs.xml.dist",
"chars": 10221,
"preview": "<?xml version=\"1.0\"?>\n<ruleset\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:noNamespaceSche"
},
{
"path": "phpstan.neon",
"chars": 1257,
"preview": "parameters:\n level: 3\n phpVersion: 80500\n paths:\n - lib\n - tests\n scanFiles:\n - tests/D"
},
{
"path": "phpunit.xml.dist",
"chars": 798,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:noNam"
},
{
"path": "psalm.xml",
"chars": 870,
"preview": "<?xml version=\"1.0\"?>\n<psalm\n errorLevel=\"7\"\n phpVersion=\"8.2\"\n resolveFromConfigFile=\"true\"\n findUnusedBase"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/CachedReadPerformanceWithInMemoryBench.php",
"chars": 905,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Ann"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/DocLexerPerformanceBench.php",
"chars": 721,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Doc"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/DocParserPerformanceBench.php",
"chars": 1762,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Doc"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/MethodInitializer.php",
"chars": 649,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Tests\\Common\\Annotatio"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithShortCutBench.php",
"chars": 758,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Php"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/PhpParserPerformanceWithoutShortCutBench.php",
"chars": 698,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Php"
},
{
"path": "tests/Doctrine/Performance/Common/Annotations/ReadPerformanceBench.php",
"chars": 580,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Performance\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Ann"
},
{
"path": "tests/Doctrine/Performance/Common/bootstrap.php",
"chars": 360,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nrequire_once __DIR__ . '/../../../../vendor/autoload.php';\nrequire_once __DIR__ . '/../"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php",
"chars": 28713,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Annotation;\nuse Doctrine\\Common\\Ann"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Annotation/TargetTest.php",
"chars": 913,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Annotation;\n\nuse Doctrine\\Common\\Annotations\\Annotation\\Target;\nuse P"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php",
"chars": 12585,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\AnnotationReader;\nuse Doctrine\\Comm"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php",
"chars": 501,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\AnnotationRegistry;\nuse Doctrine\\Te"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/AnnotationTest.php",
"chars": 1187,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse BadMethodCallException;\nuse Doctrine\\Common\\Annotations\\Annotat"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/DocLexerTest.php",
"chars": 10033,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\DocLexer;\nuse Doctrine\\Common\\Lexer"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/DocParserTest.php",
"chars": 66796,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\Annotation;\nuse Doctrine\\Common\\Ann"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/DummyClass.php",
"chars": 1111,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\n/**\n * A description of this class.\n *\n * Let's see if the parser r"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AbstractController.php",
"chars": 100,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nabstract class AbstractController\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/AnnotWithDefaultValue.php",
"chars": 172,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass AnnotWithDefaultValue\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Autoload.php",
"chars": 115,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/**\n * @Annotation\n */\nclass Autoload\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/CanBeAutoLoaded.php",
"chars": 118,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass CanBeAutoLoaded\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/LoadedUsingRegisterFile.php",
"chars": 126,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass LoadedUsingRegisterFil"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Param.php",
"chars": 89,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\nclass Param\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Route.php",
"chars": 202,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass Route\n{\n /** @var s"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Secure.php",
"chars": 427,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\nuse function is_string;\n\n/** @Annotation */\ncla"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/ShouldNeverBeLoaded.php",
"chars": 122,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass ShouldNeverBeLoaded\n{\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/SingleUseAnnotation.php",
"chars": 126,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/**\n * @Annotation\n */\nclass SingleUseAnnotatio"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Template.php",
"chars": 305,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/** @Annotation */\nclass Template\n{\n /** @va"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Version.php",
"chars": 143,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation;\n\n/**\n * @Annotation\n * @Target(\"PROPERTY\")\n */\nf"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnum.php",
"chars": 322,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumInvalid.php",
"chars": 244,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteral.php",
"chars": 669,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationE"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteralInvalid.php",
"chars": 572,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAll.php",
"chars": 255,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nclass AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAnnotation.php",
"chars": 279,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target({ \"ANNOTATION\" })\n */\nfinal "
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetClass.php",
"chars": 265,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"CLASS\")\n */\nfinal class Ann"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetMethod.php",
"chars": 267,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"METHOD\")\n */\nfinal class An"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetPropertyMethod.php",
"chars": 291,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target({ \"METHOD\", \"PROPERTY\" })\n *"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithAttributes.php",
"chars": 3045,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithConstants.php",
"chars": 283,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithEnumProperty.php",
"chars": 299,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"A"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributes.php",
"chars": 1019,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributesWithoutConstructor.php",
"chars": 377,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithTargetSyntaxError.php",
"chars": 147,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(@)\n */\nfinal class Annotatio"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithVarType.php",
"chars": 777,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @Annotation\n * @Target(\"ALL\")\n */\nfinal class Annot"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Api.php",
"chars": 166,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * This class is not an annotation\n * It's a class bui"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassDDC1660.php",
"chars": 457,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @since 2.0\n * @version $Id: SomeEntityClass.php 509"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassNoNamespaceNoComment.php",
"chars": 157,
"preview": "<?php\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationTargetClass;\n\nclass Doctrine_Tests_Common_Annotations_Fi"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassOverwritesTrait.php",
"chars": 357,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Bar2\\Autoload;\n\nclas"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassThatUsesTraitThatUsesAnotherTrait.php",
"chars": 326,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassThatUsesTraitThatUsesAnotherTraitWithMethods.php",
"chars": 497,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassUsesTrait.php",
"chars": 423,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Bar\\Autoload;\n\nclass"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationConstantReferenceWithDashes.php",
"chars": 228,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationEnum.php",
"chars": 538,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationE"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithSelfConstantReference.php",
"chars": 810,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Traits\\Trai"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithTargetSyntaxError.php",
"chars": 436,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationW"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithVarType.php",
"chars": 800,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAtInDescriptionAndAnnotation.php",
"chars": 703,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithClassAnnotationOnly.php",
"chars": 219,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithClosure.php",
"chars": 1396,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithConstants.php",
"chars": 346,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass ClassWithConstants\n{\n public const SOME_VALUE = "
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithEnumAnnotations.php",
"chars": 303,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass ClassWithEnumAnnotations\n{"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithFullPathUseStatement.php",
"chars": 346,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * The leading \\ is intentional to ensure that code us"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithFullyQualifiedUseStatements.php",
"chars": 316,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse\n \\Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annota"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithIgnoreAnnotation.php",
"chars": 235,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @ignoreAnnotation(\"IgnoreAnnotationClass\")\n */\nclas"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithImportedIgnoredAnnotation.php",
"chars": 269,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationContainingDashes.php",
"chars": 173,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @please-do-not-parse-me\n * @AlsoDoNot\\Parse-me\n */\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtClass.php",
"chars": 345,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtMethod.php",
"chars": 386,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtProperty.php",
"chars": 490,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithNotRegisteredAnnotationUsed.php",
"chars": 343,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @package Doctrine\\Tests\\Common\\Annotations\\Fixtures"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPHPCodeSnifferAnnotation.php",
"chars": 174,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @codingStandardsIgnoreStart\n * @codingStandardsIgno"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPHPStanGenericsAnnotations.php",
"chars": 932,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @template T\n */\ninterface WithPHPStanExtendsAnnotat"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithPhpCsSuppressAnnotation.php",
"chars": 282,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass ClassWithPhpCsSuppressAnnotation\n{\n /**\n * @p"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithRequire.php",
"chars": 300,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n// Include a class named Api\nrequire_once __DIR__ . '/Api."
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithValidAnnotationTarget.php",
"chars": 743,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\AnnotationT"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Controller.php",
"chars": 11416,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ControllerWithParentClass.php",
"chars": 516,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/ControllerWithTrait.php",
"chars": 582,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsFirst.php",
"chars": 423,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures {\n\n use Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annota"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsLast.php",
"chars": 422,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Foo {\n\n use Doctrine\\Tests\\Common\\Annotations\\Fixtures\\An"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/EmptyInterface.php",
"chars": 91,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\ninterface EmptyInterface\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsFirst.php",
"chars": 367,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsLast.php",
"chars": 366,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsFirst.php",
"chars": 313,
"preview": "<?php\n\nnamespace {\n\n use Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\Route;\n use Doctrine\\Tests\\Common\\A"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsLast.php",
"chars": 312,
"preview": "<?php\n\nnamespace {\n\n use Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\Secure;\n\n}\n\nnamespace {\n\n use Doctr"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/GroupUseStatement.php",
"chars": 191,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/HereForTesting.php",
"chars": 216,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoreAnnotationClass.php",
"chars": 94,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass IgnoreAnnotationClass\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtClassLevel.php",
"chars": 171,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IgnoredNamespaces;\n\n/**\n * @SomeClassAnnotationNamespace\\Sub"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtMethodLevel.php",
"chars": 230,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IgnoredNamespaces;\n\nclass AnnotatedAtMethodLevel\n{\n /**\n "
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedAtPropertyLevel.php",
"chars": 229,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IgnoredNamespaces;\n\nclass AnnotatedAtPropertyLevel\n{\n /**"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoredNamespaces/AnnotatedWithAlias.php",
"chars": 252,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IgnoredNamespaces;\n\nuse SomePropertyAnnotationNamespace\\Subn"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceThatExtendsAnInterface.php",
"chars": 293,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/InterfaceWithConstants.php",
"chars": 231,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\ninterface InterfaceWithConstants\n{\n public const SOME_V"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageButIgnoredClass.php",
"chars": 255,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageClass.php",
"chars": 125,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\n/**\n * @NoAnnotation\n */\nclass InvalidAnnotationUsageClass"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleClassesInFile.php",
"chars": 249,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleImportsInUseStatement.php",
"chars": 238,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse\n Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotat"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceAndClassCommentedOut.php",
"chars": 600,
"preview": "<?php\n\n// namespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Fo"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceWithClosureDeclaration.php",
"chars": 345,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespacedSingleClassLOC1000.php",
"chars": 26949,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass NamespacedSingleClassLOC1000\n{\n public const TEST"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/NoAnnotation.php",
"chars": 85,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nclass NoAnnotation\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/NonNamespacedClass.php",
"chars": 232,
"preview": "<?php\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\Route;\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\A"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php",
"chars": 26884,
"preview": "<?php\n\nclass SingleClassLOC1000\n{\n public const TEST1 = 1234567890;\n public const TEST2 = 1234567890;\n public c"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Suit.php",
"chars": 171,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nenum Suit\n{\n case Hearts;\n "
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/TraitWithAnnotatedMethod.php",
"chars": 330,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/EmptyTrait.php",
"chars": 90,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Traits;\n\ntrait EmptyTrait\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/SecretRouteTrait.php",
"chars": 409,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Traits;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Anno"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/TraitThatUsesAnotherTrait.php",
"chars": 125,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Traits;\n\ntrait TraitThatUsesAnotherTrait\n{\n use EmptyTrai"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/Traits/TraitWithSelfConstantReferenceTrait.php",
"chars": 417,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Traits;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Anno"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php",
"chars": 173,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Fixtures;\n\nuse Doctrine\\Tests\\Common\\Annotations\\Fixtures\\Annotation\\"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/PhpParserTest.php",
"chars": 8565,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Doctrine\\Common\\Annotations\\PhpParser;\nuse PHPUnit\\Framework\\Te"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/PsrCachedReaderTest.php",
"chars": 11758,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\nuse Closure;\nuse Doctrine\\Common\\Annotations\\AnnotationReader;\nuse "
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/ReservedKeywordsClasses.php",
"chars": 158,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations;\n\n/** @Annotation */\nclass True\n{\n}\n\n/** @Annotation */\nclass False\n{"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM141Test.php",
"chars": 1356,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Ticket;\n\nuse Doctrine\\Common\\Annotations\\AnnotationReader;\nuse PHPUni"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM55Test.php",
"chars": 1956,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Ticket;\n\nuse Doctrine\\Common\\Annotations\\AnnotationException;\nuse Doc"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php",
"chars": 97,
"preview": "<?php\n// Some class named Entity in the global namespace\n/**\n * @Annotation\n */\nclass Entity\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Test.php",
"chars": 2676,
"preview": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Annotations\\Ticket;\n\nuse Doctrine\\Common\\Annotations\\AnnotationReader;\nuse Doctri"
},
{
"path": "tests/Doctrine/Tests/Common/Annotations/TopLevelAnnotation.php",
"chars": 119,
"preview": "<?php\n\nuse Doctrine\\Common\\Annotations\\Annotation;\n\n/** @Annotation */\nclass TopLevelAnnotation extends Annotation\n{\n}\n"
},
{
"path": "tests/Doctrine/Tests/DoctrineTestCase.php",
"chars": 179,
"preview": "<?php\n\nnamespace Doctrine\\Tests;\n\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * Base testcase class for all Doctrine testcases"
},
{
"path": "tests/Doctrine/Tests/TestInit.php",
"chars": 483,
"preview": "<?php\n\n/*\n * This file bootstraps the test environment.\n */\nerror_reporting(E_ALL);\n\n// register silently failing autolo"
}
]
About this extraction
This page contains the full source code of the doctrine/annotations GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 163 files (392.5 KB), approximately 101.1k tokens, and a symbol index with 651 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.