ContextFactory does not collect use statements in class traits
Closed this issue · 2 comments
Hi everyone!
TypeResolver/src/Types/ContextFactory.php
Line 114 in 48a0c8f
Example:
<?php
namespace Acme\Example;
use Acme\Other\Example\Bar;
trait FooTrait {
/**
* @var Bar
*/
public $bar;
}
<?php
namespace Acme\Example;
use Acme\Example\FooTrait;
class Foo {
use FooTrait;
}
When collecting namespaces the Foo::$bar property will be described as \Acme\Example\Bar instead of \Acme\Other\Example\Bar.
The solution would be to also process T_USE tokens after the parser hits T_CLASS token. Additionally trait files should be loaded and processed against nested traits :)
TypeResolver/src/Types/ContextFactory.php
Lines 126 to 154 in 48a0c8f
This library detects types per file so it would be impossible to discover the types defined in a trait. We are doing this for performance and collision reasons. So even if we are parsing the body for the class we would not be able to load the right trait since we don't know where it is located.
Beside that the use case you are describing is a way more complicated use case. since the class Foo
will only contain the property $bar
at runtime. If you want this kind of information please have a look at https://github.com/phpdocumentor/reflection which is collecting the information of each phpfile and reflects all elements that are defined in each file. If you provide multiple files it will be able to create a full tree of your projects namespaces including all classes. traits and there properties.
In the end the class Foo
will never be reflected with the poperty $bar
since it is not defined in the class but only available at runtime. Which is out of scope of the library. But it can provide you the information you need if you interpret the results in the correct way.
Hopefully this helps you to find a solution for the project you are working on.
Thx for detailed explanation @jaapio !
I'll definitely have a look at phpdocumentor/reflection.
There is a quick workaround though. I can force unused use statements in class Foo file:
<?php
namespace Acme\Example;
use Acme\Example\FooTrait;
use Acme\Other\Example\Bar; // <-- HERE
class Foo {
use FooTrait;
}
And the Foo::$bar type will be annotated properly. However, unsed use statements will probably be removed by static code analyzers or code cleanup tools so not a solution for a long run :\
Cheers