allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\QA\Psalm\Plugin;
use CuyZ\Valinor\Mapper\ArgumentsMapper;
use Psalm\Internal\Type\Comparator\CallableTypeComparator;
use Psalm\Plugin\EventHandler\Event\MethodReturnTypeProviderEvent;
use Psalm\Plugin\EventHandler\MethodReturnTypeProviderInterface;
use Psalm\Type\Atomic\TClosure;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TMixed;
use Psalm\Type\Union;
use function count;
use function reset;
final class ArgumentsMapperPsalmPlugin implements MethodReturnTypeProviderInterface
{
public static function getClassLikeNames(): array
{
return [ArgumentsMapper::class];
}
public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Union
{
if ($event->getMethodNameLowercase() !== 'maparguments') {
return null;
}
$arguments = $event->getCallArgs();
if (count($arguments) === 0) {
return null;
}
$types = $event->getSource()->getNodeTypeProvider()->getType($arguments[0]->value);
if ($types === null) {
return null;
}
$types = $types->getAtomicTypes();
if (count($types) !== 1) {
return null;
}
$type = reset($types);
if ($type instanceof TKeyedArray) {
// Internal class usage, see https://github.com/vimeo/psalm/issues/8726
$type = CallableTypeComparator::getCallableFromAtomic($event->getSource()->getCodebase(), $type);
}
if (! $type instanceof TClosure) {
return null;
}
$typeParams = $type->params ?? [];
if ($typeParams === []) {
return null;
}
$params = [];
foreach ($typeParams as $param) {
$params[$param->name] = $param->type ?? new Union([new TMixed()]);
}
return new Union([new TKeyedArray($params)]);
}
}

View File

@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\QA\Psalm\Plugin;
use CuyZ\Valinor\Mapper\TreeMapper;
use Psalm\Plugin\EventHandler\Event\MethodReturnTypeProviderEvent;
use Psalm\Plugin\EventHandler\MethodReturnTypeProviderInterface;
use Psalm\Type;
use Psalm\Type\Atomic;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TDependentGetClass;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Union;
final class TreeMapperPsalmPlugin implements MethodReturnTypeProviderInterface
{
public static function getClassLikeNames(): array
{
return [TreeMapper::class];
}
public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Union
{
if ($event->getMethodNameLowercase() !== 'map') {
return null;
}
$arguments = $event->getCallArgs();
if (count($arguments) === 0) {
return null;
}
$type = $event->getSource()->getNodeTypeProvider()->getType($arguments[0]->value);
if (! $type) {
return null;
}
$types = [];
foreach ($type->getAtomicTypes() as $node) {
$inferred = self::type($node);
if ($inferred === null) {
return null;
}
$types[] = $inferred;
}
return Type::combineUnionTypeArray($types, $event->getSource()->getCodebase());
}
private static function type(Atomic $node): ?Union
{
return match (true) {
$node instanceof TLiteralString => Type::parseString($node->value),
$node instanceof TDependentGetClass => $node->as_type,
$node instanceof TClassString && $node->as_type => new Union([$node->as_type]),
default => null,
};
}
}