diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 70810c4f37..7193e871f6 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -84,7 +84,7 @@ jobs: name: "codeCoverage" path: "build" - - uses: codecov/codecov-action@v3.1.1 # upload the coverage to codecov + - uses: codecov/codecov-action@v3.1.2 # upload the coverage to codecov with: fail_ci_if_error: true # optional (default = false) # Do not upload in forks, and only on php8, latest deps diff --git a/phpstan.neon b/phpstan.neon index 91de17ea0a..02fbe8e28d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,6 +11,7 @@ parameters: level: 8 checkGenericClassInNonGenericObjectType: false reportUnmatchedIgnoredErrors: false + treatPhpDocTypesAsCertain: false ignoreErrors: - "#PHPDoc tag \\@throws with type Psr\\\\Container\\\\ContainerExceptionInterface is not subtype of Throwable#" - "#Parameter .* of class ReflectionMethod constructor expects string(\\|null)?, object\\|string given.#" diff --git a/src/Exceptions/GraphQLException.php b/src/Exceptions/GraphQLException.php index ca706d1021..c874291a5c 100644 --- a/src/Exceptions/GraphQLException.php +++ b/src/Exceptions/GraphQLException.php @@ -10,8 +10,13 @@ class GraphQLException extends Exception implements GraphQLExceptionInterface { /** @param array $extensions */ - public function __construct(string $message, int $code = 0, Throwable|null $previous = null, private string $category = 'Exception', private array $extensions = []) - { + public function __construct( + string $message, + int $code = 0, + Throwable|null $previous = null, + protected string $category = 'Exception', + protected array $extensions = [], + ) { parent::__construct($message, $code, $previous); } diff --git a/src/GlobControllerQueryProvider.php b/src/GlobControllerQueryProvider.php index 998044984f..05afa6476a 100644 --- a/src/GlobControllerQueryProvider.php +++ b/src/GlobControllerQueryProvider.php @@ -30,7 +30,7 @@ */ final class GlobControllerQueryProvider implements QueryProviderInterface { - /** @var array|null */ + /** @var array|null */ private array|null $instancesList = null; private ClassNameMapper $classNameMapper; private AggregateControllerQueryProvider|null $aggregateControllerQueryProvider = null; @@ -73,9 +73,11 @@ private function getAggregateControllerQueryProvider(): AggregateControllerQuery private function getInstancesList(): array { if ($this->instancesList === null) { - $this->instancesList = $this->cacheContract->get('globQueryProvider', function () { - return $this->buildInstancesList(); - }); + $this->instancesList = $this->cacheContract->get( + 'globQueryProvider', + fn () => $this->buildInstancesList(), + ); + if (! is_array($this->instancesList)) { throw new InvalidArgumentException('The instance list returned is not an array. There might be an issue with your PSR-16 cache implementation.'); } diff --git a/src/Mappers/Root/MyCLabsEnumTypeMapper.php b/src/Mappers/Root/MyCLabsEnumTypeMapper.php index 7ad0d1f9d8..c0c35aa168 100644 --- a/src/Mappers/Root/MyCLabsEnumTypeMapper.php +++ b/src/Mappers/Root/MyCLabsEnumTypeMapper.php @@ -34,18 +34,36 @@ class MyCLabsEnumTypeMapper implements RootTypeMapperInterface /** @var array */ private array $cacheByName = []; + /** @var array> */ + private array|null $nameToClassMapping = null; + /** @param NS[] $namespaces List of namespaces containing enums. Used when searching an enum by name. */ - public function __construct(private readonly RootTypeMapperInterface $next, private readonly AnnotationReader $annotationReader, private readonly CacheInterface $cacheService, private readonly array $namespaces) - { + public function __construct( + private readonly RootTypeMapperInterface $next, + private readonly AnnotationReader $annotationReader, + private readonly CacheInterface $cacheService, + private readonly array $namespaces, + ) { } - public function toGraphQLOutputType(Type $type, OutputType|null $subType, ReflectionMethod|ReflectionProperty $reflector, DocBlock $docBlockObj): OutputType&\GraphQL\Type\Definition\Type + public function toGraphQLOutputType( + Type $type, + OutputType|null $subType, + ReflectionMethod|ReflectionProperty $reflector, + DocBlock $docBlockObj, + ): OutputType&\GraphQL\Type\Definition\Type { $result = $this->map($type); return $result ?? $this->next->toGraphQLOutputType($type, $subType, $reflector, $docBlockObj); } - public function toGraphQLInputType(Type $type, InputType|null $subType, string $argumentName, ReflectionMethod|ReflectionProperty $reflector, DocBlock $docBlockObj): InputType&\GraphQL\Type\Definition\Type + public function toGraphQLInputType( + Type $type, + InputType|null $subType, + string $argumentName, + ReflectionMethod|ReflectionProperty $reflector, + DocBlock $docBlockObj, + ): InputType&\GraphQL\Type\Definition\Type { $result = $this->map($type); return $result ?? $this->next->toGraphQLInputType($type, $subType, $argumentName, $reflector, $docBlockObj); @@ -83,6 +101,7 @@ private function mapByClassName(string $enumClass): EnumType|null return $this->cacheByName[$type->name] = $this->cache[$enumClass] = $type; } + private function getTypeName(ReflectionClass $refClass): string { $enumType = $this->annotationReader->getEnumTypeAnnotation($refClass); @@ -131,9 +150,6 @@ public function mapNameToType(string $typeName): NamedType&\GraphQL\Type\Definit return $this->next->mapNameToType($typeName); } - /** @var array> */ - private array|null $nameToClassMapping = null; - /** * Go through all classes in the defined namespaces and loads the cache. * @@ -150,6 +166,7 @@ private function getNameToClassMapping(): array continue; } + /** @var class-string $className */ $nameToClassMapping[$this->getTypeName($classRef)] = $className; } } diff --git a/src/Utils/Namespaces/NS.php b/src/Utils/Namespaces/NS.php index cf15581051..21766b6757 100644 --- a/src/Utils/Namespaces/NS.php +++ b/src/Utils/Namespaces/NS.php @@ -30,21 +30,27 @@ final class NS private array|null $classes = null; /** @param string $namespace The namespace that contains the GraphQL types (they must have a `@Type` annotation) */ - public function __construct(private readonly string $namespace, private readonly CacheInterface $cache, private readonly ClassNameMapper $classNameMapper, private readonly int|null $globTTL, private readonly bool $recursive) - { + public function __construct( + private readonly string $namespace, + private readonly CacheInterface $cache, + private readonly ClassNameMapper $classNameMapper, + private readonly int|null $globTTL, + private readonly bool $recursive, + ) { } /** * Returns the array of globbed classes. * Only instantiable classes are returned. * - * @return array> Key: fully qualified class name + * @return array> Key: fully qualified class name */ public function getClassList(): array { if ($this->classes === null) { $this->classes = []; $explorer = new GlobClassExplorer($this->namespace, $this->cache, $this->globTTL, $this->classNameMapper, $this->recursive); + /** @var array $classes Override class-explorer lib */ $classes = $explorer->getClassMap(); foreach ($classes as $className => $phpFile) { if (! class_exists($className, false) && ! interface_exists($className, false)) { @@ -66,6 +72,7 @@ public function getClassList(): array } } + // @phpstan-ignore-next-line - Not sure why we cannot annotate the $classes above return $this->classes; }