Skip to content

Commit

Permalink
Refactor ClassesInDirectories to remove BetterReflection dependency
Browse files Browse the repository at this point in the history
Replaced BetterReflection with native PHP directory and token functions for class discovery in `ClassesInDirectories.php`. This simplifies the dependency tree by removing the `roave/better-reflection` package from `composer.json`.
  • Loading branch information
koriym committed Nov 2, 2024
1 parent 718bcf2 commit c0a8013
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 38 deletions.
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"ray/aop": "^2.10.4",
"ray/aura-sql-module": "^1.12.0",
"ray/di": "^2.14",
"roave/better-reflection": "^4.12 || ^5.6 || ^6.25",
"symfony/polyfill-php81": "^1.24"
},
"require-dev": {
Expand Down
107 changes: 70 additions & 37 deletions src/ClassesInDirectories.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,84 @@
namespace Ray\MediaQuery;

use Generator;
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Reflector\DefaultReflector;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\AutoloadSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator;

use function assert;
use function class_exists;
use function interface_exists;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;

final class ClassesInDirectories
{
/**
* get a list of all classes in the given directories.
*
* Based on: https://github.com/Roave/BetterReflection/blob/396a07c9d276cb9ffba581b24b2dadbb542d542e/demo/parsing-whole-directory/example2.php.
*
* @param list<string> $directories

Check failure on line 15 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Incorrect annotations group.

Check failure on line 15 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Incorrect annotations group.
*
* @return Generator<int, class-string>
*
* This function code is taken from https://github.com/WyriHaximus/php-list-classes-in-directory/blob/master/src/functions.php
* and modified for roave/better-reflection 5.x
*
* @see https://github.com/WyriHaximus/php-list-classes-in-directory
* @psalm-suppress MixedReturnTypeCoercion
* @phpstan-ignore-next-line/
*/
public static function list(string ...$directories): iterable
public static function list(string ...$directories): Generator

Check failure on line 18 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / sa / PHPStan

PHPDoc tag @param for parameter $directories with type array<int, string> is incompatible with native type string.

Check failure on line 18 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / sa / PHPStan

PHPDoc tag @param for parameter $directories with type array<int, string> is incompatible with native type string.
{
foreach ($directories as $directory) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory)

Check failure on line 22 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Multi-line function calls must have a trailing comma after the last parameter.

Check failure on line 22 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Multi-line function calls must have a trailing comma after the last parameter.
);

foreach ($iterator as $file) {

Check failure on line 25 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / sa / Psalm

MixedAssignment: Unable to determine the type that $file is being assigned to

Check failure on line 25 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / sa / Psalm

MixedAssignment: Unable to determine the type that $file is being assigned to
if (! $file instanceof SplFileInfo) {
continue;
}

if ($file->getExtension() !== 'php') {
continue;
}

$className = self::getClassFromFile($file->getRealPath());
if ($className === null) {
continue;
}

if (class_exists($className) || interface_exists($className)) {

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Use early exit to reduce code nesting.

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function class_exists() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function interface_exists() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Use early exit to reduce code nesting.

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function class_exists() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 39 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function interface_exists() should not be referenced via a fallback global name, but via a use statement.
yield $className;
}
}
}
}

private static function getClassFromFile(string $filePath): ?string

Check failure on line 46 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Usage of short nullable type hint in "?string" is disallowed.

Check failure on line 46 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Usage of short nullable type hint in "?string" is disallowed.
{
/** @var list<string> $directories */
$sourceLocator = new AggregateSourceLocator([
new DirectoriesSourceLocator(
$directories,
(new BetterReflection())->astLocator(),
),
// ↓ required to autoload parent classes/interface from another directory than /src (e.g. /vendor)
new AutoloadSourceLocator((new BetterReflection())->astLocator()),
]);

foreach ((new DefaultReflector($sourceLocator))->reflectAllClasses() as $class) {
$className = $class->getName();
assert(class_exists($className) || interface_exists($className));

yield $className;
$content = file_get_contents($filePath);

Check failure on line 48 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function file_get_contents() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 48 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function file_get_contents() should not be referenced via a fallback global name, but via a use statement.
if ($content === false) {
return null;
}

$namespace = '';
$class = '';
$tokens = token_get_all($content);

Check failure on line 55 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function token_get_all() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 55 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function token_get_all() should not be referenced via a fallback global name, but via a use statement.
$count = count($tokens);

Check failure on line 56 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function count() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 56 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Function count() should not be referenced via a fallback global name, but via a use statement.

for ($i = 0; $i < $count; $i++) {
if (!isset($tokens[$i][0])) {

Check failure on line 59 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Expected 1 space after NOT operator; 0 found

Check failure on line 59 in src/ClassesInDirectories.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Expected 1 space after NOT operator; 0 found
continue;
}

if ($tokens[$i][0] === T_NAMESPACE) {
for ($j = $i + 1; $j < $count; $j++) {
if ($tokens[$j][0] === T_NAME_QUALIFIED) {
$namespace = $tokens[$j][1];
break;
}
}
}

if ($tokens[$i][0] === T_CLASS || $tokens[$i][0] === T_INTERFACE) {
for ($j = $i + 1; $j < $count; $j++) {
if ($tokens[$j][0] === T_STRING) {
$class = $tokens[$j][1];
break 2;
}
}
}
}

if ($class === '') {
return null;
}

return $namespace ? $namespace . '\\' . $class : $class;
}
}

0 comments on commit c0a8013

Please sign in to comment.