Description
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Symfony version | 3.4.3 |
The class Symfony\Component\Routing\Loader\AnnotationFileLoader does not properly parse a file containing a trait which define an anonymous class.
Here is a minimal example that trigger the bug:
namespace AppBundle\Controller;
trait TestTrait {
protected function createClass() {
return new class {
//We need one T_STRING token after the class keyword to trigger the bug
public function f() {}
};
}
}
If I put that in a the file src/AppBundle/Controller/TestTrait.php of my symfony project (which is scanned for annotation by the router component), I get a ReflectionException:
Class AppBundle\Controller\f does not exist
Exception trace:
ReflectionClass->__construct() at /home/renaud/sites/Bruxelles_formation/vendor/symfony/symfony/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php:62
Symfony\Component\Routing\Loader\AnnotationDirectoryLoader->load() at /home/renaud/sites/Bruxelles_formation/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php:153
Symfony\Component\Config\Loader\FileLoader->doImport() at /home/renaud/sites/Bruxelles_formation/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php:90
Symfony\Component\Config\Loader\FileLoader->import() at /home/renaud/sites/Bruxelles_formation/vendor/symfony/symfony/src/Symfony/Component/Routing/Loader/YamlFileLoader.php:161
[...]
Looking at the source of the findClass()
method (which gives the class name in AnnotationDirectoryLoader
at line 61), it looks for the first class keyword in the file.
This is generally fine for a file that actually define a class, because even if we have anonymous classes inside the file, it would stop at the actual class definition.
But for a trait it continue looking until it eventually find a class
keyword, and if it does the first T_STRING token found after is supposed to be the class name.
I am not sure what a proper fix could be.
The ideal fix would be to detect that the class
keyword is actually used in an anonymous class context and then ignore it. It is the case if there is a new
keyword before class
, but there may be some valid tokens between them (at least comments), so I don't know if this can be done in a simple and reliable way.
A quick fix would be to detect the trait
keyword and stop parsing the file if it is found, not sure if it is acceptable. And it would miss other case where an anonymous class is used outside of an actual class (like in a file that only define functions).
For the time being, my workaround is to put the traits outside of the directories scanned by the router.