-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding methods for sequential processing and filtering of class reflections #1475
base: 6.52.x
Are you sure you want to change the base?
Changes from all commits
cc18671
2cd9196
a04eaaf
348d53a
27361f3
fa0920b
a20df62
595328d
ae01007
7d67b06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
# example of class iterator operation | ||
|
||
require_once __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use Roave\BetterReflection\BetterReflection; | ||
use Roave\BetterReflection\Reflector\DefaultReflector; | ||
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator; | ||
use Roave\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceFilter\FileSizeFilter; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceFilter\AggregateFilter; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceFilter\SourceContainsFilter; | ||
|
||
$directories = [__DIR__ . '/../../src', __DIR__ . '/../../demo']; | ||
|
||
$sourceLocator = new AggregateSourceLocator([ | ||
new DirectoriesSourceLocator( | ||
$directories, | ||
(new BetterReflection())->astLocator() | ||
), | ||
]); | ||
|
||
$reflector = new DefaultReflector($sourceLocator); | ||
|
||
$classReflections = $reflector->iterateClasses( | ||
new AggregateFilter( | ||
new FileSizeFilter(10000), | ||
new SourceContainsFilter(['class ReflectionMethod', 'class ReflectionClass']) | ||
), | ||
); | ||
|
||
print iterator_count($classReflections); | ||
|
||
$classReflections = $reflector->iterateClasses(new SourceContainsFilter(['class MyClass'])); | ||
|
||
print iterator_count($classReflections); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,14 +4,15 @@ | |
|
||
namespace Roave\BetterReflection\Reflector; | ||
|
||
use Generator; | ||
use Roave\BetterReflection\Identifier\Identifier; | ||
use Roave\BetterReflection\Identifier\IdentifierType; | ||
use Roave\BetterReflection\Reflection\ReflectionClass; | ||
use Roave\BetterReflection\Reflection\ReflectionConstant; | ||
use Roave\BetterReflection\Reflection\ReflectionFunction; | ||
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceFilter\SourceFilter; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceLocator; | ||
|
||
use function assert; | ||
|
||
final class DefaultReflector implements Reflector | ||
|
@@ -56,6 +57,23 @@ public function reflectAllClasses(): iterable | |
return $allClasses; | ||
} | ||
|
||
/** | ||
* Iterate classes available in the scope specified by the SourceLocator. | ||
* | ||
* @return Generator<ReflectionClass> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Overall, I'd say that we can change the default Yes, it's a breaking change, but it's a good one to have |
||
*/ | ||
public function iterateClasses(?SourceFilter $filter = null): Generator | ||
{ | ||
/** @var Generator<ReflectionClass> $allClasses */ | ||
$allClasses = $this->sourceLocator->iterateIdentifiersByType( | ||
$this, | ||
new IdentifierType(IdentifierType::IDENTIFIER_CLASS), | ||
$filter, | ||
); | ||
|
||
yield from $allClasses; | ||
} | ||
Comment on lines
+65
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think |
||
|
||
/** | ||
* Create a ReflectionFunction for the specified $functionName. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
namespace Roave\BetterReflection\SourceLocator\Type; | ||
|
||
use Generator; | ||
use Roave\BetterReflection\Identifier\Identifier; | ||
use Roave\BetterReflection\Identifier\IdentifierType; | ||
use Roave\BetterReflection\Reflection\Reflection; | ||
|
@@ -12,6 +13,7 @@ | |
use Roave\BetterReflection\SourceLocator\Ast\Exception\ParseToAstFailure; | ||
use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator; | ||
use Roave\BetterReflection\SourceLocator\Located\LocatedSource; | ||
use Roave\BetterReflection\SourceLocator\Type\SourceFilter\SourceFilter; | ||
|
||
abstract class AbstractSourceLocator implements SourceLocator | ||
{ | ||
|
@@ -68,4 +70,31 @@ final public function locateIdentifiersByType(Reflector $reflector, IdentifierTy | |
$identifierType, | ||
); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* @throws ParseToAstFailure | ||
*/ | ||
public function iterateIdentifiersByType( | ||
Reflector $reflector, | ||
IdentifierType $identifierType, | ||
?SourceFilter $sourceFilter, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mentioned elsewhere: this is IMO something that shouldn't be given at call-time, but should be instead intrinsic of the way you are looking at a codebase (effectively, a |
||
): Generator { | ||
$locatedSource = $this->createLocatedSource(new Identifier(Identifier::WILDCARD, $identifierType)); | ||
|
||
if (!$locatedSource || $sourceFilter?->isAllowed( | ||
$locatedSource->getSource(), | ||
$locatedSource->getName(), | ||
$locatedSource->getFileName(), | ||
) === false) { | ||
return; | ||
} | ||
|
||
yield from $this->astLocator->findReflectionsOfType( | ||
$reflector, | ||
$locatedSource, | ||
$identifierType, | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I see, you attempted to design this code so that you could push a runtime filter down the stack, into the lookup operation, for example, to select all classes in a specific namespace.
I understand the rationale, but am a bit conflicted on the design, and the attempt to create a structured filter here, which is extremely risky due to the internals of source locators being squishy, whilst this interface being
public
.I don't have a clear design/suggestion for you right now, but I think a first attempt should be done at creating a single
FilteringSourceLocator
that can wrap a$next
one and apply filtering at that level, operating on aLocatedSource|null
: that would make the use-case more specific, and would isolate the filtering change onto a single implementation.