diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ddaff30..e41d5fd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: true matrix: - php: [ 8.2 ] + php: [ 8.2, 8.3, 8.4 ] steps: - name: Checkout code @@ -50,7 +50,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.4 extensions: dom, curl, libxml, mbstring, zip tools: composer:v2 coverage: none @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: true matrix: - php: [ 8.2 ] + php: [ 8.2, 8.3, 8.4 ] steps: - name: Checkout code uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index ebbc9f8..0a4149b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ !.idea/fileTemplates # Dependencies +/benchmark/typhoon/vendor/ +/benchmark/typhoon/composer.lock /vendor/ /composer.lock diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 225095b..14d193b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,4 +5,5 @@ Here are some of the commands that you'll need: - run tests with phpunit: `docker run -it --rm -v $PWD:/app -w /app chialab/php-dev:8.2 composer test` - reformat using php-cs-fixer: `docker run -it --rm -v $PWD:/app -w /app chialab/php-dev:8.2 composer cs-fix` - analyse with phpstan: `docker run -it --rm -v $PWD:/app -w /app chialab/php-dev:8.2 composer phpstan` - - benchmark: ` docker run -it --rm -v $"($env.PWD):/app" -v $"($env.PWD)/misc/opcache.ini:/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini" -w /app chialab/php-dev:8.2` + - benchmark: `docker run -it --rm -v $"($env.PWD):/app" -v $"($env.PWD)/misc/opcache.ini:/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini" -w /app chialab/php-dev:8.2` + - typhoon benchmark: `docker run -it --rm -v $"($env.PWD)/benchmark/typhoon:/app" -v $"($env.PWD)/misc/opcache.ini:/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini" -v $"($env.PWD)/tests/Stubs:/app/tests/Stubs" -w /app chialab/php-dev:8.2 composer benchmark` diff --git a/README.md b/README.md index f08dfa9..d310879 100644 --- a/README.md +++ b/README.md @@ -64,37 +64,67 @@ full Native PHP reflection and Roave/BetterReflection are generally faster, but mind this also has to parse AST and DocBlocks to extract generics and types. Still, I believe it to be fast enough to actually be used in production if you enable the cache. -Here is a reference benchmark, performed on an M1 MacBook Pro with OpCache: +Here is a reference benchmark, performed on an M1 MacBook Pro with OpCache and JIT: ``` +~/Projects/Personal/good-php/reflection> docker run -it --rm -v $"($env.PWD):/app" -v $"($env.PWD)/misc/opcache.ini:/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini" -w /app chialab/php-dev:8.2 composer benchmark +> Composer\Config::disableProcessTimeout +> vendor/bin/phpbench run tests/Benchmark +PHPBench (1.4.0) running benchmarks... #standwithukraine +with configuration file: /app/phpbench.json +with PHP version 8.2.27, xdebug ✔, opcache ✔ + \Tests\Benchmark\ThisReflectionBench - benchWarmWithMemoryCache # only name....I49 - Mo0.011ms (±15.06%) [3.856mb / 4.779mb] - benchWarmWithMemoryCache # everything...I49 - Mo0.137ms (±5.25%) [9.970mb / 9.988mb] - benchWarmWithFileCache # only name......I49 - Mo0.047ms (±11.98%) [6.917mb / 6.958mb] - benchWarmWithFileCache # everything.....I49 - Mo0.172ms (±4.64%) [13.097mb / 13.114mb] - benchCold # only name...................I199 - Mo2.384ms (±12.80%) [2.143mb / 4.779mb] - benchCold # everything..................I199 - Mo2.506ms (±18.67%) [2.276mb / 4.779mb] - benchColdIncludingInitializationAndAuto.I199 - Mo74.279ms (±18.78%) [2.092mb / 4.779mb] - benchColdIncludingInitializationAndAuto.I199 - Mo72.901ms (±4.37%) [2.188mb / 4.779mb] + benchWarmWithMemoryCache # only name....I49 - Mo0.009ms (±4.68%) [2.149mb / 4.911mb] + benchWarmWithMemoryCache # everything...I49 - Mo0.038ms (±4.53%) [3.487mb / 4.911mb] + benchWarmWithFileCache # only name......I49 - Mo0.033ms (±2.12%) [2.229mb / 4.911mb] + benchWarmWithFileCache # everything.....I49 - Mo0.068ms (±3.02%) [6.352mb / 6.385mb] + benchCold # only name...................I199 - Mo2.519ms (±15.44%) [2.166mb / 4.911mb] + benchCold # everything..................I199 - Mo2.701ms (±12.87%) [2.267mb / 4.911mb] + benchColdIncludingInitializationAndAuto.I199 - Mo72.206ms (±3.00%) [2.132mb / 4.911mb] + benchColdIncludingInitializationAndAuto.I199 - Mo77.608ms (±10.01%) [2.217mb / 4.911mb] -\Tests\Benchmark\BetterReflectionBench +\Tests\Benchmark\NativeReflectionBench - benchWarmWithMemoryCache # only name....I49 - Mo0.005ms (±8.26%) [3.085mb / 4.779mb] - benchWarmWithMemoryCache # everything...I49 - Mo0.016ms (±5.70%) [3.093mb / 4.779mb] - benchCold # only name...................I199 - Mo1.693ms (±6.13%) [3.104mb / 4.779mb] - benchCold # everything..................I199 - Mo2.299ms (±14.67%) [3.116mb / 4.779mb] - benchColdIncludingInitializationAndAuto.I199 - Mo59.184ms (±5.79%) [3.084mb / 4.779mb] - benchColdIncludingInitializationAndAuto.I199 - Mo63.590ms (±18.52%) [3.092mb / 4.779mb] + benchWarm # only name...................I49 - Mo0.001ms (±13.48%) [575.552kb / 4.910mb] + benchWarm # everything..................I49 - Mo0.002ms (±9.02%) [575.616kb / 4.910mb] + benchCold # only name...................I199 - Mo0.005ms (±39.39%) [576.376kb / 4.911mb] + benchCold # everything..................I199 - Mo0.013ms (±32.23%) [576.376kb / 4.911mb] -\Tests\Benchmark\NativeReflectionBench +\Tests\Benchmark\BetterReflectionBench - benchWarm # only name...................I49 - Mo0.001ms (±9.11%) [517.504kb / 4.778mb] - benchWarm # everything..................I49 - Mo0.004ms (±6.08%) [517.568kb / 4.778mb] - benchCold # only name...................I199 - Mo0.009ms (±55.16%) [518.488kb / 4.779mb] - benchCold # everything..................I199 - Mo0.022ms (±23.29%) [518.488kb / 4.779mb] + benchWarmWithMemoryCache # only name....I49 - Mo0.003ms (±4.81%) [3.096mb / 4.911mb] + benchWarmWithMemoryCache # everything...I49 - Mo0.010ms (±3.97%) [3.137mb / 4.911mb] + benchCold # only name...................I199 - Mo1.265ms (±17.02%) [3.116mb / 4.911mb] + benchCold # everything..................I199 - Mo1.797ms (±13.45%) [3.103mb / 4.911mb] + benchColdIncludingInitializationAndAuto.I199 - Mo58.146ms (±9.89%) [3.095mb / 4.911mb] + benchColdIncludingInitializationAndAuto.I199 - Mo61.066ms (±3.91%) [3.074mb / 4.911mb] + +Subjects: 9, Assertions: 0, Failures: 0, Errors: 0 +~/Projects/Personal/good-php/reflection> docker run -it --rm -v $"($env.PWD)/benchmark/typhoon:/app" -v $"($env.PWD)/misc/opcache.ini:/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini" -v $"($env.PWD)/tests/Stubs:/app/tests/Stubs" -w /app chialab/php-dev:8.2 composer benchmark riant everything +> Composer\Config::disableProcessTimeout +> vendor/bin/phpbench run src +PHPBench (1.4.0) running benchmarks... #standwithukraine +with configuration file: /app/phpbench.json +with PHP version 8.2.27, xdebug ✔, opcache ✔ + +\TyphoonReflectionBench + + benchWarmWithMemoryCache # only name....I49 - Mo0.006ms (±10.36%) [1.975mb / 4.841mb] + benchWarmWithMemoryCache # everything...I49 - Mo0.018ms (±3.40%) [2.042mb / 4.841mb] + benchWarmWithFileCache # only name......I49 - Mo0.135ms (±2.14%) [2.031mb / 4.841mb] + benchWarmWithFileCache # everything.....I49 - Mo0.148ms (±2.74%) [2.033mb / 4.841mb] + benchCold # only name...................I199 - Mo6.987ms (±9.90%) [1.904mb / 4.840mb] + benchCold # everything..................I199 - Mo7.288ms (±10.82%) [1.971mb / 4.840mb] + benchColdIncludingInitializationAndAuto.I199 - Mo96.134ms (±8.41%) [1.900mb / 4.841mb] + benchColdIncludingInitializationAndAuto.I199 - Mo96.932ms (±11.23%) [1.967mb / 4.841mb] + +Subjects: 4, Assertions: 0, Failures: 0, Errors: 0 ``` +With cache, it's the slowest of them all. But the difference is in __nanoseconds__. + ### How does it work Unfortunately, it's not as simple as just using the native reflection and parsing some diff --git a/benchmark/typhoon/composer.json b/benchmark/typhoon/composer.json new file mode 100644 index 0000000..533b239 --- /dev/null +++ b/benchmark/typhoon/composer.json @@ -0,0 +1,22 @@ +{ + "scripts": { + "benchmark": [ + "Composer\\Config::disableProcessTimeout", + "vendor/bin/phpbench run src" + ] + }, + "require-dev": { + "typhoon/reflection": "^0.4.4", + "typhoon/phpstorm-reflection-stubs": "^0.4.4", + "phpbench/phpbench": "^1.4", + "typhoon/opcache": "^0.2.1", + "symfony/cache": "^7.2", + "illuminate/support": "^12.0" + }, + "autoload-dev": { + "psr-4": { + "Benchmark\\Typhoon\\": "src/", + "Tests\\Stubs\\": "tests/Stubs/" + } + } +} diff --git a/benchmark/typhoon/phpbench.json b/benchmark/typhoon/phpbench.json new file mode 100644 index 0000000..8cba4bf --- /dev/null +++ b/benchmark/typhoon/phpbench.json @@ -0,0 +1,6 @@ +{ + "$schema":"./vendor/phpbench/phpbench/phpbench.schema.json", + "runner.bootstrap": "vendor/autoload.php", + "runner.time_unit": "ms", + "runner.progress_summary_variant_format": "label(\"Mo\") ~ display_as_time(mode(variant.time.avg), coalesce(subject.time_unit,\"time\"), subject.time_precision, subject.time_mode) ~ \n\" (\" ~ rstdev(variant.time.avg) ~ \")\" ~ \" [\" ~ mode(variant.mem.final) as memory ~ \" / \" ~ mode(variant.mem.peak) as memory ~ \"]\"" +} diff --git a/benchmark/typhoon/src/TyphoonReflectionBench.php b/benchmark/typhoon/src/TyphoonReflectionBench.php new file mode 100644 index 0000000..6693744 --- /dev/null +++ b/benchmark/typhoon/src/TyphoonReflectionBench.php @@ -0,0 +1,109 @@ +reflector = TyphoonReflector::build(); + } + + public function setUpWithFileCache(): void + { + $freshOpcache = new FreshCache(new TyphoonOPcache(sys_get_temp_dir() . '/' . Str::random(32))); + $freshOpcache->clear(); + + $this->reflector = TyphoonReflector::build(cache: $freshOpcache); + } + + public function setUpWithoutCache(): void + { + $this->reflector = TyphoonReflector::build(cache: new Psr16Cache(new NullAdapter())); + } + + #[Iterations(50)] + #[Revs(200)] + #[Warmup(1)] + #[BeforeMethods('setUpWithMemoryCache')] + #[ParamProviders('hardnessProvider')] + public function benchWarmWithMemoryCache(array $params): void + { + $this->callMethods($params['hardness'], $this->reflector->reflectClass(ClassStub::class)); + } + + #[Iterations(50)] + #[Revs(200)] + #[Warmup(1)] + #[BeforeMethods('setUpWithFileCache')] + #[ParamProviders('hardnessProvider')] + public function benchWarmWithFileCache(array $params): void + { + $this->callMethods($params['hardness'], $this->reflector->reflectClass(ClassStub::class)); + } + + #[Iterations(200)] + #[Warmup(1)] + #[BeforeMethods('setUpWithoutCache')] + #[ParamProviders('hardnessProvider')] + public function benchCold(array $params): void + { + $this->callMethods($params['hardness'], $this->reflector->reflectClass(ClassStub::class)); + } + + #[Iterations(200)] + #[ParamProviders('hardnessProvider')] + public function benchColdIncludingInitializationAndAutoLoad(array $params): void + { + $this->setUpWithoutCache(); + + $this->callMethods($params['hardness'], $this->reflector->reflectClass(ClassStub::class)); + } + + public function hardnessProvider(): iterable + { + yield 'only name' => [ + 'hardness' => ['name' => true, 'everything' => false], + ]; + + yield 'everything' => [ + 'hardness' => ['name' => true, 'everything' => true], + ]; + } + + private function callMethods(array $hardness, ClassReflection $reflection): void + { + if ($hardness['name']) { + $reflection->file(); + (string) $reflection->id; + } + + if ($hardness['everything']) { + $reflection->attributes(); + $reflection->templates(); + $reflection->parentName(); + // $reflection->implements(); + // $reflection->uses(); + $reflection->properties(); + $reflection->methods(); + // $reflection->isAnonymous(); + $reflection->isAbstract(); + $reflection->isFinal(); + // $reflection->isBuiltIn(); + } + } +} diff --git a/composer.json b/composer.json index 6da0efb..6c43062 100644 --- a/composer.json +++ b/composer.json @@ -10,32 +10,34 @@ ], "require": { "php": ">=8.2", - "tenantcloud/php-standard": "^2.0", - "symfony/var-exporter": "^7.0", - "phpstan/phpdoc-parser": "^1.26", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "nikic/php-parser": "^5.0", + "phpstan/phpdoc-parser": "^2.1", "psr/simple-cache": "^3.0", "symfony/cache": "^7.0", - "webmozart/assert": "^1.11", - "nikic/php-parser": "^5.0" + "symfony/var-exporter": "^7.0", + "webmozart/assert": "^1.11" }, "require-dev": { - "pestphp/pest": "^2.8", - "php-cs-fixer/shim": "~3.21.3", - "tenantcloud/php-cs-fixer-rule-sets": "~3.1.0", - "phpstan/phpstan": "~1.10.21", + "pestphp/pest": "^3.0", + "php-cs-fixer/shim": "~3.80.0", + "tenantcloud/php-cs-fixer-rule-sets": "~3.4.1", + "phpstan/phpstan": "~2.1.0", "phake/phake": "^4.2", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-webmozart-assert": "^2.0", + "phpstan/phpstan-mockery": "^2.0", "phpbench/phpbench": "^1.2", "roave/better-reflection": "^6.36", - "dms/phpunit-arraysubset-asserts": "^0.5.0", "jiripudil/phpstan-sealed-classes": "^1.1" }, "autoload": { "psr-4": { "GoodPhp\\Reflection\\": "src/" - } + }, + "files": [ + "src/Util/Lazy/functions.php" + ] }, "autoload-dev": { "psr-4": { @@ -55,6 +57,7 @@ "minimum-stability": "stable", "prefer-stable": true, "config": { + "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true } diff --git a/misc/opcache.ini b/misc/opcache.ini index 850eb84..4587f52 100644 --- a/misc/opcache.ini +++ b/misc/opcache.ini @@ -1,2 +1,11 @@ zend_extension=opcache.so opcache.enable_cli=1 +opcache.jit_buffer_size=64M +opcache.jit=1235 +opcache.revalidate_freq=0 +opcache.validate_timestamps=0 +opcache.max_accelerated_files=10000 +opcache.memory_consumption=192 +opcache.max_wasted_percentage=10 +opcache.interned_strings_buffer=16 +xdebug.mode=off diff --git a/phpstan.neon b/phpstan.neon index 54b2986..d7982bc 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,7 +10,22 @@ parameters: paths: - src + reportUnmatchedIgnoredErrors: false ignoreErrors: + - '#Call-site variance of covariant object in generic type ReflectionClass in PHPDoc tag \@param for parameter \$reflection is redundant, template type T of object of class ReflectionClass has the same variance.#' + # PHPStan doesn't understand that Collection::values() produces a list + - '#Method .*::.* should return list<(.*)> but returns array<(int, )?\1>.#i' + - '#Parameter [\$|\#].* of .* expects list<(.*)>(|.*)?, (array|non-empty-array)<(int, )?\1> given.#i' + - '#Property .*::\$.* \(list<(.*)>\) does not accept (array|non-empty-array)<(int, )?\1>.#i' + - '#Parameter \#1 \$type of method GoodPhp\\Reflection\\NativePHPDoc\\Definition\\NativePHPDoc\\Native\\NativeTypeMapper::map\(\) expects list\|ReflectionType\|string, array given.#i' + - '#Method GoodPhp\\Reflection\\NativePHPDoc\\Definition\\NativePHPDoc\\File\\ClassLikeContextParsingVisitor::methods\(\) should return list but returns array.#i' + # Missing template types + - '#Method GoodPhp\\Reflection\\Type\\Template\\TypeParameterMap::toArguments\(\) should return list but returns array.#i' + # The return types are correct, but PHPStan complains even if types are specified explicitly. + - '#Method GoodPhp\\Reflection\\NativePHPDoc\\Reflection\\Npd.*Reflection::.* should return list> but returns array>.#i' + # Intentionally left as nullable. If there was a solid way of checking if a property is initialized + # in PHP, then these would in fact be assigned nulls if definitions contain null types. + - '#Property GoodPhp\\Reflection\\NativePHPDoc\\Reflection\\Npd.*::.* \(GoodPhp\\Reflection\\Type\\(NamedType|Type)\|null\) is never assigned null so it can be removed from the property type.#i' # It is in fact nullable. Probably a bug in PHPStan. - '#Using nullsafe property access \"\?->excludedTraitMethods\" on left side of \?\? is unnecessary. Use -> instead.#i' # It's not a native type. Bug in PHPStan. @@ -18,14 +33,12 @@ parameters: # Bug with inherited readonly properties - '#Readonly property [a-z\\]+::\$[a-z0-9]+ is assigned outside of the constructor.#i' - '#Class [a-z\\]+ has an uninitialized readonly property \$[a-z0-9]+\. Assign it in the constructor.#i' - # Wrongly inferred types - - '#Property GoodPhp\\Reflection\\Type\\Combinatorial\\(IntersectionType|UnionType)::\$types \(Illuminate\\Support\\Collection\) does not accept Illuminate\\Support\\Collection<\(int\|string\), mixed>.#i' # We expect proper error handling, in which case file_get_contents() will never return `false` - message: '#Parameter \#1 \$code of method PhpParser\\Parser::parse\(\) expects string, string\|false given\.#i' path: 'src/NativePHPDoc/Definition/NativePHPDoc/File/FileContextParser.php' - - message: '#Parameter \#2 \$aliases of class GoodPhp\\Reflection\\NativePHPDoc\\Definition\\NativePHPDoc\\File\\FileClassLikeContext\\TraitUse constructor expects Illuminate\\Support\\Collection, Illuminate\\Support\\Collection given\.#i' + message: '#Parameter \#2 \$aliases of class GoodPhp\\Reflection\\NativePHPDoc\\Definition\\NativePHPDoc\\File\\FileClassLikeContext\\TraitUse constructor expects list, list\|int<1, max>\|null}> given\.#i' path: 'src/NativePHPDoc/Definition/NativePHPDoc/File/ClassLikeContextParsingVisitor.php' # This, again, I'm not sure how to approach - diff --git a/src/NativePHPDoc/Definition/BuiltIns/BuiltInCoreDefinitionProvider.php b/src/NativePHPDoc/Definition/BuiltIns/BuiltInCoreDefinitionProvider.php index a6bfd81..738fd55 100644 --- a/src/NativePHPDoc/Definition/BuiltIns/BuiltInCoreDefinitionProvider.php +++ b/src/NativePHPDoc/Definition/BuiltIns/BuiltInCoreDefinitionProvider.php @@ -20,11 +20,10 @@ use GoodPhp\Reflection\Type\Special\VoidType; use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; -use Illuminate\Support\Collection; -use TenantCloud\Standard\Lazy\Lazy; +use GoodPhp\Reflection\Util\Lazy\Lazy; use Traversable; -use function TenantCloud\Standard\Lazy\lazy; +use function GoodPhp\Reflection\Util\Lazy\lazy; class BuiltInCoreDefinitionProvider implements DefinitionProvider { @@ -38,22 +37,22 @@ public function __construct() qualifiedName: Countable::class, fileName: null, builtIn: true, - typeParameters: new Collection(), - extends: new Collection(), - methods: new Collection([ + typeParameters: [], + extends: [], + methods: [ new MethodDefinition( name: 'count', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: PrimitiveType::integer(), ), - ]) + ] )), ArrayAccess::class => lazy(fn () => new InterfaceTypeDefinition( qualifiedName: ArrayAccess::class, fileName: null, builtIn: true, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'TKey', variadic: false, @@ -66,13 +65,13 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::INVARIANT ), - ]), - extends: new Collection(), - methods: new Collection([ + ], + extends: [], + methods: [ new MethodDefinition( name: 'offsetExists', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'offset', type: new TemplateType( @@ -80,13 +79,13 @@ public function __construct() ), hasDefaultValue: false, ), - ]), + ], returnType: PrimitiveType::boolean(), ), new MethodDefinition( name: 'offsetGet', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'offset', type: new TemplateType( @@ -94,7 +93,7 @@ public function __construct() ), hasDefaultValue: false, ), - ]), + ], returnType: new NullableType( new TemplateType( name: 'TValue', @@ -103,8 +102,8 @@ public function __construct() ), new MethodDefinition( name: 'offsetSet', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'offset', type: new NullableType( @@ -121,13 +120,13 @@ public function __construct() ), hasDefaultValue: false, ), - ]), + ], returnType: VoidType::get(), ), new MethodDefinition( name: 'offsetUnset', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'offset', type: new TemplateType( @@ -135,16 +134,16 @@ public function __construct() ), hasDefaultValue: false, ), - ]), + ], returnType: VoidType::get(), ), - ]) + ] )), Traversable::class => lazy(fn () => new InterfaceTypeDefinition( qualifiedName: Traversable::class, fileName: null, builtIn: true, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'TKey', variadic: false, @@ -157,25 +156,25 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::COVARIANT, ), - ]), - extends: new Collection([ - new NamedType('iterable', new Collection([ + ], + extends: [ + new NamedType('iterable', [ new TemplateType( name: 'TKey', ), new TemplateType( name: 'TValue', ), - ])), - ]), - methods: new Collection([ + ]), + ], + methods: [ new MethodDefinition( name: 'count', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: PrimitiveType::integer(), ), - ]) + ] )), Closure::class => lazy(fn () => new ClassTypeDefinition( qualifiedName: Closure::class, @@ -184,7 +183,7 @@ public function __construct() anonymous: false, final: true, abstract: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'TReturn', variadic: false, @@ -197,10 +196,10 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::CONTRAVARIANT ), - ]), + ], extends: null, - implements: new Collection([ - new NamedType('callable', new Collection([ + implements: [ + new NamedType('callable', [ new TemplateType( name: 'TReturn', ), @@ -209,11 +208,11 @@ public function __construct() name: 'TParameter', ) ), - ])), - ]), + ]), + ], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection(), + properties: [], + methods: [], )), ]; } diff --git a/src/NativePHPDoc/Definition/BuiltIns/BuiltInSpecialsDefinitionProvider.php b/src/NativePHPDoc/Definition/BuiltIns/BuiltInSpecialsDefinitionProvider.php index e42fe7a..3769430 100644 --- a/src/NativePHPDoc/Definition/BuiltIns/BuiltInSpecialsDefinitionProvider.php +++ b/src/NativePHPDoc/Definition/BuiltIns/BuiltInSpecialsDefinitionProvider.php @@ -8,10 +8,9 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; -use Illuminate\Support\Collection; -use TenantCloud\Standard\Lazy\Lazy; +use GoodPhp\Reflection\Util\Lazy\Lazy; -use function TenantCloud\Standard\Lazy\lazy; +use function GoodPhp\Reflection\Util\Lazy\lazy; class BuiltInSpecialsDefinitionProvider implements DefinitionProvider { @@ -29,10 +28,9 @@ public function __construct() )), 'int' => lazy(fn () => new SpecialTypeDefinition( 'int', - new Collection(), - new Collection([ + superTypes: [ new NamedType('float'), - ]) + ] )), 'float' => lazy(fn () => new SpecialTypeDefinition( 'float', @@ -42,7 +40,7 @@ public function __construct() )), 'iterable' => lazy(fn () => new SpecialTypeDefinition( 'iterable', - new Collection([ + [ new TypeParameterDefinition( name: 'TKey', variadic: false, @@ -55,11 +53,11 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::COVARIANT ), - ]) + ] )), 'array' => lazy(fn () => new SpecialTypeDefinition( 'array', - new Collection([ + [ new TypeParameterDefinition( name: 'TKey', variadic: false, @@ -72,21 +70,21 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::INVARIANT ), - ]), - new Collection([ - new NamedType('iterable', new Collection([ + ], + [ + new NamedType('iterable', [ new TemplateType( name: 'TKey', ), new TemplateType( name: 'TValue', ), - ])), - ]) + ]), + ] )), 'callable' => lazy(fn () => new SpecialTypeDefinition( 'callable', - new Collection([ + [ new TypeParameterDefinition( name: 'TReturn', variadic: false, @@ -99,7 +97,7 @@ public function __construct() upperBound: null, variance: TemplateTypeVariance::CONTRAVARIANT ), - ]) + ] )), ]; } diff --git a/src/NativePHPDoc/Definition/Fallback/FallbackDefinitionProvider.php b/src/NativePHPDoc/Definition/Fallback/FallbackDefinitionProvider.php index 0dea0aa..56053ca 100644 --- a/src/NativePHPDoc/Definition/Fallback/FallbackDefinitionProvider.php +++ b/src/NativePHPDoc/Definition/Fallback/FallbackDefinitionProvider.php @@ -8,7 +8,7 @@ class FallbackDefinitionProvider implements DefinitionProvider { /** - * @param DefinitionProvider[] $providers + * @param list $providers */ public function __construct( private readonly array $providers diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/ClassLikeContextParsingVisitor.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/ClassLikeContextParsingVisitor.php index 43cdb7b..e4e78c6 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/ClassLikeContextParsingVisitor.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/ClassLikeContextParsingVisitor.php @@ -25,25 +25,22 @@ class ClassLikeContextParsingVisitor extends NodeVisitorAbstract { - /** @var Collection */ - public Collection $classLikes; + /** @var array */ + public array $classLikes = []; - /** @var Collection */ - public Collection $anonymousClassLikes; + /** @var array */ + public array $anonymousClassLikes = []; public function __construct( private readonly NameResolver $nameResolverVisitor, - ) { - $this->classLikes = new Collection(); - $this->anonymousClassLikes = new Collection(); - } + ) {} public function enterNode(Node $node) { if ( - !$node instanceof Node\Stmt\Class_ && + !$node instanceof Class_ && !$node instanceof Interface_ && - !$node instanceof Node\Stmt\Trait_ && + !$node instanceof Trait_ && !$node instanceof Enum_ ) { return null; @@ -65,7 +62,7 @@ traitsUses: $this->traitsUses($node), $this->classLikes[(string) $node->namespacedName] = $context; } else { Assert::keyNotExists( - $this->anonymousClassLikes->all(), + $this->anonymousClassLikes, $node->getStartLine(), 'Only one anonymous class-like can be defined within a single line due to PHPs limitations.' ); @@ -77,30 +74,32 @@ traitsUses: $this->traitsUses($node), } /** - * @return Collection> + * @return array> */ - public function excludedTraitMethods(ClassLike $classLike): Collection + public function excludedTraitMethods(ClassLike $classLike): array { + /** @var array> */ return collect($classLike->getTraitUses()) ->flatMap( fn (Node\Stmt\TraitUse $traitUseNode) => collect($traitUseNode->adaptations)->whereInstanceOf(Precedence::class) ) - ->reduce(function (Collection $carry, Precedence $precedence) { + ->reduce(function (array $carry, Precedence $precedence) { foreach ($precedence->insteadof as $insteadof) { - /** @var Collection> $carry */ - $carry[(string) $insteadof] ??= collect(); - $carry[(string) $insteadof]->push((string) $precedence->method); + /** @var array> $carry */ + $carry[(string) $insteadof] ??= []; + $carry[(string) $insteadof][] = (string) $precedence->method; } return $carry; - }, collect()); + }, []); } /** - * @return Collection + * @return list */ - private function implementsInterfaces(ClassLike $classLike): Collection + private function implementsInterfaces(ClassLike $classLike): array { + /** @var list $nameNodes */ $nameNodes = match (true) { $classLike instanceof Class_ => $classLike->implements, $classLike instanceof Interface_ => $classLike->extends, @@ -108,14 +107,13 @@ private function implementsInterfaces(ClassLike $classLike): Collection default => [], }; - return collect($nameNodes) - ->map(fn (Name $name) => (string) $name); + return array_map(fn (Name $name) => (string) $name, $nameNodes); } /** - * @return Collection + * @return array */ - private function uses(NameContext $nameContext): Collection + private function uses(NameContext $nameContext): array { static $aliasesProperty; @@ -124,16 +122,16 @@ private function uses(NameContext $nameContext): Collection } /** @var array $uses */ + /** @phpstan-ignore-next-line */ $uses = $aliasesProperty->getValue($nameContext)[Node\Stmt\Use_::TYPE_NORMAL] ?? []; - return collect($uses) - ->map(fn (Name $name) => (string) $name); + return array_map(fn (Name $name) => (string) $name, $uses); } /** - * @return Collection + * @return list */ - private function traitsUses(ClassLike $classLike): Collection + private function traitsUses(ClassLike $classLike): array { // You don't wanna know how much time I spent researching how these stupid traits work in PHP. // What's crazy here is that even Roave/BetterReflection currently gets it wrong and doesn't @@ -143,54 +141,55 @@ private function traitsUses(ClassLike $classLike): Collection // by aliases (which doesn't actually remove the "original" method, just adds a new one on top) // and even remove methods from used traits with "precedence". // After __halt_compiler, this is definitely the most useless feature of PHP. - return collect($classLike->getTraitUses()) - ->map(function (Node\Stmt\TraitUse $traitUseNode) { - // Aliases keyed by trait class name - $aliasNodes = collect($traitUseNode->adaptations) - ->whereInstanceOf(Alias::class) - ->groupBy(fn (Alias $alias) => (string) ($alias->trait ?? end($traitUseNode->traits))); - - return new TraitsUse( - traits: collect($traitUseNode->traits) - ->map(function (Name $name) use ($aliasNodes) { - $name = (string) $name; - $aliasNodesForTrait = $aliasNodes[$name] ?? collect(); - - $aliases = $aliasNodesForTrait - ->map(fn (Alias $alias) => [ - (string) $alias->method, - ((string) $alias->newName) ?: null, - $alias->newModifier ?: null, - ]) - ->values(); - - return new TraitUse($name, $aliases); - }), - docComment: ((string) $traitUseNode->getDocComment()) ?: null, - ); - }); + return array_map(function (Node\Stmt\TraitUse $traitUseNode) { + // Aliases keyed by trait class name + $aliasNodes = collect($traitUseNode->adaptations) + ->whereInstanceOf(Alias::class) + ->groupBy(fn (Alias $alias) => (string) ($alias->trait ?? end($traitUseNode->traits))) + ->map( + fn (Collection $attributes) => $attributes->all() + ) + ->all(); + + return new TraitsUse( + traits: array_map(function (Name $name) use ($aliasNodes) { + $name = (string) $name; + $aliasNodesForTrait = $aliasNodes[$name] ?? []; + + $aliases = array_map(fn (Alias $alias) => [ + (string) $alias->method, + ((string) $alias->newName) ?: null, + $alias->newModifier ?: null, + ], $aliasNodesForTrait); + + return new TraitUse($name, array_values($aliases)); + }, $traitUseNode->traits), + docComment: ((string) $traitUseNode->getDocComment()) ?: null, + ); + }, $classLike->getTraitUses()); } /** - * @return Collection + * @return list */ - private function properties(ClassLike $classLike): Collection + private function properties(ClassLike $classLike): array { if (!$classLike instanceof Class_ && !$classLike instanceof Trait_) { - return collect(); + return []; } $properties = collect($classLike->stmts) ->whereInstanceOf(Property::class) ->flatMap(fn (Property $node) => $node->props) - ->map(fn (PropertyItem $property) => (string) $property->name); + ->map(fn (PropertyItem $property) => (string) $property->name) + ->all(); /** @var ClassMethod|null $constructor */ $constructor = collect($classLike->stmts) ->first(fn (Node $node) => $node instanceof ClassMethod && (string) $node->name === '__construct'); if (!$constructor) { - return $properties; + return array_values($properties); } $promoted = collect($constructor->params) @@ -202,16 +201,17 @@ private function properties(ClassLike $classLike): Collection return $node->var->name; }); - return $properties->concat($promoted); + return [...$properties, ...$promoted]; } /** - * @return Collection + * @return list */ - private function methods(ClassLike $classLike): Collection + private function methods(ClassLike $classLike): array { return collect($classLike->stmts) ->whereInstanceOf(ClassMethod::class) - ->map(fn (ClassMethod $method) => (string) $method->name); + ->map(fn (ClassMethod $method) => (string) $method->name) + ->all(); } } diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext.php index 95077f8..c51ca51 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext.php @@ -3,25 +3,24 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File; use GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File\FileClassLikeContext\TraitsUse; -use Illuminate\Support\Collection; class FileClassLikeContext { /** - * @param Collection $implementsInterfaces - * @param Collection $uses - * @param Collection $traitsUses - * @param Collection> $excludedTraitMethods - * @param Collection $declaredProperties - * @param Collection $declaredMethods + * @param list $implementsInterfaces + * @param array $uses + * @param list $traitsUses + * @param array> $excludedTraitMethods + * @param list $declaredProperties + * @param list $declaredMethods */ public function __construct( public readonly ?string $namespace, - public readonly Collection $implementsInterfaces, - public readonly Collection $uses, - public readonly Collection $traitsUses, - public readonly Collection $excludedTraitMethods, - public readonly Collection $declaredProperties, - public readonly Collection $declaredMethods, + public readonly array $implementsInterfaces, + public readonly array $uses, + public readonly array $traitsUses, + public readonly array $excludedTraitMethods, + public readonly array $declaredProperties, + public readonly array $declaredMethods, ) {} } diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitUse.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitUse.php index cefa4d2..ead909e 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitUse.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitUse.php @@ -2,16 +2,15 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File\FileClassLikeContext; -use Illuminate\Support\Collection; use ReflectionMethod; final class TraitUse { /** - * @param Collection|null }> $aliases [old method name, new method name, new visibility] + * @param list|null }> $aliases [old method name, new method name, new visibility] */ public function __construct( public readonly string $qualifiedName, - public readonly Collection $aliases = new Collection(), + public readonly array $aliases = [], ) {} } diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitsUse.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitsUse.php index f1ba078..e57b9b5 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitsUse.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileClassLikeContext/TraitsUse.php @@ -2,15 +2,13 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File\FileClassLikeContext; -use Illuminate\Support\Collection; - final class TraitsUse { /** - * @param Collection $traits + * @param list $traits */ public function __construct( - public readonly Collection $traits, + public readonly array $traits, public readonly ?string $docComment = null, ) {} } diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContext.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContext.php index 371b55e..a2492f1 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContext.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContext.php @@ -2,22 +2,21 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File; -use Illuminate\Support\Collection; use ReflectionClass; class FileContext { /** - * @param Collection $classLikes - * @param Collection $anonymousClassLikes + * @param array $classLikes + * @param array $anonymousClassLikes */ public function __construct( - public readonly Collection $classLikes, - public readonly Collection $anonymousClassLikes, + public readonly array $classLikes, + public readonly array $anonymousClassLikes, ) {} /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection */ public function forClassLike(ReflectionClass $reflection): FileClassLikeContext { diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContextParser.php b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContextParser.php index 5f393e2..4761d87 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContextParser.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/File/FileContextParser.php @@ -17,7 +17,7 @@ class FileContextParser public function __construct(private readonly Parser $phpParser) {} /** - * @param ReflectionClass|ReflectionFunction $reflection + * @param ReflectionClass|ReflectionFunction $reflection */ public function parse(ReflectionClass|ReflectionFunction $reflection): ?FileContext { diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/Native/NativeTypeMapper.php b/src/NativePHPDoc/Definition/NativePHPDoc/Native/NativeTypeMapper.php index 9e4a192..b31cf92 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/Native/NativeTypeMapper.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/Native/NativeTypeMapper.php @@ -15,7 +15,6 @@ use GoodPhp\Reflection\Type\Special\VoidType; use GoodPhp\Reflection\Type\Type; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use ReflectionIntersectionType; use ReflectionNamedType; use ReflectionType; @@ -25,14 +24,14 @@ class NativeTypeMapper { /** - * @param ReflectionType|string|iterable $type + * @param ReflectionType|string|list $type * - * @return ($type is ReflectionType|string ? Type : Collection) + * @return ($type is ReflectionType|string ? Type : list) */ - public function map(ReflectionType|string|iterable $type, TypeContext $context): Type|Collection + public function map(ReflectionType|string|array $type, TypeContext $context): Type|array { - if (is_iterable($type)) { - return Collection::wrap($type)->map(fn (ReflectionType|string $type) => $this->map($type, $context)); + if (is_array($type)) { + return array_map(fn (ReflectionType|string $type) => $this->map($type, $context), $type); } $isNull = fn (ReflectionType $isNullType) => $isNullType instanceof ReflectionNamedType && $isNullType->getName() === 'null'; diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/NativePHPDocDefinitionProvider.php b/src/NativePHPDoc/Definition/NativePHPDoc/NativePHPDocDefinitionProvider.php index 77e77cc..de19faa 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/NativePHPDocDefinitionProvider.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/NativePHPDocDefinitionProvider.php @@ -27,10 +27,10 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; use GoodPhp\Reflection\Type\Type; -use GoodPhp\Reflection\Util\LateInitLazy; +use GoodPhp\Reflection\Util\Lazy\LateInitLazy; +use GoodPhp\Reflection\Util\Lazy\Lazy; use GoodPhp\Reflection\Util\ReflectionAssert; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use Illuminate\Support\Str; use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode; @@ -48,11 +48,10 @@ use ReflectionParameter; use ReflectionProperty; use ReflectionType; -use TenantCloud\Standard\Lazy\Lazy; use UnitEnum; use Webmozart\Assert\Assert; -use function TenantCloud\Standard\Lazy\lazy; +use function GoodPhp\Reflection\Util\Lazy\lazy; class NativePHPDocDefinitionProvider implements DefinitionProvider { @@ -152,7 +151,7 @@ private function forEnum(string $type): TypeDefinition fileName: $this->fileName($reflection), builtIn: !$reflection->isUserDefined(), backingType: $backingType, - implements: $this->interfaces($reflection, $phpDoc, $context)->concat($implicitInterfaces), + implements: [...$this->interfaces($reflection, $phpDoc, $context), ...$implicitInterfaces], uses: $this->traits($reflection, $context), cases: $this->enumCases($reflection), methods: $this->methods($reflection, $context), @@ -160,7 +159,7 @@ private function forEnum(string $type): TypeDefinition } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection */ private function createTypeContext(ReflectionClass $reflection, PhpDocNode $phpDoc): TypeContext { @@ -170,7 +169,7 @@ private function createTypeContext(ReflectionClass $reflection, PhpDocNode $phpD ?->forClassLike($reflection), declaringType: new NamedType($reflection->getName()), declaringTypeParent: $reflection->getParentClass() ? new NamedType($reflection->getParentClass()->getName()) : null, - typeParameters: new Collection() + typeParameters: [] ); $lazyTypeParameters = $this->lazyTypeParameters($phpDoc, $context); @@ -179,7 +178,7 @@ private function createTypeContext(ReflectionClass $reflection, PhpDocNode $phpD } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection * * @return ($reflection is ReflectionEnum ? class-string : class-string) */ @@ -189,7 +188,7 @@ private function qualifiedName(ReflectionClass $reflection): string } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection */ private function fileName(ReflectionClass $reflection): ?string { @@ -199,16 +198,16 @@ private function fileName(ReflectionClass $reflection): ?string /** * @param ReflectionClass $reflection * - * @return Collection + * @return list */ - private function properties(ReflectionClass $reflection, TypeContext $context): Collection + private function properties(ReflectionClass $reflection, TypeContext $context): array { $constructorPhpDoc = $this->phpDocStringParser->parse( $reflection->getConstructor()?->getDocComment() ?: '' ); - return Collection::make($reflection->getProperties()) - ->filter(fn (ReflectionProperty $property) => !$context->fileClassLikeContext || $context->fileClassLikeContext->declaredProperties->contains($property->getName())) + return collect($reflection->getProperties()) + ->filter(fn (ReflectionProperty $property) => !$context->fileClassLikeContext || in_array($property->getName(), $context->fileClassLikeContext->declaredProperties, true)) ->map(function (ReflectionProperty $property) use ($context, $constructorPhpDoc) { $phpDoc = $this->phpDocStringParser->parse($property); @@ -238,18 +237,19 @@ private function properties(ReflectionClass $reflection, TypeContext $context): hasDefaultValue: $property->hasDefaultValue(), isPromoted: $property->isPromoted(), ); - }); + }) + ->all(); } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection * - * @return Collection + * @return list */ - private function methods(ReflectionClass $reflection, TypeContext $context): Collection + private function methods(ReflectionClass $reflection, TypeContext $context): array { - return Collection::make($reflection->getMethods()) - ->filter(fn (ReflectionMethod $method) => !$context->fileClassLikeContext || $context->fileClassLikeContext->declaredMethods->contains($method->getName())) + return collect($reflection->getMethods()) + ->filter(fn (ReflectionMethod $method) => !$context->fileClassLikeContext || in_array($method->getName(), $context->fileClassLikeContext->declaredMethods, true)) ->map(function (ReflectionMethod $method) use ($context) { $phpDoc = $this->phpDocStringParser->parse($method); @@ -269,16 +269,17 @@ private function methods(ReflectionClass $reflection, TypeContext $context): Col $context, ) ); - }); + }) + ->all(); } /** - * @return Collection> + * @return array> */ - private function lazyTypeParameters(PhpDocNode $phpDoc, TypeContext $context): Collection + private function lazyTypeParameters(PhpDocNode $phpDoc, TypeContext $context): array { - /** @var Collection> $lazyTypeParametersMap */ - $lazyTypeParametersMap = new Collection(); + /** @var array> $lazyTypeParametersMap */ + $lazyTypeParametersMap = []; /** @var LateInitLazy $temporaryContext */ $temporaryContext = new LateInitLazy(); @@ -319,23 +320,23 @@ function () use ($node, $value, $temporaryContext) { } /** - * @return Collection + * @return list */ - private function typeParameters(PhpDocNode $phpDoc, TypeContext $context): Collection + private function typeParameters(PhpDocNode $phpDoc, TypeContext $context): array { // The types are properly defined, but for whatever reason ->map() breaks it all. - /** @var Collection */ - return $this->lazyTypeParameters($phpDoc, $context) - ->values() - ->map(fn (Lazy $lazy) => $lazy->value()); + return array_map( + fn (Lazy $lazy) => $lazy->value(), + array_values($this->lazyTypeParameters($phpDoc, $context)) + ); } /** - * @return Collection + * @return list */ - private function functionParameters(ReflectionMethod $reflection, PhpDocNode $phpDoc, TypeContext $context): Collection + private function functionParameters(ReflectionMethod $reflection, PhpDocNode $phpDoc, TypeContext $context): array { - return Collection::make($reflection->getParameters()) + return collect($reflection->getParameters()) ->map(function (ReflectionParameter $parameter) use ($context, $phpDoc) { /** @var ParamTagValueNode|null $phpDocType */ $phpDocType = Arr::first( @@ -352,7 +353,8 @@ private function functionParameters(ReflectionMethod $reflection, PhpDocNode $ph ), hasDefaultValue: $parameter->isDefaultValueAvailable(), ); - }); + }) + ->all(); } /** @@ -392,14 +394,14 @@ private function parent(ReflectionClass $reflection, PhpDocNode $phpDoc, TypeCon } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection * - * @return Collection + * @return list */ - private function interfaces(ReflectionClass $reflection, PhpDocNode $phpDoc, TypeContext $context): Collection + private function interfaces(ReflectionClass $reflection, PhpDocNode $phpDoc, TypeContext $context): array { - return Collection::make($reflection->getInterfaceNames()) - ->filter(fn (string $className) => !$context->fileClassLikeContext || $context->fileClassLikeContext->implementsInterfaces->contains($className)) + return collect($reflection->getInterfaceNames()) + ->filter(fn (string $className) => !$context->fileClassLikeContext || in_array($className, $context->fileClassLikeContext->implementsInterfaces, true)) ->map(function (string $className) use ($reflection, $context, $phpDoc) { /** @var PhpDocTagNode|null $tag */ $tag = Arr::first( @@ -421,11 +423,12 @@ private function interfaces(ReflectionClass $reflection, PhpDocNode $phpDoc, Typ ReflectionAssert::namedType($type, 'mapping `implements` types for [' . $reflection->getName() . ']'); return $type; - }); + }) + ->all(); } /** - * @param ReflectionClass $reflection + * @param ReflectionClass $reflection */ private function traits(ReflectionClass $reflection, TypeContext $context): UsedTraitsDefinition { @@ -434,69 +437,73 @@ private function traits(ReflectionClass $reflection, TypeContext $context): Used ->fileClassLikeContext ->traitsUses; } else { - $traitsUses = collect([ + $traitsUses = [ new TraitsUse( - collect($reflection->getTraitNames())->map(fn (string $className) => new TraitUse($className)) + array_map( + fn (string $className) => new TraitUse($className), + $reflection->getTraitNames() + ) ), - ]); + ]; } - $traits = $traitsUses + $traits = collect($traitsUses) ->flatMap(function (TraitsUse $traitsUse) use ($reflection, $context) { $phpDoc = $this->phpDocStringParser->parse($traitsUse->docComment); - return $traitsUse - ->traits - ->map(function (TraitUse $traitUse) use ($reflection, $context, $phpDoc) { - $qualifiedName = $this->typeAliasResolver->resolve($traitUse->qualifiedName, $context->fileClassLikeContext); - /** @var PhpDocTagNode|null $tag */ - $tag = Arr::first( - $phpDoc->getTags(), - fn (PhpDocTagNode $node) => $node->value instanceof UsesTagValueNode && - $qualifiedName === $this->typeAliasResolver->resolve($node->value->type->type->name, $context->fileClassLikeContext) - ); - - /** @var UsesTagValueNode|null $tagValue */ - $tagValue = $tag?->value; - - $type = $this->map( - $qualifiedName, - $tagValue?->type, - $context - ); - - Assert::notNull($type); - ReflectionAssert::namedType($type, 'mapping trait `use` for [' . $reflection->getName() . ']'); - - return [$type, $traitUse->aliases]; - }); + return array_map(function (TraitUse $traitUse) use ($reflection, $context, $phpDoc) { + $qualifiedName = $this->typeAliasResolver->resolve($traitUse->qualifiedName, $context->fileClassLikeContext); + /** @var PhpDocTagNode|null $tag */ + $tag = Arr::first( + $phpDoc->getTags(), + fn (PhpDocTagNode $node) => $node->value instanceof UsesTagValueNode && + $qualifiedName === $this->typeAliasResolver->resolve($node->value->type->type->name, $context->fileClassLikeContext) + ); + + /** @var UsesTagValueNode|null $tagValue */ + $tagValue = $tag?->value; + + $type = $this->map( + $qualifiedName, + $tagValue?->type, + $context + ); + + Assert::notNull($type); + ReflectionAssert::namedType($type, 'mapping trait `use` for [' . $reflection->getName() . ']'); + + return [$type, $traitUse->aliases]; + }, $traitsUse->traits); }) ->map(fn (array $data) => new UsedTraitDefinition( trait: $data[0], - aliases: $data[1]->map(fn (array $aliasData) => new UsedTraitAliasDefinition( + aliases: array_map(fn (array $aliasData) => new UsedTraitAliasDefinition( name: $aliasData[0], newName: $aliasData[1], newModifier: $aliasData[2], - )) - )); + ), $data[1]) + )) + ->all(); return new UsedTraitsDefinition( traits: $traits, - excludedTraitMethods: $context->fileClassLikeContext?->excludedTraitMethods ?? collect(), + excludedTraitMethods: $context->fileClassLikeContext?->excludedTraitMethods ?? [], ); } /** * @param ReflectionEnum $reflection * - * @return Collection + * @return list */ - private function enumCases(ReflectionEnum $reflection): Collection + private function enumCases(ReflectionEnum $reflection): array { - return Collection::make($reflection->getCases()) - ->map(fn (ReflectionEnumUnitCase $case) => new EnumCaseDefinition( + return array_map( + fn (ReflectionEnumUnitCase $case) => new EnumCaseDefinition( name: $case->getName(), backingValue: $case instanceof ReflectionEnumBackedCase ? $case->getBackingValue() : null, - )); + ), + $reflection->getCases() + ); } } diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/PhpDoc/PhpDocTypeMapper.php b/src/NativePHPDoc/Definition/NativePHPDoc/PhpDoc/PhpDocTypeMapper.php index 817f9f7..ce0ef40 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/PhpDoc/PhpDocTypeMapper.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/PhpDoc/PhpDocTypeMapper.php @@ -18,7 +18,6 @@ use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Type; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode; use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode; use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; @@ -40,14 +39,14 @@ public function __construct( ) {} /** - * @param TypeNode|iterable $node + * @param TypeNode|list $node * - * @return ($node is TypeNode ? Type : Collection) + * @return ($node is TypeNode ? Type : list) */ - public function map(TypeNode|iterable $node, TypeContext $context): Type|Collection + public function map(TypeNode|array $node, TypeContext $context): Type|array { if (!$node instanceof TypeNode) { - return Collection::wrap($node)->map(fn (TypeNode $node) => $this->map($node, $context)); + return array_map(fn (TypeNode $node) => $this->map($node, $context), $node); } try { @@ -56,17 +55,20 @@ public function map(TypeNode|iterable $node, TypeContext $context): Type|Collect $this->map($node->type, $context) ), $node instanceof ArrayShapeNode => new TupleType( - collect($node->items)->map(fn (ArrayShapeItemNode $node) => $this->map($node->valueType, $context)) + array_map( + fn (ArrayShapeItemNode $node) => $this->map($node->valueType, $context), + $node->items + ) ), $node instanceof CallableTypeNode => $this->mapNamed( $node->identifier->name, - new Collection([ + [ $this->map($node->returnType, $context), ...array_map( fn (CallableTypeParameterNode $parameterNode) => $this->map($parameterNode->type, $context), $node->parameters ), - ]), + ], $context, ), $node instanceof GenericTypeNode => $this->mapNamed( @@ -76,7 +78,7 @@ public function map(TypeNode|iterable $node, TypeContext $context): Type|Collect ), $node instanceof IdentifierTypeNode => $this->mapNamed( $node->name, - new Collection(), + [], $context, ), $node instanceof IntersectionTypeNode => new IntersectionType( @@ -97,9 +99,9 @@ public function map(TypeNode|iterable $node, TypeContext $context): Type|Collect } /** - * @param Collection $arguments + * @param list $arguments */ - public function mapNamed(string $type, Collection $arguments, TypeContext $context): Type + public function mapNamed(string $type, array $arguments, TypeContext $context): Type { if ($context->typeParameters[$type] ?? null) { return new TemplateType( @@ -124,34 +126,34 @@ public function mapNamed(string $type, Collection $arguments, TypeContext $conte 'never', 'never-return', 'never-returns', 'no-return', 'noreturn' => NeverType::get(), 'void' => VoidType::get(), 'int', 'integer', 'positive-int', 'negative-int', 'int-mask', 'int-mask-of' => PrimitiveType::integer(), - 'number' => new UnionType(new Collection([ + 'number' => new UnionType([ PrimitiveType::integer(), PrimitiveType::float(), - ])), + ]), 'float', 'double' => PrimitiveType::float(), 'string', 'numeric-string', 'literal-string', 'class-string', 'interface-string', 'trait-string', 'callable-string', 'non-empty-string' => PrimitiveType::string(), 'bool', 'boolean', 'true', 'false' => PrimitiveType::boolean(), - 'array-key' => new UnionType(new Collection([ + 'array-key' => new UnionType([ PrimitiveType::integer(), PrimitiveType::string(), - ])), + ]), 'callable', 'iterable', 'resource', 'object' => new NamedType($type, $arguments), - 'array', 'non-empty-array' => match ($arguments->count()) { + 'array', 'non-empty-array' => match (count($arguments)) { 1 => PrimitiveType::array($arguments[0]), default => new NamedType('array', $arguments) }, 'associative-array' => new NamedType('array', $arguments), - 'list', 'non-empty-list' => new NamedType('array', new Collection([ + 'list', 'non-empty-list' => new NamedType('array', [ PrimitiveType::integer(), ...$arguments, - ])), - 'scalar' => new UnionType(new Collection([ + ]), + 'scalar' => new UnionType([ PrimitiveType::integer(), PrimitiveType::float(), PrimitiveType::string(), PrimitiveType::boolean(), - ])), + ]), 'self' => new NamedType($context->declaringType->name, $arguments), 'static' => new StaticType($context->declaringType), default => null, diff --git a/src/NativePHPDoc/Definition/NativePHPDoc/TypeContext.php b/src/NativePHPDoc/Definition/NativePHPDoc/TypeContext.php index 005d3cc..59d66ce 100644 --- a/src/NativePHPDoc/Definition/NativePHPDoc/TypeContext.php +++ b/src/NativePHPDoc/Definition/NativePHPDoc/TypeContext.php @@ -5,31 +5,33 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\NativePHPDoc\File\FileClassLikeContext; use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition\TypeParameterDefinition; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; -use TenantCloud\Standard\Lazy\Lazy; +use GoodPhp\Reflection\Util\Lazy\Lazy; class TypeContext { /** - * @param Collection> $typeParameters + * @param array> $typeParameters */ public function __construct( public readonly ?FileClassLikeContext $fileClassLikeContext, public readonly NamedType $declaringType, public readonly ?NamedType $declaringTypeParent, - public readonly Collection $typeParameters + public readonly array $typeParameters ) {} /** - * @param Collection> $parameters + * @param array> $parameters */ - public function withMergedTypeParameters(Collection $parameters): self + public function withMergedTypeParameters(array $parameters): self { return new self( fileClassLikeContext: $this->fileClassLikeContext, declaringType: $this->declaringType, declaringTypeParent: $this->declaringTypeParent, - typeParameters: (clone $this->typeParameters)->merge($parameters) + typeParameters: [ + ...$this->typeParameters, + ...$parameters, + ], ); } } diff --git a/src/NativePHPDoc/Definition/TypeDefinition/ClassTypeDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/ClassTypeDefinition.php index 64cbc9c..1fc486d 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/ClassTypeDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/ClassTypeDefinition.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template-covariant T of object @@ -15,11 +14,11 @@ final class ClassTypeDefinition extends TypeDefinition public readonly string $qualifiedName; /** - * @param class-string $qualifiedName - * @param Collection $typeParameters - * @param Collection $implements - * @param Collection $properties - * @param Collection $methods + * @param class-string $qualifiedName + * @param list $typeParameters + * @param list $implements + * @param list $properties + * @param list $methods */ public function __construct( string $qualifiedName, @@ -28,12 +27,12 @@ public function __construct( public readonly bool $anonymous, public readonly bool $final, public readonly bool $abstract, - public readonly Collection $typeParameters, + public readonly array $typeParameters, public readonly ?NamedType $extends, - public readonly Collection $implements, + public readonly array $implements, public readonly UsedTraitsDefinition $uses, - public readonly Collection $properties, - public readonly Collection $methods, + public readonly array $properties, + public readonly array $methods, ) { parent::__construct( $qualifiedName, diff --git a/src/NativePHPDoc/Definition/TypeDefinition/EnumTypeDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/EnumTypeDefinition.php index 41f7bf4..f26d3c3 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/EnumTypeDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/EnumTypeDefinition.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template-covariant T of \UnitEnum @@ -15,20 +14,20 @@ final class EnumTypeDefinition extends TypeDefinition public readonly string $qualifiedName; /** - * @param class-string $qualifiedName - * @param Collection $implements - * @param Collection $cases - * @param Collection $methods + * @param class-string $qualifiedName + * @param list $implements + * @param list $cases + * @param list $methods */ public function __construct( string $qualifiedName, ?string $fileName, public readonly bool $builtIn, public readonly ?NamedType $backingType, - public readonly Collection $implements, + public readonly array $implements, public readonly UsedTraitsDefinition $uses, - public readonly Collection $cases, - public readonly Collection $methods, + public readonly array $cases, + public readonly array $methods, ) { parent::__construct( $qualifiedName, diff --git a/src/NativePHPDoc/Definition/TypeDefinition/InterfaceTypeDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/InterfaceTypeDefinition.php index f8ab611..3274e48 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/InterfaceTypeDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/InterfaceTypeDefinition.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template-covariant T of object @@ -15,18 +14,18 @@ final class InterfaceTypeDefinition extends TypeDefinition public readonly string $qualifiedName; /** - * @param class-string $qualifiedName - * @param Collection $typeParameters - * @param Collection $extends - * @param Collection $methods + * @param class-string $qualifiedName + * @param list $typeParameters + * @param list $extends + * @param list $methods */ public function __construct( string $qualifiedName, ?string $fileName, public readonly bool $builtIn, - public readonly Collection $typeParameters, - public readonly Collection $extends, - public readonly Collection $methods, + public readonly array $typeParameters, + public readonly array $extends, + public readonly array $methods, ) { parent::__construct( $qualifiedName, diff --git a/src/NativePHPDoc/Definition/TypeDefinition/MethodDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/MethodDefinition.php index f63928d..51571d4 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/MethodDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/MethodDefinition.php @@ -3,18 +3,17 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; final class MethodDefinition { /** - * @param Collection $typeParameters - * @param Collection $parameters + * @param list $typeParameters + * @param list $parameters */ public function __construct( public readonly string $name, - public readonly Collection $typeParameters, - public readonly Collection $parameters, + public readonly array $typeParameters, + public readonly array $parameters, public readonly ?Type $returnType, ) {} } diff --git a/src/NativePHPDoc/Definition/TypeDefinition/SpecialTypeDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/SpecialTypeDefinition.php index 30acf40..324e139 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/SpecialTypeDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/SpecialTypeDefinition.php @@ -4,18 +4,17 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; final class SpecialTypeDefinition extends TypeDefinition { /** - * @param Collection $typeParameters - * @param Collection $superTypes + * @param list $typeParameters + * @param list $superTypes */ public function __construct( string $qualifiedName, - public readonly Collection $typeParameters = new Collection(), - public readonly Collection $superTypes = new Collection(), + public readonly array $typeParameters = [], + public readonly array $superTypes = [], ) { parent::__construct( $qualifiedName, diff --git a/src/NativePHPDoc/Definition/TypeDefinition/TraitTypeDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/TraitTypeDefinition.php index 5cc1b7a..3d1273b 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/TraitTypeDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/TraitTypeDefinition.php @@ -3,7 +3,6 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; -use Illuminate\Support\Collection; /** * @template-covariant T of object @@ -14,19 +13,19 @@ final class TraitTypeDefinition extends TypeDefinition public readonly string $qualifiedName; /** - * @param class-string $qualifiedName - * @param Collection $typeParameters - * @param Collection $properties - * @param Collection $methods + * @param class-string $qualifiedName + * @param list $typeParameters + * @param list $properties + * @param list $methods */ public function __construct( string $qualifiedName, ?string $fileName, public readonly bool $builtIn, - public readonly Collection $typeParameters, + public readonly array $typeParameters, public readonly UsedTraitsDefinition $uses, - public readonly Collection $properties, - public readonly Collection $methods, + public readonly array $properties, + public readonly array $methods, ) { parent::__construct( $qualifiedName, diff --git a/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitDefinition.php index e57b92c..d75a8d7 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitDefinition.php @@ -3,15 +3,14 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; final class UsedTraitDefinition { /** - * @param Collection $aliases + * @param list $aliases */ public function __construct( public readonly NamedType $trait, - public readonly Collection $aliases = new Collection(), + public readonly array $aliases = [], ) {} } diff --git a/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitsDefinition.php b/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitsDefinition.php index eea81ec..ed14915 100644 --- a/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitsDefinition.php +++ b/src/NativePHPDoc/Definition/TypeDefinition/UsedTraitsDefinition.php @@ -2,16 +2,14 @@ namespace GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition; -use Illuminate\Support\Collection; - final class UsedTraitsDefinition { /** - * @param Collection $traits - * @param Collection> $excludedTraitMethods + * @param list $traits + * @param array> $excludedTraitMethods */ public function __construct( - public readonly Collection $traits = new Collection(), - public readonly Collection $excludedTraitMethods = new Collection(), + public readonly array $traits = [], + public readonly array $excludedTraitMethods = [], ) {} } diff --git a/src/NativePHPDoc/DefinitionProviderReflector.php b/src/NativePHPDoc/DefinitionProviderReflector.php index a1b2d3d..3ebaf98 100644 --- a/src/NativePHPDoc/DefinitionProviderReflector.php +++ b/src/NativePHPDoc/DefinitionProviderReflector.php @@ -20,7 +20,6 @@ use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeComparator; use GoodPhp\Reflection\UnknownTypeException; -use Illuminate\Support\Collection; use InvalidArgumentException; final class DefinitionProviderReflector implements Reflector @@ -50,7 +49,7 @@ public function forNamedType(NamedType $type): TypeReflection $definition instanceof ClassTypeDefinition || $definition instanceof InterfaceTypeDefinition || $definition instanceof TraitTypeDefinition || - $definition instanceof SpecialTypeDefinition => TypeParameterMap::fromArguments($type->arguments->all(), $definition->typeParameters), + $definition instanceof SpecialTypeDefinition => TypeParameterMap::fromArguments($type->arguments, $definition->typeParameters), default => TypeParameterMap::empty() }; @@ -65,11 +64,11 @@ public function forNamedType(NamedType $type): TypeReflection } /** - * @param Collection $arguments + * @param list $arguments * * @return TypeReflection */ - public function forType(string $name, Collection $arguments = new Collection()): TypeReflection + public function forType(string $name, array $arguments = []): TypeReflection { return $this->forNamedType(new NamedType($name, $arguments)); } diff --git a/src/NativePHPDoc/Reflection/Attributes/NativeAttributes.php b/src/NativePHPDoc/Reflection/Attributes/NativeAttributes.php index a402305..ef291dd 100644 --- a/src/NativePHPDoc/Reflection/Attributes/NativeAttributes.php +++ b/src/NativePHPDoc/Reflection/Attributes/NativeAttributes.php @@ -4,11 +4,11 @@ use GoodPhp\Reflection\Reflection\Attributes\ArrayAttributes; use GoodPhp\Reflection\Reflection\Attributes\Attributes; +use GoodPhp\Reflection\Util\Lazy\Lazy; use Illuminate\Support\Collection; use ReflectionAttribute; -use TenantCloud\Standard\Lazy\Lazy; -use function TenantCloud\Standard\Lazy\lazy; +use function GoodPhp\Reflection\Util\Lazy\lazy; final class NativeAttributes implements Attributes { @@ -16,9 +16,9 @@ final class NativeAttributes implements Attributes private readonly Lazy $delegate; /** - * @param callable(): ReflectionAttribute[]|null $makeAttributes + * @param callable(): list>|null $makeAttributes */ - public function __construct(callable $makeAttributes = null) + public function __construct(?callable $makeAttributes = null) { $makeAttributes ??= fn () => []; @@ -39,7 +39,7 @@ public function __construct(callable $makeAttributes = null) /** * @param class-string|null $className */ - public function has(string $className = null): bool + public function has(?string $className = null): bool { return $this->delegate->value()->has($className); } @@ -49,9 +49,9 @@ public function has(string $className = null): bool * * @param class-string|null $className * - * @return ($className is null ? Collection : Collection) + * @return ($className is null ? list : list) */ - public function all(string $className = null): Collection + public function all(?string $className = null): array { return $this->delegate->value()->all($className); } diff --git a/src/NativePHPDoc/Reflection/NpdClassReflection.php b/src/NativePHPDoc/Reflection/NpdClassReflection.php index c040fa7..c44e244 100644 --- a/src/NativePHPDoc/Reflection/NpdClassReflection.php +++ b/src/NativePHPDoc/Reflection/NpdClassReflection.php @@ -22,7 +22,7 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\TypeProjector; -use Illuminate\Support\Collection; +use Illuminate\Support\Arr; use ReflectionClass; /** @@ -42,29 +42,29 @@ final class NpdClassReflection extends NpdTypeReflection implements ClassReflect /** @var ReflectionClass */ private readonly ReflectionClass $nativeReflection; - /** @var Collection> */ - private readonly Collection $typeParameters; + /** @var list> */ + private array $typeParameters; private readonly Attributes $attributes; - private readonly ?NamedType $extends; + private ?NamedType $extends; - /** @var Collection */ - private readonly Collection $implements; + /** @var list */ + private array $implements; private UsedTraitsReflection $uses; - /** @var Collection> */ - private readonly Collection $declaredProperties; + /** @var list> */ + private array $declaredProperties; - /** @var Collection>> */ - private readonly Collection $properties; + /** @var list>> */ + private array $properties; - /** @var Collection> */ - private readonly Collection $declaredMethods; + /** @var list> */ + private array $declaredMethods; - /** @var Collection>> */ - private readonly Collection $methods; + /** @var list>> */ + private array $methods; /** * @param ClassTypeDefinition $definition @@ -114,13 +114,14 @@ public function attributes(): Attributes } /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection + public function typeParameters(): array { - return $this->typeParameters ??= $this->definition - ->typeParameters - ->map(fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType)); + return $this->typeParameters ??= array_map( + fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType), + $this->definition->typeParameters + ); } public function extends(): ?NamedType @@ -141,17 +142,18 @@ public function extends(): ?NamedType } /** - * @return Collection + * @return list */ - public function implements(): Collection + public function implements(): array { - return $this->implements ??= $this->definition - ->implements - ->map(fn (NamedType $type) => TypeProjector::templateTypes( + return $this->implements ??= array_map( + fn (NamedType $type) => TypeProjector::templateTypes( $type, $this->resolvedTypeParameterMap, $this->staticType, - )); + ), + $this->definition->implements + ); } public function uses(): UsedTraitsReflection @@ -160,19 +162,20 @@ public function uses(): UsedTraitsReflection } /** - * @return Collection> + * @return list> */ - public function declaredProperties(): Collection + public function declaredProperties(): array { - return $this->declaredProperties ??= $this->definition - ->properties - ->map(fn (PropertyDefinition $property) => new NpdPropertyReflection($property, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->declaredProperties ??= array_map( + fn (PropertyDefinition $property) => new NpdPropertyReflection($property, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->properties, + ); } /** - * @return Collection>> + * @return list>> */ - public function properties(): Collection + public function properties(): array { return $this->properties ??= collect([ ...$this->propertiesFromTraits($this->uses(), $this->staticType, $this->reflector), @@ -180,23 +183,25 @@ public function properties(): Collection ...$this->declaredProperties(), ]) ->keyBy(fn (PropertyReflection $property) => $property->name()) - ->values(); + ->values() + ->all(); } /** - * @return Collection> + * @return list> */ - public function declaredMethods(): Collection + public function declaredMethods(): array { - return $this->declaredMethods ??= $this->definition - ->methods - ->map(fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->declaredMethods ??= array_map( + fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->methods, + ); } /** - * @return Collection>> + * @return list>> */ - public function methods(): Collection + public function methods(): array { return $this->methods ??= collect([ ...$this->methodsFromTypes($this->implements(), $this->staticType, $this->reflector), @@ -205,7 +210,8 @@ public function methods(): Collection ...$this->declaredMethods(), ]) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } /** @@ -213,9 +219,10 @@ public function methods(): Collection */ public function constructor(): ?MethodReflection { - return $this - ->methods() - ->first(fn (MethodReflection $reflection) => $reflection->name() === '__construct'); + return Arr::first( + $this->methods(), + fn (MethodReflection $reflection) => $reflection->name() === '__construct' + ); } public function isAnonymous(): bool diff --git a/src/NativePHPDoc/Reflection/NpdEnumReflection.php b/src/NativePHPDoc/Reflection/NpdEnumReflection.php index 7092152..9ecf4c7 100644 --- a/src/NativePHPDoc/Reflection/NpdEnumReflection.php +++ b/src/NativePHPDoc/Reflection/NpdEnumReflection.php @@ -15,7 +15,6 @@ use GoodPhp\Reflection\Reflector; use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; -use Illuminate\Support\Collection; use ReflectionEnum; /** @@ -39,11 +38,11 @@ final class NpdEnumReflection extends NpdTypeReflection implements EnumReflectio private UsedTraitsReflection $uses; - /** @var Collection> */ - private readonly Collection $declaredMethods; + /** @var list> */ + private array $declaredMethods; - /** @var Collection>> */ - private readonly Collection $methods; + /** @var list>> */ + private array $methods; /** * @param EnumTypeDefinition $definition @@ -92,9 +91,9 @@ public function attributes(): Attributes } /** - * @return Collection + * @return list */ - public function implements(): Collection + public function implements(): array { return $this->definition->implements; } @@ -105,19 +104,20 @@ public function uses(): UsedTraitsReflection } /** - * @return Collection> + * @return list> */ - public function declaredMethods(): Collection + public function declaredMethods(): array { - return $this->declaredMethods ??= $this->definition - ->methods - ->map(fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, TypeParameterMap::empty())); + return $this->declaredMethods ??= array_map( + fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, TypeParameterMap::empty()), + $this->definition->methods, + ); } /** - * @return Collection>> + * @return list>> */ - public function methods(): Collection + public function methods(): array { return $this->methods ??= collect([ ...$this->methodsFromTypes($this->implements(), $this->staticType, $this->reflector), @@ -125,7 +125,8 @@ public function methods(): Collection ...$this->declaredMethods(), ]) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } public function isBuiltIn(): bool diff --git a/src/NativePHPDoc/Reflection/NpdInterfaceReflection.php b/src/NativePHPDoc/Reflection/NpdInterfaceReflection.php index 0cca8f1..e83b965 100644 --- a/src/NativePHPDoc/Reflection/NpdInterfaceReflection.php +++ b/src/NativePHPDoc/Reflection/NpdInterfaceReflection.php @@ -17,7 +17,6 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\TypeProjector; -use Illuminate\Support\Collection; use ReflectionClass; /** @@ -34,22 +33,22 @@ final class NpdInterfaceReflection extends NpdTypeReflection implements Interfac private NamedType $staticType; - /** @var Collection> */ - private readonly Collection $typeParameters; + /** @var list> */ + private array $typeParameters; /** @var ReflectionClass */ private readonly ReflectionClass $nativeReflection; private readonly Attributes $attributes; - /** @var Collection */ - private readonly Collection $extends; + /** @var list */ + private array $extends; - /** @var Collection> */ - private readonly Collection $declaredMethods; + /** @var list> */ + private array $declaredMethods; - /** @var Collection>> */ - private readonly Collection $methods; + /** @var list>> */ + private array $methods; /** * @param InterfaceTypeDefinition $definition @@ -99,50 +98,51 @@ public function attributes(): Attributes } /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection + public function typeParameters(): array { - return $this->typeParameters ??= $this->definition - ->typeParameters - ->map(fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType)); + return $this->typeParameters ??= array_map( + fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType), + $this->definition->typeParameters + ); } /** - * @return Collection + * @return list */ - public function extends(): Collection + public function extends(): array { - return $this->extends ??= $this->definition - ->extends - ->map(fn (NamedType $type) => TypeProjector::templateTypes( - $type, - $this->resolvedTypeParameterMap, - $this->staticType, - )); + return $this->extends ??= array_map(fn (NamedType $type) => TypeProjector::templateTypes( + $type, + $this->resolvedTypeParameterMap, + $this->staticType, + ), $this->definition->extends); } /** - * @return Collection> + * @return list> */ - public function declaredMethods(): Collection + public function declaredMethods(): array { - return $this->declaredMethods ??= $this->definition - ->methods - ->map(fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->declaredMethods ??= array_map( + fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->methods + ); } /** - * @return Collection>> + * @return list>> */ - public function methods(): Collection + public function methods(): array { return $this->methods ??= collect([ ...$this->methodsFromTypes($this->extends(), $this->staticType, $this->reflector), ...$this->declaredMethods(), ]) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } public function isBuiltIn(): bool diff --git a/src/NativePHPDoc/Reflection/NpdMethodReflection.php b/src/NativePHPDoc/Reflection/NpdMethodReflection.php index 7d5abed..f19eb9a 100644 --- a/src/NativePHPDoc/Reflection/NpdMethodReflection.php +++ b/src/NativePHPDoc/Reflection/NpdMethodReflection.php @@ -16,7 +16,6 @@ use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeProjector; -use Illuminate\Support\Collection; use ReflectionMethod; /** @@ -30,13 +29,13 @@ final class NpdMethodReflection implements MethodReflection { private readonly ReflectionMethod $nativeReflection; - /** @var Collection> */ - private readonly Collection $typeParameters; + /** @var list> */ + private array $typeParameters; private readonly Attributes $attributes; - /** @var Collection> */ - private Collection $parameters; + /** @var list> */ + private array $parameters; private ?Type $returnType; @@ -76,23 +75,25 @@ public function attributes(): Attributes } /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection + public function typeParameters(): array { - return $this->typeParameters ??= $this->definition - ->typeParameters - ->map(fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType)); + return $this->typeParameters ??= array_map( + fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType), + $this->definition->typeParameters + ); } /** - * @return Collection> + * @return list> */ - public function parameters(): Collection + public function parameters(): array { - return $this->parameters ??= $this->definition - ->parameters - ->map(fn (FunctionParameterDefinition $parameter) => new NpdFunctionParameterReflection($parameter, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->parameters ??= array_map( + fn (FunctionParameterDefinition $parameter) => new NpdFunctionParameterReflection($parameter, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->parameters + ); } public function returnType(): ?Type diff --git a/src/NativePHPDoc/Reflection/NpdPropertyReflection.php b/src/NativePHPDoc/Reflection/NpdPropertyReflection.php index 6ee89c9..9579943 100644 --- a/src/NativePHPDoc/Reflection/NpdPropertyReflection.php +++ b/src/NativePHPDoc/Reflection/NpdPropertyReflection.php @@ -15,6 +15,7 @@ use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeProjector; +use Illuminate\Support\Arr; use ReflectionProperty; use Webmozart\Assert\Assert; @@ -31,10 +32,10 @@ final class NpdPropertyReflection implements PropertyReflection private readonly Attributes $attributes; - private readonly ?Type $type; + private ?Type $type; /** @var FunctionParameterReflection>>|null */ - private readonly ?FunctionParameterReflection $promotedParameter; + private ?FunctionParameterReflection $promotedParameter; /** * @param DeclaringTypeReflection $declaringType @@ -106,7 +107,7 @@ public function isPromoted(): bool * * @return FunctionParameterReflection>>|null */ - public function promotedParameter(): FunctionParameterReflection|null + public function promotedParameter(): ?FunctionParameterReflection { if (isset($this->promotedParameter)) { return $this->promotedParameter; @@ -120,7 +121,8 @@ public function promotedParameter(): FunctionParameterReflection|null Assert::notNull($constructor); - return $this->promotedParameter ??= $constructor->parameters()->first( + return $this->promotedParameter ??= Arr::first( + $constructor->parameters(), fn (FunctionParameterReflection $parameter) => $this->definition->name === $parameter->name() ); } diff --git a/src/NativePHPDoc/Reflection/NpdSpecialTypeReflection.php b/src/NativePHPDoc/Reflection/NpdSpecialTypeReflection.php index 4c3d8cf..4b7c008 100644 --- a/src/NativePHPDoc/Reflection/NpdSpecialTypeReflection.php +++ b/src/NativePHPDoc/Reflection/NpdSpecialTypeReflection.php @@ -10,7 +10,6 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; /** * @template ReflectableType @@ -23,8 +22,8 @@ final class NpdSpecialTypeReflection extends NpdTypeReflection implements Specia private NamedType $staticType; - /** @var Collection> */ - private readonly Collection $typeParameters; + /** @var list> */ + private array $typeParameters; public function __construct( private readonly SpecialTypeDefinition $definition, @@ -63,19 +62,20 @@ public function fileName(): ?string } /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection + public function typeParameters(): array { - return $this->typeParameters ??= $this->definition - ->typeParameters - ->map(fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->type)); + return $this->typeParameters ??= array_map( + fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->type), + $this->definition->typeParameters + ); } /** - * @return Collection + * @return list */ - public function superTypes(): Collection + public function superTypes(): array { return $this->definition->superTypes; } diff --git a/src/NativePHPDoc/Reflection/NpdTraitReflection.php b/src/NativePHPDoc/Reflection/NpdTraitReflection.php index 3301a93..cfdf3ba 100644 --- a/src/NativePHPDoc/Reflection/NpdTraitReflection.php +++ b/src/NativePHPDoc/Reflection/NpdTraitReflection.php @@ -21,7 +21,6 @@ use GoodPhp\Reflection\Reflector; use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; -use Illuminate\Support\Collection; use ReflectionClass; /** @@ -41,24 +40,24 @@ final class NpdTraitReflection extends NpdTypeReflection implements TraitReflect /** @var ReflectionClass */ private readonly ReflectionClass $nativeReflection; - /** @var Collection> */ - private readonly Collection $typeParameters; + /** @var list> */ + private array $typeParameters; private readonly Attributes $attributes; private UsedTraitsReflection $uses; - /** @var Collection> */ - private Collection $declaredProperties; + /** @var list> */ + private array $declaredProperties; - /** @var Collection>> */ - private Collection $properties; + /** @var list>> */ + private array $properties; - /** @var Collection> */ - private Collection $declaredMethods; + /** @var list> */ + private array $declaredMethods; - /** @var Collection>> */ - private Collection $methods; + /** @var list>> */ + private array $methods; /** * @param TraitTypeDefinition $definition @@ -108,13 +107,14 @@ public function attributes(): Attributes } /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection + public function typeParameters(): array { - return $this->typeParameters ??= $this->definition - ->typeParameters - ->map(fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType)); + return $this->typeParameters ??= array_map( + fn (TypeParameterDefinition $parameter) => new NpdTypeParameterReflection($parameter, $this, $this->staticType), + $this->definition->typeParameters + ); } public function uses(): UsedTraitsReflection @@ -123,49 +123,53 @@ public function uses(): UsedTraitsReflection } /** - * @return Collection> + * @return list> */ - public function declaredProperties(): Collection + public function declaredProperties(): array { - return $this->declaredProperties ??= $this->definition - ->properties - ->map(fn (PropertyDefinition $property) => new NpdPropertyReflection($property, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->declaredProperties ??= array_map( + fn (PropertyDefinition $property) => new NpdPropertyReflection($property, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->properties, + ); } /** - * @return Collection>> + * @return list>> */ - public function properties(): Collection + public function properties(): array { return $this->properties ??= collect([ ...$this->propertiesFromTraits($this->uses(), $this->staticType, $this->reflector), ...$this->declaredProperties(), ]) ->keyBy(fn (PropertyReflection $property) => $property->name()) - ->values(); + ->values() + ->all(); } /** - * @return Collection> + * @return list> */ - public function declaredMethods(): Collection + public function declaredMethods(): array { - return $this->declaredMethods ??= $this->definition - ->methods - ->map(fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap)); + return $this->declaredMethods ??= array_map( + fn (MethodDefinition $method) => new NpdMethodReflection($method, $this, $this->staticType, $this->resolvedTypeParameterMap), + $this->definition->methods + ); } /** - * @return Collection>> + * @return list>> */ - public function methods(): Collection + public function methods(): array { return $this->methods ??= collect([ ...$this->methodsFromTraits($this->uses(), $this->staticType, $this->reflector), ...$this->declaredMethods(), ]) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } public function isBuiltIn(): bool diff --git a/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitReflection.php b/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitReflection.php index 6070a10..f882828 100644 --- a/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitReflection.php +++ b/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitReflection.php @@ -8,14 +8,13 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; use GoodPhp\Reflection\Type\TypeProjector; -use Illuminate\Support\Collection; final class NpdUsedTraitReflection implements UsedTraitReflection { private readonly NamedType $trait; - /** @var Collection */ - private readonly Collection $aliases; + /** @var list */ + private readonly array $aliases; public function __construct( private readonly UsedTraitDefinition $definition, @@ -33,12 +32,13 @@ public function trait(): NamedType } /** - * @return Collection + * @return list */ - public function aliases(): Collection + public function aliases(): array { - return $this->aliases ??= $this->definition - ->aliases - ->map(fn (UsedTraitAliasDefinition $alias) => new NpdUsedTraitAliasReflection($alias)); + return $this->aliases ??= array_map( + fn (UsedTraitAliasDefinition $alias) => new NpdUsedTraitAliasReflection($alias), + $this->definition->aliases, + ); } } diff --git a/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitsReflection.php b/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitsReflection.php index 22a2480..c1e6610 100644 --- a/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitsReflection.php +++ b/src/NativePHPDoc/Reflection/Traits/NpdUsedTraitsReflection.php @@ -7,12 +7,11 @@ use GoodPhp\Reflection\Reflection\Traits\UsedTraitsReflection; use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; -use Illuminate\Support\Collection; final class NpdUsedTraitsReflection implements UsedTraitsReflection { - /** @var Collection */ - private readonly Collection $traits; + /** @var list */ + private readonly array $traits; public function __construct( private readonly UsedTraitsDefinition $definition, @@ -21,19 +20,20 @@ public function __construct( ) {} /** - * @return Collection + * @return list */ - public function traits(): Collection + public function traits(): array { - return $this->traits ??= $this->definition - ->traits - ->map(fn (UsedTraitDefinition $trait) => new NpdUsedTraitReflection($trait, $this->resolvedTypeParameterMap, $this->staticType)); + return $this->traits ??= array_map( + fn (UsedTraitDefinition $trait) => new NpdUsedTraitReflection($trait, $this->resolvedTypeParameterMap, $this->staticType), + $this->definition->traits, + ); } /** - * @return Collection> + * @return array> */ - public function excludedTraitMethods(): Collection + public function excludedTraitMethods(): array { return $this->definition->excludedTraitMethods; } diff --git a/src/Reflection/Attributes/ArrayAttributes.php b/src/Reflection/Attributes/ArrayAttributes.php index fec4223..26a0145 100644 --- a/src/Reflection/Attributes/ArrayAttributes.php +++ b/src/Reflection/Attributes/ArrayAttributes.php @@ -3,9 +3,6 @@ namespace GoodPhp\Reflection\Reflection\Attributes; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; -use Illuminate\Support\ItemNotFoundException; -use Illuminate\Support\MultipleItemsFoundException; class ArrayAttributes implements Attributes { @@ -19,7 +16,7 @@ public function __construct( /** * @param class-string|null $className */ - public function has(string $className = null): bool + public function has(?string $className = null): bool { $attributes = $className ? $this->attributes[$className] ?? [] : $this->attributes; @@ -31,11 +28,11 @@ public function has(string $className = null): bool * * @param class-string|null $className * - * @return ($className is null ? Collection : Collection) + * @return ($className is null ? list : list) */ - public function all(string $className = null): Collection + public function all(?string $className = null): array { - /** @var Collection */ + /** @var list */ return $this->resolveAttributesFiltered($className); } @@ -48,13 +45,15 @@ public function all(string $className = null): Collection */ public function sole(string $className): ?object { - try { - return $this->resolveAttributesFiltered($className)->sole(); - } catch (MultipleItemsFoundException) { - throw new MultipleAttributesFoundException($className); - } catch (ItemNotFoundException) { - return null; - } + $attributes = $this->resolveAttributesFiltered($className); + + $count = count($attributes); + + return match ($count) { + 0 => null, + 1 => $attributes[0], + default => throw new MultipleAttributesFoundException($className), + }; } public function allEqual(Attributes $attributes): bool @@ -62,7 +61,7 @@ public function allEqual(Attributes $attributes): bool $thisAttributes = $this->all(); $otherAttributes = $attributes->all(); - if ($thisAttributes->count() !== $otherAttributes->count()) { + if (count($thisAttributes) !== count($otherAttributes)) { return false; } @@ -83,7 +82,7 @@ public function allEqual(Attributes $attributes): bool return false; } - $otherAttributes->forget($otherAttributeKey); + unset($otherAttributes[$otherAttributeKey]); } return true; @@ -94,13 +93,14 @@ public function allEqual(Attributes $attributes): bool * * @param class-string|null $className * - * @return Collection + * @return list */ - private function resolveAttributesFiltered(string $className = null): Collection + private function resolveAttributesFiltered(?string $className = null): array { $attributes = $className ? $this->attributes[$className] ?? [] : Arr::flatten($this->attributes); - return collect( + /* @phpstan-ignore return.type */ + return array_values( is_array($attributes) ? $attributes : $attributes() ); } diff --git a/src/Reflection/Attributes/Attributes.php b/src/Reflection/Attributes/Attributes.php index cb653b6..119a476 100644 --- a/src/Reflection/Attributes/Attributes.php +++ b/src/Reflection/Attributes/Attributes.php @@ -2,7 +2,6 @@ namespace GoodPhp\Reflection\Reflection\Attributes; -use Illuminate\Support\Collection; use Stringable; interface Attributes extends Stringable @@ -10,16 +9,16 @@ interface Attributes extends Stringable /** * @param class-string|null $className */ - public function has(string $className = null): bool; + public function has(?string $className = null): bool; /** * @template AttributeType of object * * @param class-string|null $className * - * @return ($className is null ? Collection : Collection) + * @return ($className is null ? list : list) */ - public function all(string $className = null): Collection; + public function all(?string $className = null): array; /** * @template AttributeType of object diff --git a/src/Reflection/Attributes/MultipleAttributesFoundException.php b/src/Reflection/Attributes/MultipleAttributesFoundException.php index ffd15e3..c5c952a 100644 --- a/src/Reflection/Attributes/MultipleAttributesFoundException.php +++ b/src/Reflection/Attributes/MultipleAttributesFoundException.php @@ -7,7 +7,7 @@ class MultipleAttributesFoundException extends RuntimeException { - public function __construct(string $className, Throwable $previous = null) + public function __construct(string $className, ?Throwable $previous = null) { parent::__construct("Expected to only have one #[{$className}] attribute, but found more.", 0, $previous); } diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 8e51122..485dbcd 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -8,7 +8,6 @@ use GoodPhp\Reflection\Reflection\Traits\UsedTraitsReflection; use GoodPhp\Reflection\Reflection\TypeParameters\HasTypeParameters; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template ReflectableType of object @@ -25,9 +24,9 @@ public function withStaticType(NamedType $staticType): static; public function extends(): ?NamedType; /** - * @return Collection + * @return list */ - public function implements(): Collection; + public function implements(): array; public function uses(): UsedTraitsReflection; diff --git a/src/Reflection/EnumReflection.php b/src/Reflection/EnumReflection.php index e30ceb9..623835d 100644 --- a/src/Reflection/EnumReflection.php +++ b/src/Reflection/EnumReflection.php @@ -6,7 +6,6 @@ use GoodPhp\Reflection\Reflection\Methods\HasMethods; use GoodPhp\Reflection\Reflection\Traits\UsedTraitsReflection; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template ReflectableType of \UnitEnum @@ -19,9 +18,9 @@ interface EnumReflection extends TypeReflection, HasAttributes, HasMethods public function withStaticType(NamedType $staticType): static; /** - * @return Collection + * @return list */ - public function implements(): Collection; + public function implements(): array; public function uses(): UsedTraitsReflection; diff --git a/src/Reflection/InheritsClassMembers.php b/src/Reflection/InheritsClassMembers.php index 4190c7a..34a2fa7 100644 --- a/src/Reflection/InheritsClassMembers.php +++ b/src/Reflection/InheritsClassMembers.php @@ -10,7 +10,6 @@ use GoodPhp\Reflection\Reflection\Traits\UsedTraitsReflection; use GoodPhp\Reflection\Reflector; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; use Webmozart\Assert\Assert; /** @@ -19,14 +18,13 @@ trait InheritsClassMembers { /** - * @param Collection|NamedType $types + * @param list|NamedType $types * - * @return Collection>> + * @return list>> */ - protected function propertiesFromTypes(Collection|NamedType $types, NamedType $staticType, Reflector $reflector): Collection + protected function propertiesFromTypes(array|NamedType $types, NamedType $staticType, Reflector $reflector): array { - /** @var Collection>> */ - return Collection::wrap($types) + return collect(is_array($types) ? $types : [$types]) ->flatMap(function (NamedType $type) use ($staticType, $reflector) { $reflection = $reflector->forNamedType($type); @@ -37,30 +35,31 @@ protected function propertiesFromTypes(Collection|NamedType $types, NamedType $s ->properties(); }) ->keyBy(fn (PropertyReflection $property) => $property->name()) - ->values(); + ->values() + ->all(); } /** - * @return Collection>> + * @return list>> */ - protected function propertiesFromTraits(UsedTraitsReflection $usedTraits, NamedType $staticType, Reflector $reflector): Collection + protected function propertiesFromTraits(UsedTraitsReflection $usedTraits, NamedType $staticType, Reflector $reflector): array { - $types = $usedTraits - ->traits() - ->map(fn (UsedTraitReflection $usedTrait) => $usedTrait->trait()); + $types = array_map( + fn (UsedTraitReflection $usedTrait) => $usedTrait->trait(), + $usedTraits->traits() + ); return $this->propertiesFromTypes($types, $staticType, $reflector); } /** - * @param Collection|NamedType $types + * @param list|NamedType $types * - * @return Collection>> + * @return list>> */ - protected function methodsFromTypes(Collection|NamedType $types, NamedType $staticType, Reflector $reflector): Collection + protected function methodsFromTypes(array|NamedType $types, NamedType $staticType, Reflector $reflector): array { - /** @var Collection>> */ - return Collection::wrap($types) + return collect(is_array($types) ? $types : [$types]) ->flatMap(function (NamedType $type) use ($staticType, $reflector) { $reflection = $reflector->forNamedType($type); @@ -71,47 +70,46 @@ protected function methodsFromTypes(Collection|NamedType $types, NamedType $stat ->methods(); }) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } /** - * @return Collection>> + * @return list>> */ - protected function methodsFromTraits(UsedTraitsReflection $usedTraits, NamedType $staticType, Reflector $reflector): Collection + protected function methodsFromTraits(UsedTraitsReflection $usedTraits, NamedType $staticType, Reflector $reflector): array { - return $usedTraits - ->traits() + return collect($usedTraits->traits()) ->flatMap(function (UsedTraitReflection $usedTrait) use ($staticType, $reflector, $usedTraits) { - $traitExcludedMethods = $usedTraits->excludedTraitMethods()[$usedTrait->trait()->name] ?? collect(); + $traitExcludedMethods = $usedTraits->excludedTraitMethods()[$usedTrait->trait()->name] ?? []; $reflection = $reflector->forNamedType($usedTrait->trait()); Assert::isInstanceOf($reflection, TraitReflection::class); /** @var TraitReflection $reflection */ - return $reflection - ->withStaticType($staticType) - ->methods() - ->reject(fn (MethodReflection $method) => $traitExcludedMethods->contains($method->name())) + return collect($reflection->withStaticType($staticType)->methods()) + ->reject(fn (MethodReflection $method) => in_array($method->name(), $traitExcludedMethods, true)) ->flatMap(function (MethodReflection $method) use ($usedTrait) { /** @var MethodReflection> $method */ return $this->aliasMethod($method, $usedTrait->aliases()); }); }) ->keyBy(fn (MethodReflection $method) => $method->name()) - ->values(); + ->values() + ->all(); } /** * @param MethodReflection> $method - * @param Collection $aliases + * @param list $aliases * - * @return array>> + * @return list>> */ - private function aliasMethod(MethodReflection $method, Collection $aliases): array + private function aliasMethod(MethodReflection $method, array $aliases): array { $result = [$method->name() => $method]; - $aliasesForMethod = $aliases->filter(fn (UsedTraitAliasReflection $alias) => $alias->name() === $method->name()); + $aliasesForMethod = array_filter($aliases, fn (UsedTraitAliasReflection $alias) => $alias->name() === $method->name()); foreach ($aliasesForMethod as $alias) { $newName = $alias->newName() ?? $alias->name(); diff --git a/src/Reflection/InterfaceReflection.php b/src/Reflection/InterfaceReflection.php index 0ec8479..d183e03 100644 --- a/src/Reflection/InterfaceReflection.php +++ b/src/Reflection/InterfaceReflection.php @@ -6,7 +6,6 @@ use GoodPhp\Reflection\Reflection\Methods\HasMethods; use GoodPhp\Reflection\Reflection\TypeParameters\HasTypeParameters; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; /** * @template ReflectableType of object @@ -20,9 +19,9 @@ interface InterfaceReflection extends TypeReflection, HasAttributes, HasTypePara public function withStaticType(NamedType $staticType): static; /** - * @return Collection + * @return list */ - public function extends(): Collection; + public function extends(): array; public function isBuiltIn(): bool; } diff --git a/src/Reflection/MethodReflection.php b/src/Reflection/MethodReflection.php index 429ac7d..08b7ec6 100644 --- a/src/Reflection/MethodReflection.php +++ b/src/Reflection/MethodReflection.php @@ -7,7 +7,6 @@ use GoodPhp\Reflection\Reflection\TypeParameters\HasTypeParameters; use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; use Stringable; /** @@ -24,9 +23,9 @@ public function withStaticType(NamedType $staticType): static; public function name(): string; /** - * @return Collection>> + * @return list>> */ - public function parameters(): Collection; + public function parameters(): array; public function returnType(): ?Type; diff --git a/src/Reflection/Methods/HasMethods.php b/src/Reflection/Methods/HasMethods.php index eb145eb..2188928 100644 --- a/src/Reflection/Methods/HasMethods.php +++ b/src/Reflection/Methods/HasMethods.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\Reflection\HasName; use GoodPhp\Reflection\Reflection\MethodReflection; -use Illuminate\Support\Collection; /** * @template ReflectableType of object @@ -12,12 +11,12 @@ interface HasMethods extends HasName { /** - * @return Collection> + * @return list> */ - public function declaredMethods(): Collection; + public function declaredMethods(): array; /** - * @return Collection>> + * @return list>> */ - public function methods(): Collection; + public function methods(): array; } diff --git a/src/Reflection/Properties/HasProperties.php b/src/Reflection/Properties/HasProperties.php index 2415e39..ae2f556 100644 --- a/src/Reflection/Properties/HasProperties.php +++ b/src/Reflection/Properties/HasProperties.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\Reflection\HasName; use GoodPhp\Reflection\Reflection\PropertyReflection; -use Illuminate\Support\Collection; /** * @template ReflectableType of object @@ -12,12 +11,12 @@ interface HasProperties extends HasName { /** - * @return Collection> + * @return list> */ - public function declaredProperties(): Collection; + public function declaredProperties(): array; /** - * @return Collection>> + * @return list>> */ - public function properties(): Collection; + public function properties(): array; } diff --git a/src/Reflection/PropertyReflection.php b/src/Reflection/PropertyReflection.php index 9675a5f..f0f48b0 100644 --- a/src/Reflection/PropertyReflection.php +++ b/src/Reflection/PropertyReflection.php @@ -33,7 +33,7 @@ public function isPromoted(): bool; * * @return FunctionParameterReflection>>|null */ - public function promotedParameter(): FunctionParameterReflection|null; + public function promotedParameter(): ?FunctionParameterReflection; /** * @param ReflectableType $receiver diff --git a/src/Reflection/SpecialTypeReflection.php b/src/Reflection/SpecialTypeReflection.php index bdc2014..42e2ba8 100644 --- a/src/Reflection/SpecialTypeReflection.php +++ b/src/Reflection/SpecialTypeReflection.php @@ -4,7 +4,6 @@ use GoodPhp\Reflection\Reflection\TypeParameters\HasTypeParameters; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; /** * @template ReflectableType @@ -15,7 +14,7 @@ interface SpecialTypeReflection extends TypeReflection, HasTypeParameters { /** - * @return Collection + * @return list */ - public function superTypes(): Collection; + public function superTypes(): array; } diff --git a/src/Reflection/Traits/TraitAliasesMethodReflection.php b/src/Reflection/Traits/TraitAliasesMethodReflection.php index aa1842b..052e3cd 100644 --- a/src/Reflection/Traits/TraitAliasesMethodReflection.php +++ b/src/Reflection/Traits/TraitAliasesMethodReflection.php @@ -7,7 +7,6 @@ use GoodPhp\Reflection\Reflection\Methods\HasMethods; use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; /** * @template-contravariant ReflectableType of object @@ -46,12 +45,12 @@ public function attributes(): Attributes return $this->method->attributes(); } - public function typeParameters(): Collection + public function typeParameters(): array { return $this->method->typeParameters(); } - public function parameters(): Collection + public function parameters(): array { return $this->method->parameters(); } diff --git a/src/Reflection/Traits/UsedTraitReflection.php b/src/Reflection/Traits/UsedTraitReflection.php index c9cb36e..c294e02 100644 --- a/src/Reflection/Traits/UsedTraitReflection.php +++ b/src/Reflection/Traits/UsedTraitReflection.php @@ -3,14 +3,13 @@ namespace GoodPhp\Reflection\Reflection\Traits; use GoodPhp\Reflection\Type\NamedType; -use Illuminate\Support\Collection; interface UsedTraitReflection { public function trait(): NamedType; /** - * @return Collection + * @return list */ - public function aliases(): Collection; + public function aliases(): array; } diff --git a/src/Reflection/Traits/UsedTraitsReflection.php b/src/Reflection/Traits/UsedTraitsReflection.php index fb8beaf..3642803 100644 --- a/src/Reflection/Traits/UsedTraitsReflection.php +++ b/src/Reflection/Traits/UsedTraitsReflection.php @@ -2,17 +2,15 @@ namespace GoodPhp\Reflection\Reflection\Traits; -use Illuminate\Support\Collection; - interface UsedTraitsReflection { /** - * @return Collection + * @return list */ - public function traits(): Collection; + public function traits(): array; /** - * @return Collection> + * @return array> */ - public function excludedTraitMethods(): Collection; + public function excludedTraitMethods(): array; } diff --git a/src/Reflection/TypeParameters/HasTypeParameters.php b/src/Reflection/TypeParameters/HasTypeParameters.php index 218edee..7bbc3c6 100644 --- a/src/Reflection/TypeParameters/HasTypeParameters.php +++ b/src/Reflection/TypeParameters/HasTypeParameters.php @@ -2,15 +2,13 @@ namespace GoodPhp\Reflection\Reflection\TypeParameters; -use Illuminate\Support\Collection; - /** * @template-covariant DeclaringStructureReflection of HasTypeParameters */ interface HasTypeParameters { /** - * @return Collection> + * @return list> */ - public function typeParameters(): Collection; + public function typeParameters(): array; } diff --git a/src/Reflector.php b/src/Reflector.php index f9de156..220f85b 100644 --- a/src/Reflector.php +++ b/src/Reflector.php @@ -6,7 +6,6 @@ use GoodPhp\Reflection\Type\NamedType; use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeComparator; -use Illuminate\Support\Collection; interface Reflector { @@ -18,9 +17,9 @@ public function typeComparator(): TypeComparator; public function forNamedType(NamedType $type): TypeReflection; /** - * @param Collection $arguments + * @param list $arguments * * @return TypeReflection */ - public function forType(string $name, Collection $arguments = new Collection()): TypeReflection; + public function forType(string $name, array $arguments = []): TypeReflection; } diff --git a/src/ReflectorBuilder.php b/src/ReflectorBuilder.php index edff5ef..63d4784 100644 --- a/src/ReflectorBuilder.php +++ b/src/ReflectorBuilder.php @@ -23,6 +23,7 @@ use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\PhpDocParser; use PHPStan\PhpDocParser\Parser\TypeParser; +use PHPStan\PhpDocParser\ParserConfig; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\PhpFilesAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -33,7 +34,7 @@ class ReflectorBuilder private ?DefinitionProvider $definitionProvider = null; - public function withFileCache(string $path = null, DateInterval $ttl = null): self + public function withFileCache(?string $path = null, ?DateInterval $ttl = null): self { $path ??= sys_get_temp_dir() . '/good-php-reflection'; @@ -51,7 +52,7 @@ public function withFileCache(string $path = null, DateInterval $ttl = null): se )); } - public function withMemoryCache(int $maxItems = 100, DateInterval $ttl = null): self + public function withMemoryCache(int $maxItems = 100, ?DateInterval $ttl = null): self { return $this->withDefinitionProvider(new StaticCacheDefinitionProvider( $this->definitionProvider(), @@ -90,11 +91,12 @@ public function innerDefinitionProvider(): DefinitionProvider return $this->innerDefinitionProvider; } + $config = new ParserConfig(usedAttributes: []); $typeAliasResolver = new TypeAliasResolver(); - $constExprParser = new ConstExprParser(); - $typeParser = new TypeParser($constExprParser); - $phpDocParser = new PhpDocParser($typeParser, $constExprParser); - $lexer = new Lexer(); + $constExprParser = new ConstExprParser($config); + $typeParser = new TypeParser($config, $constExprParser); + $phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser); + $lexer = new Lexer($config); $phpDocStringParser = new PhpDocStringParser($lexer, $phpDocParser); return $this->innerDefinitionProvider = new NativePHPDocDefinitionProvider( diff --git a/src/Type/Combinatorial/IntersectionType.php b/src/Type/Combinatorial/IntersectionType.php index c69cd4c..3e7d2cd 100644 --- a/src/Type/Combinatorial/IntersectionType.php +++ b/src/Type/Combinatorial/IntersectionType.php @@ -7,7 +7,7 @@ use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeExtensions; use GoodPhp\Reflection\Type\TypeUtil; -use Illuminate\Support\Collection; +use Illuminate\Support\Arr; use Webmozart\Assert\Assert; class IntersectionType implements Type @@ -15,17 +15,18 @@ class IntersectionType implements Type use TypeExtensions; /** - * @param Collection $types + * @param list $types */ public function __construct( - public Collection $types, + public array $types, ) { // Transform A&(B&C) into A&B&C - $this->types = $types->reduce(function (Collection $accumulator, Type $type) { + /* @phpstan-ignore assign.propertyType */ + $this->types = array_reduce($types, function (array $accumulator, Type $type) { $types = $type instanceof self ? $type->types : [$type]; - return $accumulator->concat($types); - }, new Collection()); + return [...$accumulator, ...$types]; + }, []); Assert::minCount($this->types, 2); } @@ -40,16 +41,15 @@ public function traverse(callable $callback): Type { $changed = false; - $types = $this->types - ->map(function (Type $type) use ($callback, &$changed) { - $newType = $callback($type); + $types = array_map(function (Type $type) use ($callback, &$changed) { + $newType = $callback($type); - if ($type !== $newType) { - $changed = true; - } + if ($type !== $newType) { + $changed = true; + } - return $newType; - }); + return $newType; + }, $this->types); if ($changed) { return new self($types); @@ -62,22 +62,25 @@ public function withoutType(Type|callable $filter): Type { $filter = $filter instanceof Type ? fn (Type $other) => $other->equals($filter) : $filter; - $types = $this->types - ->reject($filter) - ->values(); + $types = array_values( + array_filter($this->types, fn (Type $type) => !$filter($type)) + ); /** @var Type */ - return match ($types->count()) { + return match (count($types)) { 0 => NeverType::get(), - 1 => $types->first(), + 1 => Arr::first($types), default => new self($types) }; } public function __toString(): string { - return $this->types - ->map(fn (Type $type) => $type instanceof UnionType || $type instanceof self || $type instanceof NullableType ? "({$type})" : (string) $type) - ->join('&'); + $types = array_map( + fn (Type $type) => $type instanceof UnionType || $type instanceof self || $type instanceof NullableType ? "({$type})" : (string) $type, + $this->types + ); + + return implode('&', $types); } } diff --git a/src/Type/Combinatorial/TupleType.php b/src/Type/Combinatorial/TupleType.php index f18cd2f..6afa418 100644 --- a/src/Type/Combinatorial/TupleType.php +++ b/src/Type/Combinatorial/TupleType.php @@ -5,17 +5,16 @@ use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeExtensions; use GoodPhp\Reflection\Type\TypeUtil; -use Illuminate\Support\Collection; class TupleType implements Type { use TypeExtensions; /** - * @param Collection $types + * @param list $types */ public function __construct( - public Collection $types, + public array $types, ) {} public function equals(Type $other): bool @@ -28,16 +27,15 @@ public function traverse(callable $callback): Type { $changed = false; - $types = $this->types - ->map(function (Type $type) use ($callback, &$changed) { - $newType = $callback($type); + $types = array_map(function (Type $type) use ($callback, &$changed) { + $newType = $callback($type); - if ($type !== $newType) { - $changed = true; - } + if ($type !== $newType) { + $changed = true; + } - return $newType; - }); + return $newType; + }, $this->types); if ($changed) { return new self($types); @@ -48,9 +46,12 @@ public function traverse(callable $callback): Type public function __toString(): string { - $types = $this->types - ->map(fn (Type $type) => (string) $type) - ->join(', '); + $types = array_map( + fn (Type $type) => (string) $type, + $this->types + ); + + $types = implode(', ', $types); return "array{{$types}}"; } diff --git a/src/Type/Combinatorial/UnionType.php b/src/Type/Combinatorial/UnionType.php index d9072e0..d4ee622 100644 --- a/src/Type/Combinatorial/UnionType.php +++ b/src/Type/Combinatorial/UnionType.php @@ -7,7 +7,7 @@ use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeExtensions; use GoodPhp\Reflection\Type\TypeUtil; -use Illuminate\Support\Collection; +use Illuminate\Support\Arr; use Webmozart\Assert\Assert; class UnionType implements Type @@ -15,17 +15,18 @@ class UnionType implements Type use TypeExtensions; /** - * @param Collection $types + * @param list $types */ public function __construct( - public Collection $types, + public array $types, ) { // Transform A|(B|C) into A|B|C - $this->types = $types->reduce(function (Collection $accumulator, Type $type) { + /* @phpstan-ignore assign.propertyType */ + $this->types = array_reduce($types, function (array $accumulator, Type $type) { $types = $type instanceof self ? $type->types : [$type]; - return $accumulator->concat($types); - }, new Collection()); + return [...$accumulator, ...$types]; + }, []); Assert::minCount($this->types, 2); } @@ -40,16 +41,15 @@ public function traverse(callable $callback): Type { $changed = false; - $types = $this->types - ->map(function (Type $type) use ($callback, &$changed) { - $newType = $callback($type); + $types = array_map(function (Type $type) use ($callback, &$changed) { + $newType = $callback($type); - if ($type !== $newType) { - $changed = true; - } + if ($type !== $newType) { + $changed = true; + } - return $newType; - }); + return $newType; + }, $this->types); if ($changed) { return new self($types); @@ -62,22 +62,25 @@ public function withoutType(Type|callable $filter): Type { $filter = $filter instanceof Type ? fn (Type $other) => $other->equals($filter) : $filter; - $types = $this->types - ->reject($filter) - ->values(); + $types = array_values( + array_filter($this->types, fn (Type $type) => !$filter($type)) + ); /** @var Type */ - return match ($types->count()) { + return match (count($types)) { 0 => NeverType::get(), - 1 => $types->first(), + 1 => Arr::first($types), default => new self($types) }; } public function __toString(): string { - return $this->types - ->map(fn (Type $type) => $type instanceof self || $type instanceof IntersectionType || $type instanceof NullableType ? "({$type})" : (string) $type) - ->join('|'); + $types = array_map( + fn (Type $type) => $type instanceof self || $type instanceof IntersectionType || $type instanceof NullableType ? "({$type})" : (string) $type, + $this->types + ); + + return implode('|', $types); } } diff --git a/src/Type/NamedType.php b/src/Type/NamedType.php index b44ea89..057a743 100644 --- a/src/Type/NamedType.php +++ b/src/Type/NamedType.php @@ -2,7 +2,6 @@ namespace GoodPhp\Reflection\Type; -use Illuminate\Support\Collection; use Webmozart\Assert\Assert; class NamedType implements Type @@ -10,12 +9,12 @@ class NamedType implements Type use TypeExtensions; /** - * @param class-string|string $name - * @param Collection $arguments + * @param class-string|string $name + * @param list $arguments */ public function __construct( public readonly string $name, - public readonly Collection $arguments = new Collection(), + public readonly array $arguments = [], ) { Assert::false( in_array($name, [ @@ -33,9 +32,9 @@ public function __construct( } /** - * @param array|Collection|null $arguments + * @param list|null $arguments */ - public static function wrap(string|self $name, array|Collection $arguments = null): self + public static function wrap(string|self $name, ?array $arguments = null): self { if ($name instanceof self) { Assert::null($arguments, 'Arguments must be null when a NamedType instance is given.'); @@ -45,8 +44,9 @@ public static function wrap(string|self $name, array|Collection $arguments = nul return new self( $name, - Collection::wrap($arguments ?? [])->map( - fn (Type|string $type) => is_string($type) ? new self($type) : $type + array_map( + fn (Type|string $type) => is_string($type) ? new self($type) : $type, + $arguments ?? [] ) ); } @@ -62,16 +62,15 @@ public function traverse(callable $callback): Type { $changed = false; - $types = $this->arguments - ->map(function (Type $type) use ($callback, &$changed) { - $newType = $callback($type); + $types = array_map(function (Type $type) use ($callback, &$changed) { + $newType = $callback($type); - if ($type !== $newType) { - $changed = true; - } + if ($type !== $newType) { + $changed = true; + } - return $newType; - }); + return $newType; + }, $this->arguments); if ($changed) { return new self($this->name, $types); @@ -82,10 +81,11 @@ public function traverse(callable $callback): Type public function __toString(): string { - $arguments = $this->arguments - ->map(fn (Type $type) => (string) $type) - ->join(', '); + $arguments = array_map( + fn (Type $type) => (string) $type, + $this->arguments + ); - return $this->name . ($arguments ? '<' . $arguments . '>' : ''); + return $this->name . ($arguments ? '<' . implode(', ', $arguments) . '>' : ''); } } diff --git a/src/Type/PrimitiveType.php b/src/Type/PrimitiveType.php index d13b325..dae27b1 100644 --- a/src/Type/PrimitiveType.php +++ b/src/Type/PrimitiveType.php @@ -3,7 +3,6 @@ namespace GoodPhp\Reflection\Type; use GoodPhp\Reflection\Type\Combinatorial\UnionType; -use Illuminate\Support\Collection; final class PrimitiveType { @@ -29,7 +28,7 @@ public static function callable(Type|string $returnType, Type|string ...$paramet ]); } - public static function array(Type|string $value, Type|string $key = null): NamedType + public static function array(Type|string $value, Type|string|null $key = null): NamedType { return NamedType::wrap('array', [ $key ?? self::arrayKey(), @@ -37,7 +36,7 @@ public static function array(Type|string $value, Type|string $key = null): Named ]); } - public static function iterable(Type|string $value, Type|string $key = null): NamedType + public static function iterable(Type|string $value, Type|string|null $key = null): NamedType { return NamedType::wrap('iterable', [ $key ?? self::arrayKey(), @@ -72,11 +71,9 @@ public static function float(): NamedType private static function arrayKey(): UnionType { - return self::$arrayKey ??= new UnionType( - new Collection([ - self::integer(), - self::string(), - ]), - ); + return self::$arrayKey ??= new UnionType([ + self::integer(), + self::string(), + ]); } } diff --git a/src/Type/Template/TypeParameterMap.php b/src/Type/Template/TypeParameterMap.php index 191336a..c801530 100644 --- a/src/Type/Template/TypeParameterMap.php +++ b/src/Type/Template/TypeParameterMap.php @@ -5,7 +5,7 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition\TypeParameterDefinition; use GoodPhp\Reflection\Type\Combinatorial\TupleType; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; +use Illuminate\Support\Arr; use Webmozart\Assert\Assert; final class TypeParameterMap @@ -18,17 +18,21 @@ public function __construct( ) {} /** - * @param Type[] $arguments + * @param list $arguments * @param iterable $typeParameters */ public static function fromArguments(array $arguments, iterable $typeParameters): self { + if (!$arguments) { + return self::empty(); + } + $map = []; $i = 0; foreach ($typeParameters as $parameter) { if ($parameter->variadic) { - $map[$parameter->name] = new TupleType(collect(array_slice($arguments, $i))); + $map[$parameter->name] = new TupleType(array_slice($arguments, $i)); break; } @@ -46,24 +50,25 @@ public static function fromArguments(array $arguments, iterable $typeParameters) public static function empty(): self { - static $map; - - if (!$map) { - $map = new self([]); - } + /** @var self $map */ + static $map = new self([]); return $map; } /** - * @param iterable $typeParameters + * @param list $typeParameters * - * @return Collection + * @return list */ - public function toArguments(iterable $typeParameters): Collection + public function toArguments(array $typeParameters): array { - return Collection::wrap($typeParameters) - ->flatMap(function (TypeParameterDefinition $parameter) { + if (!$this->types) { + return []; + } + + return Arr::flatten( + array_map(function (TypeParameterDefinition $parameter) { $type = $this->types[$parameter->name] ?? null; if (!$type) { @@ -77,6 +82,8 @@ public function toArguments(iterable $typeParameters): Collection } return [$type]; - }); + }, $typeParameters), + depth: 1 + ); } } diff --git a/src/Type/TypeComparator.php b/src/Type/TypeComparator.php index e770d17..7371dbb 100644 --- a/src/Type/TypeComparator.php +++ b/src/Type/TypeComparator.php @@ -21,7 +21,6 @@ use GoodPhp\Reflection\Type\Special\VoidType; use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; -use Illuminate\Support\Collection; use InvalidArgumentException; use Tests\Integration\Type\TypeComparatorTest; @@ -43,10 +42,10 @@ public function accepts(Type $a, Type $b): bool $b instanceof VoidType => false, $a instanceof MixedType => true, $b instanceof MixedType => false, - $a instanceof IntersectionType => $a->types->every(fn (Type $type) => $this->accepts($type, $b)), - $b instanceof IntersectionType => $b->types->some(fn (Type $type) => $this->accepts($a, $type)), - $a instanceof UnionType => $a->types->some(fn (Type $type) => $this->accepts($type, $b)), - $b instanceof UnionType => $b->types->every(fn (Type $type) => $this->accepts($a, $type)), + $a instanceof IntersectionType => collect($a->types)->every(fn (Type $type) => $this->accepts($type, $b)), + $b instanceof IntersectionType => collect($b->types)->some(fn (Type $type) => $this->accepts($a, $type)), + $a instanceof UnionType => collect($a->types)->some(fn (Type $type) => $this->accepts($type, $b)), + $b instanceof UnionType => collect($b->types)->every(fn (Type $type) => $this->accepts($a, $type)), $a instanceof NullableType => $this->accepts($a->innerType, $b instanceof NullableType ? $b->innerType : $b), $b instanceof NullableType => false, // `static` type is very much like a template type - in a sense that it should have been replaced with another @@ -80,12 +79,12 @@ public function acceptsNamed(NamedType $a, NamedType $b): bool $aReflection = $this->reflector->forNamedType($a); - $typeParameters = $aReflection instanceof HasTypeParameters ? $aReflection->typeParameters() : new Collection(); + $typeParameters = $aReflection instanceof HasTypeParameters ? $aReflection->typeParameters() : []; - /** @var array|TraitReflection|TraitReflection>, Type, Type}> $pairs */ + /** @var list|TraitReflection|TraitReflection>, Type, Type}> $pairs */ $pairs = []; - $aArguments = clone $a->arguments; - $bArguments = clone $b->arguments; + $aArguments = $a->arguments; + $bArguments = $b->arguments; foreach ($typeParameters as $i => $typeParameter) { if ($typeParameter->variadic()) { @@ -95,9 +94,9 @@ public function acceptsNamed(NamedType $a, NamedType $b): bool } /** @var Type|null $aArgument */ - $aArgument = $aArguments->shift(); + $aArgument = array_shift($aArguments); /** @var Type|null $bArgument */ - $bArgument = $bArguments->shift(); + $bArgument = array_shift($bArguments); if (!$aArgument || !$bArgument) { throw new InvalidArgumentException('Missing type argument #' . ($i + 1) . " {$typeParameter} when comparing named types '{$a}' and '{$b}'"); @@ -123,24 +122,36 @@ public function acceptsNamed(NamedType $a, NamedType $b): bool private function acceptsTuple(TupleType $a, Type $b): bool { - return $b instanceof TupleType && - $b->types->count() >= $a->types->count() && - $a->types->every(fn (Type $type, int $i) => $this->accepts($type, $b->types[$i])); + if (!$b instanceof TupleType) { + return false; + } + + if (count($b->types) < count($a->types)) { + return false; + } + + foreach ($a->types as $i => $type) { + if (!$this->accepts($type, $b->types[$i])) { + return false; + } + } + + return true; } private function findDescendant(NamedType $a, string $className): ?NamedType { $aReflection = $this->reflector->forNamedType($a); - /** @var NamedType[] $descendants */ + /** @var list $descendants */ $descendants = match (true) { - $aReflection instanceof ClassReflection => $aReflection - ->implements() - ->concat($aReflection->extends() ? [$aReflection->extends()] : []) - ->filter(), + $aReflection instanceof ClassReflection => [ + ...$aReflection->implements(), + ...($aReflection->extends() ? [$aReflection->extends()] : []), + ], $aReflection instanceof InterfaceReflection => $aReflection ->extends(), - $aReflection instanceof TraitReflection => new Collection(), + $aReflection instanceof TraitReflection => [], $aReflection instanceof EnumReflection => $aReflection ->implements(), $aReflection instanceof SpecialTypeReflection => $aReflection diff --git a/src/Type/TypeExtensions.php b/src/Type/TypeExtensions.php index 86c9ab1..4795873 100644 --- a/src/Type/TypeExtensions.php +++ b/src/Type/TypeExtensions.php @@ -5,6 +5,4 @@ /** * A set of "extension methods" for types. */ -trait TypeExtensions -{ -} +trait TypeExtensions {} diff --git a/src/Type/TypeProjector.php b/src/Type/TypeProjector.php index 8aba641..59d9381 100644 --- a/src/Type/TypeProjector.php +++ b/src/Type/TypeProjector.php @@ -7,13 +7,14 @@ use GoodPhp\Reflection\Type\Special\StaticType; use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Template\TypeParameterMap; +use Illuminate\Support\Arr; class TypeProjector { /** * @return ($type is NamedType ? NamedType : Type) */ - public static function templateTypes(Type $type, TypeParameterMap $typeParameterMap, NamedType $staticType = null): Type + public static function templateTypes(Type $type, TypeParameterMap $typeParameterMap, ?NamedType $staticType = null): Type { $mapped = TypeTraversingMapper::map($type, static function (Type $type, callable $traverse) use ($staticType, $typeParameterMap): Type { // todo: && !$type->isArgument() @@ -39,8 +40,9 @@ public static function templateTypes(Type $type, TypeParameterMap $typeParameter if ($type instanceof NamedType) { $changed = false; - $arguments = $type->arguments - ->flatMap(function (Type $type) use (&$changed) { + /** @var list $arguments */ + $arguments = Arr::flatten( + array_map(function (Type $type) use (&$changed) { if ($type instanceof ExpandedType && $type->innerType instanceof TupleType) { $changed = true; @@ -48,7 +50,9 @@ public static function templateTypes(Type $type, TypeParameterMap $typeParameter } return [$type]; - }); + }, $type->arguments), + 1 + ); if ($changed) { $type = new NamedType($type->name, $arguments); diff --git a/src/Type/TypeTraversingMapper.php b/src/Type/TypeTraversingMapper.php index 8eda1a4..497f51b 100644 --- a/src/Type/TypeTraversingMapper.php +++ b/src/Type/TypeTraversingMapper.php @@ -5,7 +5,7 @@ class TypeTraversingMapper { /** - * @param callable(Type $type, callable(Type): Type $traverse): Type $callback + * @param callable(Type, callable(Type): Type): Type $callback */ private function __construct(private readonly mixed $callback) {} @@ -42,11 +42,11 @@ public static function map(Type $type, callable $cb): Type public function mapInternal(Type $type): Type { - return ($this->callback)($type, [$this, 'traverseInternal']); + return ($this->callback)($type, $this->traverseInternal(...)); } public function traverseInternal(Type $type): Type { - return $type->traverse([$this, 'mapInternal']); + return $type->traverse($this->mapInternal(...)); } } diff --git a/src/Type/TypeUtil.php b/src/Type/TypeUtil.php index c97728a..3bcf01e 100644 --- a/src/Type/TypeUtil.php +++ b/src/Type/TypeUtil.php @@ -2,17 +2,24 @@ namespace GoodPhp\Reflection\Type; -use Illuminate\Support\Collection; - class TypeUtil { /** - * @param Collection $types - * @param Collection $otherTypes + * @param list $types + * @param list $otherTypes */ - public static function allEqual(Collection $types, Collection $otherTypes): bool + public static function allEqual(array $types, array $otherTypes): bool { - return $types->count() === $otherTypes->count() && - $types->every(fn (Type $type, int $i) => $type->equals($otherTypes[$i])); + if (count($types) !== count($otherTypes)) { + return false; + } + + foreach ($types as $i => $type) { + if (!$type->equals($otherTypes[$i])) { + return false; + } + } + + return true; } } diff --git a/src/UnknownTypeException.php b/src/UnknownTypeException.php index 7abd400..fdb63d9 100644 --- a/src/UnknownTypeException.php +++ b/src/UnknownTypeException.php @@ -7,7 +7,7 @@ class UnknownTypeException extends RuntimeException { - public function __construct(string $type, Throwable $previous = null) + public function __construct(string $type, ?Throwable $previous = null) { parent::__construct("Unable to reflect type '{$type}'.", 0, $previous); } diff --git a/src/Util/Lazy/CallableLazy.php b/src/Util/Lazy/CallableLazy.php new file mode 100644 index 0000000..7b27c75 --- /dev/null +++ b/src/Util/Lazy/CallableLazy.php @@ -0,0 +1,52 @@ + + */ +class CallableLazy implements Lazy +{ + /** @var T */ + private $value; + + private bool $initialized = false; + + /** + * @param Closure(): T $resolveValue + */ + public function __construct( + private readonly Closure $resolveValue + ) {} + + public function value() + { + $this->initialize(); + + return $this->value; + } + + public function isInitialized(): bool + { + return $this->initialized; + } + + /** + * Initialize the lazy by resolving the value. Will not do anything if called twice. + */ + private function initialize(): void + { + if ($this->isInitialized()) { + return; + } + + $this->value = ($this->resolveValue)(); + $this->initialized = true; + } +} diff --git a/src/Util/LateInitLazy.php b/src/Util/Lazy/LateInitLazy.php similarity index 90% rename from src/Util/LateInitLazy.php rename to src/Util/Lazy/LateInitLazy.php index a3640a1..7e53bce 100644 --- a/src/Util/LateInitLazy.php +++ b/src/Util/Lazy/LateInitLazy.php @@ -1,9 +1,8 @@ + */ +function lazy(Closure $resolve): Lazy +{ + return new CallableLazy($resolve); +} diff --git a/src/Util/ReflectionAssert.php b/src/Util/ReflectionAssert.php index 553c49a..34b12da 100644 --- a/src/Util/ReflectionAssert.php +++ b/src/Util/ReflectionAssert.php @@ -16,7 +16,7 @@ public static function namedType(Type $type, string $when = ''): void Assert::isInstanceOf( $type, NamedType::class, - 'Expected a named type (int, \stdClass, Collection), but [' . $type . '] given' . ($when ? " {$when}" : '') . '.' + 'Expected a named type (int, \stdClass, array), but [' . $type . '] given' . ($when ? " {$when}" : '') . '.' ); } } diff --git a/tests/Integration/Definition/FileModificationCacheDefinitionProviderTest.php b/tests/Integration/Definition/FileModificationCacheDefinitionProviderTest.php index 4a42d65..89f6a48 100644 --- a/tests/Integration/Definition/FileModificationCacheDefinitionProviderTest.php +++ b/tests/Integration/Definition/FileModificationCacheDefinitionProviderTest.php @@ -7,7 +7,6 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\DefinitionProvider; use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition\ClassTypeDefinition; use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition\UsedTraitsDefinition; -use Illuminate\Support\Collection; use Phake; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -37,12 +36,12 @@ protected function setUp(): void anonymous: false, final: true, abstract: false, - typeParameters: new Collection(), + typeParameters: [], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection() + properties: [], + methods: [] )); $this->definitionProvider = new FileModificationCacheDefinitionProvider( diff --git a/tests/Integration/Definition/NativePHPDocDefinitionProviderTest.php b/tests/Integration/Definition/NativePHPDocDefinitionProviderTest.php index 69abf9d..443a439 100644 --- a/tests/Integration/Definition/NativePHPDocDefinitionProviderTest.php +++ b/tests/Integration/Definition/NativePHPDocDefinitionProviderTest.php @@ -41,6 +41,8 @@ use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\PhpDocParser; use PHPStan\PhpDocParser\Parser\TypeParser; +use PHPStan\PhpDocParser\ParserConfig; +use PHPUnit\Framework\Attributes\DataProvider; use ReflectionMethod; use Tests\Integration\IntegrationTestCase; use Tests\Stubs\Classes\AllMissingTypes; @@ -73,11 +75,14 @@ protected function setUp(): void { parent::setUp(); + $parserConfig = new ParserConfig(usedAttributes: []); + $this->definitionProvider = new NativePHPDocDefinitionProvider( new PhpDocStringParser( - new Lexer(), + new Lexer($parserConfig), new PhpDocParser( - new TypeParser($constExprParser = new ConstExprParser()), + $parserConfig, + new TypeParser($parserConfig, $constExprParser = new ConstExprParser($parserConfig)), $constExprParser, ), ), @@ -103,7 +108,7 @@ public static function providesDefinitionForTypeProvider(): iterable anonymous: false, final: true, abstract: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'T', variadic: false, @@ -116,39 +121,39 @@ public static function providesDefinitionForTypeProvider(): iterable upperBound: PrimitiveType::integer(), variance: TemplateTypeVariance::COVARIANT, ), - ]), - extends: new NamedType(ParentClassStub::class, collect([ + ], + extends: new NamedType(ParentClassStub::class, [ new TemplateType( name: 'T' ), new NamedType(SomeStub::class), - ])), - implements: new Collection([ - new NamedType(ParentInterfaceStub::class, collect([ + ]), + implements: [ + new NamedType(ParentInterfaceStub::class, [ new TemplateType( name: 'S' ), new NamedType(SomeStub::class), - ])), - ]), + ]), + ], uses: new UsedTraitsDefinition( - traits: new Collection([ + traits: [ new UsedTraitDefinition( trait: NamedType::wrap(ParentTraitStub::class, [ new TemplateType('T'), SomeStub::class, ]), - aliases: new Collection([ + aliases: [ new UsedTraitAliasDefinition('traitMethod', null, ReflectionMethod::IS_PRIVATE), new UsedTraitAliasDefinition('traitMethod', 'traitMethodTwo', ReflectionMethod::IS_PROTECTED), - ]) + ] ), new UsedTraitDefinition( trait: NamedType::wrap(ParentTraitStub::class) ), - ]) + ] ), - properties: new Collection([ + properties: [ new PropertyDefinition( name: 'factories', type: PrimitiveType::array(new NamedType(SomeStub::class)), @@ -157,12 +162,12 @@ trait: NamedType::wrap(ParentTraitStub::class) ), new PropertyDefinition( name: 'generic', - type: new NamedType(DoubleTemplateType::class, collect([ + type: new NamedType(DoubleTemplateType::class, [ new NamedType(DateTime::class), new TemplateType( name: 'T' ), - ])), + ]), hasDefaultValue: false, isPromoted: false, ), @@ -172,54 +177,54 @@ trait: NamedType::wrap(ParentTraitStub::class) hasDefaultValue: false, isPromoted: true, ), - ]), - methods: new Collection([ + ], + methods: [ new MethodDefinition( name: '__construct', - typeParameters: collect(), - parameters: collect([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'promoted', type: new TemplateType('T'), hasDefaultValue: false, ), - ]), + ], returnType: null, ), new MethodDefinition( name: 'method', - typeParameters: collect([ + typeParameters: [ new TypeParameterDefinition( name: 'G', variadic: false, upperBound: null, variance: TemplateTypeVariance::INVARIANT, ), - ]), - parameters: collect([ + ], + parameters: [ new FunctionParameterDefinition( name: 'param', - type: new NamedType(DoubleTemplateType::class, collect([ + type: new NamedType(DoubleTemplateType::class, [ new NamedType(SomeStub::class), new TemplateType( name: 'T' ), - ])), + ]), hasDefaultValue: false, ), - ]), - returnType: new NamedType(Collection::class, collect([ + ], + returnType: new NamedType(Collection::class, [ new TemplateType( name: 'S' ), new TemplateType( name: 'G' ), - ])) + ]) ), new MethodDefinition( name: 'methodTwo', - typeParameters: collect([ + typeParameters: [ new TypeParameterDefinition( name: 'KValue', variadic: false, @@ -229,15 +234,15 @@ trait: NamedType::wrap(ParentTraitStub::class) new TypeParameterDefinition( name: 'K', variadic: false, - upperBound: new NamedType(SingleTemplateType::class, collect([ + upperBound: new NamedType(SingleTemplateType::class, [ new TemplateType( name: 'KValue' ), - ])), + ]), variance: TemplateTypeVariance::INVARIANT, ), - ]), - parameters: collect([ + ], + parameters: [ new FunctionParameterDefinition( name: 'param', type: new TemplateType( @@ -245,15 +250,15 @@ trait: NamedType::wrap(ParentTraitStub::class) ), hasDefaultValue: false, ), - ]), + ], returnType: new TemplateType( name: 'KValue' ) ), new MethodDefinition( name: 'self', - typeParameters: collect([]), - parameters: collect([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'parent', type: NamedType::wrap(ParentClassStub::class, [ @@ -262,12 +267,12 @@ trait: NamedType::wrap(ParentTraitStub::class) ]), hasDefaultValue: false, ), - ]), + ], returnType: new StaticType( new NamedType(ClassStub::class) ) ), - ]), + ], ), ]; @@ -280,13 +285,13 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection(), + typeParameters: [], extends: new NamedType(SomeStub::class), - implements: new Collection([ + implements: [ new NamedType(SingleTemplateType::class), - ]), + ], uses: new UsedTraitsDefinition(), - properties: new Collection([ + properties: [ new PropertyDefinition( name: 'property', type: null, @@ -305,12 +310,12 @@ trait: NamedType::wrap(ParentTraitStub::class) hasDefaultValue: false, isPromoted: true, ), - ]), - methods: new Collection([ + ], + methods: [ new MethodDefinition( name: '__construct', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'promoted', type: null, @@ -321,22 +326,22 @@ trait: NamedType::wrap(ParentTraitStub::class) type: new NullableType(PrimitiveType::integer()), hasDefaultValue: true, ), - ]), + ], returnType: null ), new MethodDefinition( name: 'test', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'something', type: null, hasDefaultValue: false, ), - ]), + ], returnType: null ), - ]), + ], ), ]; @@ -349,16 +354,16 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection(), + typeParameters: [], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection([ + properties: [], + methods: [ new MethodDefinition( name: 'f1', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', type: PrimitiveType::integer(), @@ -404,13 +409,13 @@ trait: NamedType::wrap(ParentTraitStub::class) type: MixedType::get(), hasDefaultValue: false, ), - ]), + ], returnType: VoidType::get(), ), new MethodDefinition( name: 'f2', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', type: new NullableType(PrimitiveType::integer()), @@ -419,27 +424,27 @@ trait: NamedType::wrap(ParentTraitStub::class) new FunctionParameterDefinition( name: 'p2', type: new NullableType( - new UnionType(new Collection([ + new UnionType([ PrimitiveType::string(), PrimitiveType::float(), - ])) + ]) ), hasDefaultValue: false, ), new FunctionParameterDefinition( name: 'p3', - type: new UnionType(new Collection([ + type: new UnionType([ PrimitiveType::string(), PrimitiveType::float(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( name: 'p4', - type: new UnionType(new Collection([ + type: new UnionType([ PrimitiveType::string(), PrimitiveType::boolean(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( @@ -447,18 +452,18 @@ trait: NamedType::wrap(ParentTraitStub::class) type: new NamedType(AllNativeTypes::class), hasDefaultValue: false, ), - ]), + ], returnType: NeverType::get(), ), new MethodDefinition( name: 'f3', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: new StaticType( new NamedType(AllNativeTypes::class) ), ), - ]), + ], ), ]; @@ -471,16 +476,16 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection(), + typeParameters: [], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection([ + properties: [], + methods: [ new MethodDefinition( name: 'f1', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', type: PrimitiveType::integer(), @@ -518,10 +523,10 @@ trait: NamedType::wrap(ParentTraitStub::class) ), new FunctionParameterDefinition( name: 'p8', - type: new UnionType(new Collection([ + type: new UnionType([ PrimitiveType::integer(), PrimitiveType::float(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( @@ -539,13 +544,13 @@ trait: NamedType::wrap(ParentTraitStub::class) type: PrimitiveType::float(), hasDefaultValue: false, ), - ]), + ], returnType: VoidType::get(), ), new MethodDefinition( name: 'f2', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', type: PrimitiveType::string(), @@ -586,13 +591,13 @@ trait: NamedType::wrap(ParentTraitStub::class) type: PrimitiveType::string(), hasDefaultValue: false, ), - ]), + ], returnType: NeverType::get(), ), new MethodDefinition( name: 'f3', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', type: PrimitiveType::boolean(), @@ -613,30 +618,30 @@ trait: NamedType::wrap(ParentTraitStub::class) type: PrimitiveType::boolean(), hasDefaultValue: false, ), - ]), + ], returnType: NeverType::get(), ), new MethodDefinition( name: 'f4', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', - type: new NamedType('array', new Collection([ - new UnionType(new Collection([ + type: new NamedType('array', [ + new UnionType([ PrimitiveType::integer(), PrimitiveType::string(), - ])), + ]), PrimitiveType::string(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( name: 'p2', - type: new UnionType(new Collection([ + type: new UnionType([ PrimitiveType::integer(), PrimitiveType::string(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( @@ -646,42 +651,42 @@ trait: NamedType::wrap(ParentTraitStub::class) ), new FunctionParameterDefinition( name: 'p4', - type: new NamedType('array', new Collection([ + type: new NamedType('array', [ PrimitiveType::string(), PrimitiveType::string(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( name: 'p5', - type: new NamedType('array', new Collection([ + type: new NamedType('array', [ PrimitiveType::integer(), PrimitiveType::string(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( name: 'p6', - type: new NamedType('array', new Collection([ + type: new NamedType('array', [ PrimitiveType::integer(), - ])), + ]), hasDefaultValue: false, ), - ]), + ], returnType: NeverType::get(), ), new MethodDefinition( name: 'f5', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'p1', - type: new UnionType(new Collection([ + type: new UnionType([ PrimitiveType::integer(), PrimitiveType::float(), PrimitiveType::string(), PrimitiveType::boolean(), - ])), + ]), hasDefaultValue: false, ), new FunctionParameterDefinition( @@ -714,38 +719,38 @@ trait: NamedType::wrap(ParentTraitStub::class) type: new NamedType('object'), hasDefaultValue: false, ), - ]), + ], returnType: NeverType::get(), ), new MethodDefinition( name: 'f6', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: NeverType::get(), ), new MethodDefinition( name: 'f7', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: new StaticType( new NamedType(AllPhpDocTypes::class) ), ), new MethodDefinition( name: 'f8', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: new NamedType(AllPhpDocTypes::class), ), new MethodDefinition( name: 'f9', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: new StaticType( new NamedType(AllPhpDocTypes::class) ), ), - ]), + ], ), ]; @@ -758,19 +763,19 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'T', variadic: false, upperBound: null, variance: TemplateTypeVariance::INVARIANT, ), - ]), + ], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection(), + properties: [], + methods: [], ), ]; @@ -783,19 +788,19 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'T', variadic: false, upperBound: null, variance: TemplateTypeVariance::CONTRAVARIANT, ), - ]), + ], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection(), + properties: [], + methods: [], ), ]; @@ -808,19 +813,19 @@ trait: NamedType::wrap(ParentTraitStub::class) anonymous: false, final: false, abstract: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'T', variadic: false, upperBound: null, variance: TemplateTypeVariance::COVARIANT, ), - ]), + ], extends: null, - implements: new Collection(), + implements: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection(), + properties: [], + methods: [], ), ]; @@ -830,22 +835,22 @@ trait: NamedType::wrap(ParentTraitStub::class) qualifiedName: NonGenericInterface::class, fileName: realpath(__DIR__ . '/../../Stubs/Interfaces/NonGenericInterface.php'), builtIn: false, - typeParameters: new Collection(), - extends: new Collection(), - methods: new Collection([ + typeParameters: [], + extends: [], + methods: [ new MethodDefinition( name: 'function', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'i', type: PrimitiveType::string(), hasDefaultValue: false, ), - ]), + ], returnType: MixedType::get(), ), - ]), + ], ), ]; @@ -855,16 +860,16 @@ trait: NamedType::wrap(ParentTraitStub::class) qualifiedName: SingleTemplateType::class, fileName: realpath(__DIR__ . '/../../Stubs/Interfaces/SingleTemplateType.php'), builtIn: false, - typeParameters: new Collection([ + typeParameters: [ new TypeParameterDefinition( name: 'T', variadic: false, upperBound: null, variance: TemplateTypeVariance::INVARIANT, ), - ]), - extends: new Collection(), - methods: new Collection(), + ], + extends: [], + methods: [], ), ]; @@ -874,17 +879,17 @@ trait: NamedType::wrap(ParentTraitStub::class) qualifiedName: TraitWithoutProperties::class, fileName: realpath(__DIR__ . '/../../Stubs/Traits/TraitWithoutProperties.php'), builtIn: false, - typeParameters: new Collection(), + typeParameters: [], uses: new UsedTraitsDefinition(), - properties: new Collection(), - methods: new Collection([ + properties: [], + methods: [ new MethodDefinition( name: 'otherFunction', - typeParameters: new Collection(), - parameters: new Collection(), + typeParameters: [], + parameters: [], returnType: new NamedType(Generator::class), ), - ]), + ], ), ]; @@ -895,14 +900,14 @@ trait: NamedType::wrap(ParentTraitStub::class) fileName: realpath(__DIR__ . '/../../Stubs/Enums/BackedEnum.php'), builtIn: false, backingType: PrimitiveType::string(), - implements: new Collection([ - new NamedType(SingleGenericInterface::class, new Collection([ + implements: [ + new NamedType(SingleGenericInterface::class, [ PrimitiveType::string(), - ])), + ]), new NamedType(\BackedEnum::class), - ]), + ], uses: new UsedTraitsDefinition(), - cases: new Collection([ + cases: [ new EnumCaseDefinition( name: 'FIRST', backingValue: 'first', @@ -911,8 +916,8 @@ trait: NamedType::wrap(ParentTraitStub::class) name: 'SECOND', backingValue: 'second', ), - ]), - methods: new Collection(), + ], + methods: [], ), ]; @@ -923,24 +928,24 @@ trait: NamedType::wrap(ParentTraitStub::class) fileName: realpath(__DIR__ . '/../../Stubs/Enums/UnitEnum.php'), builtIn: false, backingType: null, - implements: new Collection([ + implements: [ new NamedType(NonGenericInterface::class), new NamedType(\UnitEnum::class), - ]), + ], uses: new UsedTraitsDefinition( - traits: new Collection([ + traits: [ new UsedTraitDefinition( trait: NamedType::wrap(TraitWithoutProperties::class), ), new UsedTraitDefinition( trait: NamedType::wrap(TraitWithoutProperties::class), - aliases: new Collection([ + aliases: [ new UsedTraitAliasDefinition('otherFunction', 'otherOtherFunction'), - ]) + ] ), - ]) + ] ), - cases: new Collection([ + cases: [ new EnumCaseDefinition( name: 'FIRST', backingValue: null, @@ -949,28 +954,26 @@ trait: NamedType::wrap(TraitWithoutProperties::class), name: 'SECOND', backingValue: null, ), - ]), - methods: new Collection([ + ], + methods: [ new MethodDefinition( name: 'function', - typeParameters: new Collection(), - parameters: new Collection([ + typeParameters: [], + parameters: [ new FunctionParameterDefinition( name: 'i', type: PrimitiveType::string(), hasDefaultValue: false, ), - ]), + ], returnType: MixedType::get(), ), - ]), + ], ), ]; } - /** - * @dataProvider providesDefinitionForTypeProvider - */ + #[DataProvider('providesDefinitionForTypeProvider')] public function testProvidesDefinitionForType(string $type, TypeDefinition $expected): void { $actual = $this->definitionProvider->forType($type); diff --git a/tests/Integration/Reflection/ReflectionTest.php b/tests/Integration/Reflection/ReflectionTest.php index 3cb2a46..575c3e1 100644 --- a/tests/Integration/Reflection/ReflectionTest.php +++ b/tests/Integration/Reflection/ReflectionTest.php @@ -20,6 +20,7 @@ use GoodPhp\Reflection\Type\Template\TemplateType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; use Illuminate\Support\Collection; +use PHPUnit\Framework\Attributes\DataProvider; use ReflectionMethod; use stdClass; use Tests\Integration\IntegrationTestCase; @@ -49,11 +50,11 @@ function (ClassReflection $reflection) { self::assertFalse($reflection->isAbstract()); self::assertTrue($reflection->isFinal()); self::assertFalse($reflection->isBuiltIn()); - self::assertEquals(new Collection([new AttributeStub('123')]), $reflection->attributes()->all()); + self::assertEquals([new AttributeStub('123')], $reflection->attributes()->all()); self::assertTrue($reflection->attributes()->has()); self::assertEquals('#[\Tests\Stubs\AttributeStub(...)]', (string) $reflection->attributes()); - with($reflection->typeParameters(), function (Collection $parameters) { + with($reflection->typeParameters(), function (array $parameters) { self::assertCount(2, $parameters); self::assertContainsOnlyInstancesOf(TypeParameterReflection::class, $parameters); @@ -108,7 +109,7 @@ function (ClassReflection $reflection) { self::assertCount(0, $uses->excludedTraitMethods()); }); - with($reflection->declaredProperties(), function (Collection $properties) use ($reflection) { + with($reflection->declaredProperties(), function (array $properties) use ($reflection) { self::assertCount(3, $properties); self::assertContainsOnlyInstancesOf(PropertyReflection::class, $properties); @@ -122,7 +123,7 @@ function (ClassReflection $reflection) { self::assertSame($reflection->properties()[4], $properties[2]); }); - with($reflection->properties(), function (Collection $properties) use ($reflection) { + with($reflection->properties(), function (array $properties) use ($reflection) { self::assertCount(5, $properties); self::assertContainsOnlyInstancesOf(PropertyReflection::class, $properties); @@ -146,7 +147,7 @@ function (ClassReflection $reflection) { self::assertFalse($properties[2]->hasDefaultValue()); self::assertFalse($properties[2]->isPromoted()); self::assertNull($properties[2]->promotedParameter()); - self::assertEquals(new Collection([new AttributeStub('4')]), $properties[2]->attributes()->all()); + self::assertEquals([new AttributeStub('4')], $properties[2]->attributes()->all()); self::assertSame('generic', $properties[3]->name()); self::assertEquals(NamedType::wrap(DoubleTemplateType::class, [DateTime::class, stdClass::class]), $properties[3]->type()); @@ -160,10 +161,10 @@ function (ClassReflection $reflection) { self::assertFalse($properties[4]->hasDefaultValue()); self::assertTrue($properties[4]->isPromoted()); self::assertSame($reflection->constructor()->parameters()[0], $properties[4]->promotedParameter()); - self::assertEquals(new Collection([new AttributeStub('6')]), $properties[4]->attributes()->all()); + self::assertEquals([new AttributeStub('6')], $properties[4]->attributes()->all()); }); - with($reflection->declaredMethods(), function (Collection $methods) use ($reflection) { + with($reflection->declaredMethods(), function (array $methods) use ($reflection) { self::assertCount(4, $methods); self::assertContainsOnlyInstancesOf(MethodReflection::class, $methods); @@ -180,14 +181,14 @@ function (ClassReflection $reflection) { // self::assertSame($reflection->methods()[7], $methods[3]); }); - with($reflection->methods(), function (Collection $methods) use ($reflection) { + with($reflection->methods(), function (array $methods) use ($reflection) { self::assertCount(9, $methods); self::assertContainsOnlyInstancesOf(MethodReflection::class, $methods); self::assertSame('test', $methods[0]->name()); self::assertEmpty($methods[0]->attributes()->all()); self::assertEmpty($methods[0]->typeParameters()); - with($methods[0]->parameters(), function (Collection $parameters) { + with($methods[0]->parameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(FunctionParameterReflection::class, $parameters); @@ -232,22 +233,22 @@ function (ClassReflection $reflection) { self::assertSame('__construct', $methods[5]->name()); self::assertEmpty($methods[5]->attributes()->all()); self::assertEmpty($methods[5]->typeParameters()); - with($methods[5]->parameters(), function (Collection $parameters) { + with($methods[5]->parameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(FunctionParameterReflection::class, $parameters); self::assertEquals('promoted', $parameters[0]->name()); self::assertEquals(new NamedType(stdClass::class), $parameters[0]->type()); self::assertFalse($parameters[0]->hasDefaultValue()); - self::assertEquals(new Collection([new AttributeStub('6')]), $parameters[0]->attributes()->all()); + self::assertEquals([new AttributeStub('6')], $parameters[0]->attributes()->all()); self::assertSame('arg $promoted', (string) $parameters[0]); }); self::assertNull($methods[5]->returnType()); self::assertSame('__construct()', (string) $methods[5]); self::assertSame('method', $methods[6]->name()); - self::assertEquals(new Collection([new AttributeStub('5')]), $methods[6]->attributes()->all()); - with($methods[6]->typeParameters(), function (Collection $parameters) { + self::assertEquals([new AttributeStub('5')], $methods[6]->attributes()->all()); + with($methods[6]->typeParameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(TypeParameterReflection::class, $parameters); @@ -256,14 +257,14 @@ function (ClassReflection $reflection) { self::assertSame(MixedType::get(), $parameters[0]->upperBound()); self::assertSame(TemplateTypeVariance::INVARIANT, $parameters[0]->variance()); }); - with($methods[6]->parameters(), function (Collection $parameters) { + with($methods[6]->parameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(FunctionParameterReflection::class, $parameters); self::assertEquals('param', $parameters[0]->name()); self::assertEquals(NamedType::wrap(DoubleTemplateType::class, [SomeStub::class, stdClass::class]), $parameters[0]->type()); self::assertFalse($parameters[0]->hasDefaultValue()); - self::assertEquals(new Collection([new AttributeStub('6')]), $parameters[0]->attributes()->all()); + self::assertEquals([new AttributeStub('6')], $parameters[0]->attributes()->all()); self::assertSame('arg $param', (string) $parameters[0]); }); self::assertEquals(NamedType::wrap(Collection::class, [new TemplateType('S'), new TemplateType('G')]), $methods[6]->returnType()); @@ -271,7 +272,7 @@ function (ClassReflection $reflection) { self::assertSame('methodTwo', $methods[7]->name()); self::assertEmpty($methods[7]->attributes()->all()); - with($methods[7]->typeParameters(), function (Collection $parameters) { + with($methods[7]->typeParameters(), function (array $parameters) { self::assertCount(2, $parameters); self::assertContainsOnlyInstancesOf(TypeParameterReflection::class, $parameters); @@ -285,7 +286,7 @@ function (ClassReflection $reflection) { self::assertEquals(NamedType::wrap(SingleTemplateType::class, [new TemplateType('KValue')]), $parameters[1]->upperBound()); self::assertSame(TemplateTypeVariance::INVARIANT, $parameters[1]->variance()); }); - with($methods[7]->parameters(), function (Collection $parameters) { + with($methods[7]->parameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(FunctionParameterReflection::class, $parameters); @@ -301,7 +302,7 @@ function (ClassReflection $reflection) { self::assertSame('self', $methods[8]->name()); self::assertEmpty($methods[8]->attributes()->all()); self::assertEmpty($methods[8]->typeParameters()); - with($methods[8]->parameters(), function (Collection $parameters) { + with($methods[8]->parameters(), function (array $parameters) { self::assertCount(1, $parameters); self::assertContainsOnlyInstancesOf(FunctionParameterReflection::class, $parameters); @@ -318,9 +319,7 @@ function (ClassReflection $reflection) { ]; } - /** - * @dataProvider reflectsNamedTypeProvider - */ + #[DataProvider('reflectsNamedTypeProvider')] public function testReflectsNamedType(NamedType|string $type, callable $assertReflection): void { if (is_string($type)) { diff --git a/tests/Integration/Type/TypeComparatorTest.php b/tests/Integration/Type/TypeComparatorTest.php index b503444..2208fad 100644 --- a/tests/Integration/Type/TypeComparatorTest.php +++ b/tests/Integration/Type/TypeComparatorTest.php @@ -10,7 +10,7 @@ use GoodPhp\Reflection\Type\Special\NullableType; use GoodPhp\Reflection\Type\Type; use GoodPhp\Reflection\Type\TypeComparator; -use Illuminate\Support\Collection; +use PHPUnit\Framework\Attributes\DataProvider; use Tests\Integration\IntegrationTestCase; use Tests\Stubs\Classes\ClassStub; use Tests\Stubs\Classes\ParentClassStub; @@ -30,18 +30,16 @@ protected function setUp(): void $this->comparator = $this->reflector->typeComparator(); } - /** - * @dataProvider acceptsIntersectionProvider - * @dataProvider acceptsUnionProvider - * @dataProvider acceptsErrorProvider - * @dataProvider acceptsMixedProvider - * @dataProvider acceptsNeverProvider - * @dataProvider acceptsNullableProvider - * @dataProvider acceptsStaticProvider - * @dataProvider acceptsVoidProvider - * @dataProvider acceptsTemplateProvider - * @dataProvider acceptsNamedProvider - */ + #[DataProvider('acceptsProvider')] + #[DataProvider('acceptsUnionProvider')] + #[DataProvider('acceptsErrorProvider')] + #[DataProvider('acceptsMixedProvider')] + #[DataProvider('acceptsNeverProvider')] + #[DataProvider('acceptsNullableProvider')] + #[DataProvider('acceptsStaticProvider')] + #[DataProvider('acceptsVoidProvider')] + #[DataProvider('acceptsTemplateProvider')] + #[DataProvider('acceptsNamedProvider')] public function testAccepts(bool $expected, Type $a, Type $b): void { self::assertSame( @@ -51,7 +49,7 @@ public function testAccepts(bool $expected, Type $a, Type $b): void ); } - public static function acceptsIntersectionProvider(): iterable + public static function acceptsProvider(): iterable { yield from []; } @@ -111,48 +109,48 @@ public static function acceptsNullableProvider(): iterable yield '?string <= string|int|null' => [ false, new NullableType(PrimitiveType::string()), - new NullableType(new UnionType(new Collection([PrimitiveType::string(), PrimitiveType::integer()]))), + new NullableType(new UnionType([PrimitiveType::string(), PrimitiveType::integer()])), ]; yield 'string|int|null <= string' => [ true, - new NullableType(new UnionType(new Collection([PrimitiveType::string(), PrimitiveType::integer()]))), + new NullableType(new UnionType([PrimitiveType::string(), PrimitiveType::integer()])), new NullableType(PrimitiveType::string()), ]; yield '?string <= (?string)|int' => [ false, new NullableType(PrimitiveType::string()), - new UnionType(new Collection([new NullableType(PrimitiveType::string()), PrimitiveType::integer()])), + new UnionType([new NullableType(PrimitiveType::string()), PrimitiveType::integer()]), ]; yield '(?string)|int <= ?string' => [ true, - new UnionType(new Collection([new NullableType(PrimitiveType::string()), PrimitiveType::integer()])), + new UnionType([new NullableType(PrimitiveType::string()), PrimitiveType::integer()]), new NullableType(PrimitiveType::string()), ]; yield '?string <= ?(string&integer)' => [ true, new NullableType(PrimitiveType::string()), - new NullableType(new IntersectionType(new Collection([PrimitiveType::string(), PrimitiveType::integer()]))), + new NullableType(new IntersectionType([PrimitiveType::string(), PrimitiveType::integer()])), ]; yield '?(string&integer) <= ?string' => [ false, - new NullableType(new IntersectionType(new Collection([PrimitiveType::string(), PrimitiveType::integer()]))), + new NullableType(new IntersectionType([PrimitiveType::string(), PrimitiveType::integer()])), new NullableType(PrimitiveType::string()), ]; yield '?string <= (?string)&integer' => [ true, new NullableType(PrimitiveType::string()), - new IntersectionType(new Collection([new NullableType(PrimitiveType::string()), PrimitiveType::integer()])), + new IntersectionType([new NullableType(PrimitiveType::string()), PrimitiveType::integer()]), ]; yield '(?string)&integer <= ?string' => [ false, - new IntersectionType(new Collection([new NullableType(PrimitiveType::string()), PrimitiveType::integer()])), + new IntersectionType([new NullableType(PrimitiveType::string()), PrimitiveType::integer()]), new NullableType(PrimitiveType::string()), ]; } @@ -194,38 +192,38 @@ public static function acceptsNamedProvider(): iterable yield 'ClassStub <= ClassStub' => [ true, - new NamedType(ClassStub::class, new Collection([ + new NamedType(ClassStub::class, [ new NamedType(SomeStub::class), PrimitiveType::integer(), - ])), - new NamedType(ClassStub::class, new Collection([ + ]), + new NamedType(ClassStub::class, [ new NamedType(SomeStub::class), PrimitiveType::integer(), - ])), + ]), ]; yield 'callable(int): float <= Closure(float): int' => [ true, - new NamedType('callable', new Collection([ + new NamedType('callable', [ PrimitiveType::float(), PrimitiveType::integer(), - ])), - new NamedType(Closure::class, new Collection([ + ]), + new NamedType(Closure::class, [ PrimitiveType::integer(), PrimitiveType::float(), - ])), + ]), ]; yield 'callable(float): int <= Closure(int): float' => [ false, - new NamedType('callable', new Collection([ + new NamedType('callable', [ PrimitiveType::integer(), PrimitiveType::float(), - ])), - new NamedType(Closure::class, new Collection([ + ]), + new NamedType(Closure::class, [ PrimitiveType::float(), PrimitiveType::integer(), - ])), + ]), ]; } } diff --git a/tests/Stubs/Classes/ParentClassStub.php b/tests/Stubs/Classes/ParentClassStub.php index d1c3a10..872e032 100644 --- a/tests/Stubs/Classes/ParentClassStub.php +++ b/tests/Stubs/Classes/ParentClassStub.php @@ -19,5 +19,5 @@ class ParentClassStub */ public function parentMethod(): mixed {} - public function test(string $str = null): static {} + public function test(?string $str = null): static {} } diff --git a/tests/Unit/Type/Definition/TypeDefinition/TypeParameterDefinitionTest.php b/tests/Unit/Type/Definition/TypeDefinition/TypeParameterDefinitionTest.php index 61a56b5..f728871 100644 --- a/tests/Unit/Type/Definition/TypeDefinition/TypeParameterDefinitionTest.php +++ b/tests/Unit/Type/Definition/TypeDefinition/TypeParameterDefinitionTest.php @@ -5,6 +5,7 @@ use GoodPhp\Reflection\NativePHPDoc\Definition\TypeDefinition\TypeParameterDefinition; use GoodPhp\Reflection\Type\PrimitiveType; use GoodPhp\Reflection\Type\Template\TemplateTypeVariance; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -12,9 +13,7 @@ */ class TypeParameterDefinitionTest extends TestCase { - /** - * @dataProvider toStringProvider - */ + #[DataProvider('toStringProvider')] public function testToString(string $expected, TypeParameterDefinition $parameter): void { self::assertSame( diff --git a/tests/Unit/Type/Special/NullableTypeTest.php b/tests/Unit/Type/Special/NullableTypeTest.php index 28152ef..06d2afe 100644 --- a/tests/Unit/Type/Special/NullableTypeTest.php +++ b/tests/Unit/Type/Special/NullableTypeTest.php @@ -7,7 +7,7 @@ use GoodPhp\Reflection\Type\PrimitiveType; use GoodPhp\Reflection\Type\Special\NullableType; use GoodPhp\Reflection\Type\Type; -use Illuminate\Support\Collection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -15,9 +15,7 @@ */ class NullableTypeTest extends TestCase { - /** - * @dataProvider equalsProvider - */ + #[DataProvider('equalsProvider')] public function testEquals(bool $expected, NullableType $first, Type $second): void { self::assertSame( @@ -47,9 +45,7 @@ public static function equalsProvider(): iterable ]; } - /** - * @dataProvider stringRepresentationProvider - */ + #[DataProvider('stringRepresentationProvider')] public function testStringRepresentation(string $expected, Type $delegate): void { self::assertSame( @@ -67,18 +63,18 @@ public static function stringRepresentationProvider(): iterable yield 'intersection' => [ '?(int&float)', - new IntersectionType(new Collection([ + new IntersectionType([ PrimitiveType::integer(), PrimitiveType::float(), - ])), + ]), ]; yield 'union' => [ 'int|float|null', - new UnionType(new Collection([ + new UnionType([ PrimitiveType::integer(), PrimitiveType::float(), - ])), + ]), ]; } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8f9a918..2bef05e 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,6 +1,6 @@