Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHPStan level 7 #1045

Merged
merged 35 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0c57b2e
PHPStan level 7
spawnia Dec 27, 2021
121d0ab
Apply php-cs-fixer changes
spawnia Dec 27, 2021
321ad8a
fix
spawnia Dec 28, 2021
e6fc227
Merge remote-tracking branch 'origin/phpstan-level-7' into phpstan-le…
spawnia Dec 28, 2021
22dc4a2
Fix tests
spawnia Dec 28, 2021
e318013
fix codestyle
spawnia Dec 28, 2021
179772a
Make errors when parsing scalar literals more precise
spawnia Dec 29, 2021
2e6fbbc
Simplify
spawnia Dec 29, 2021
8b6b7f7
fix more errors
spawnia Dec 29, 2021
403d20f
more fixes
spawnia Dec 30, 2021
1435cf8
Apply php-cs-fixer changes
spawnia Dec 30, 2021
efacd38
fix more errors
spawnia Jan 1, 2022
683acf9
fix remaining errors
spawnia Jan 2, 2022
0d0bb1c
Upgrade
spawnia Jan 2, 2022
aac5ca5
precise
spawnia Jan 2, 2022
b90fc71
document
spawnia Jan 2, 2022
a4509a6
Merge branch 'master' into phpstan-level-7
spawnia Jan 2, 2022
4002a20
ignore phpstan bug through baseline
spawnia Jan 2, 2022
8ff28df
safety first
spawnia Jan 2, 2022
9858dda
Apply php-cs-fixer changes
spawnia Jan 2, 2022
bcc5135
Update src/Utils/Utils.php
spawnia Jan 4, 2022
8185809
Update src/Language/Lexer.php
spawnia Jan 4, 2022
5ebf5f0
Apply php-cs-fixer changes
spawnia Jan 4, 2022
7e86cf2
Fully type AST nodes
spawnia Jan 4, 2022
e82e388
Replace @var with assert()
spawnia Jan 4, 2022
db07d73
Apply php-cs-fixer changes
spawnia Jan 4, 2022
cb06139
move some ignores to baseline
spawnia Jan 4, 2022
f7982f1
Merge remote-tracking branch 'origin/phpstan-level-7' into phpstan-le…
spawnia Jan 4, 2022
1db08f7
or null
spawnia Jan 4, 2022
7db9ec1
Apply php-cs-fixer changes
spawnia Jan 4, 2022
5c60f6c
fix tests
spawnia Jan 4, 2022
bd414b8
doc
spawnia Jan 4, 2022
5db2f9d
simplify
spawnia Jan 4, 2022
251467d
string literal
spawnia Jan 4, 2022
4d1cbc5
consider trace might miss file,line
spawnia Jan 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You can find and compare releases at the [GitHub release page](https://github.co
- Use native PHP types for properties of `Type` and its subclasses
- Throw `SerializationError` over client safe `Error` when failing to serialize leaf types
- Move debug entries in errors under `extensions` key
- Use native PHP types for `Schema` and `SchemaConfig`
- Use native PHP types wherever possible
- Always throw `RequestError` with useful message when clients provide an invalid JSON body
- Move class `BlockString` from namespace `GraphQL\Utils` to `GraphQL\Language`
- Return string-keyed arrays from `GraphQL::getStandardDirectives()`, `GraphQL::getStandardTypes()` and `GraphQL::getStandardValidationRules()`
Expand All @@ -32,6 +32,11 @@ You can find and compare releases at the [GitHub release page](https://github.co
- Always convert recursively when calling `Node::toArray()`
- Make `Directive::$config['args']` use the same definition style as `FieldDefinition::$config['args']`
- Rename `FieldArgument` to `Argument`
- Make errors when parsing scalar literals more precise
- Change expected `QueryPlan` options from `['group-implementor-fields']` to `['groupImplementorFields' => true]` in `ResolveInfo::lookAhead()`
- Always convert promises through `PromiseAdapter::convertThenable()` before calling `->then()` on them
- Use `JSON_THROW_ON_ERROR` in `json_encode()`
- Validate some internal invariants through `assert()`

### Added

Expand Down Expand Up @@ -97,6 +102,7 @@ You can find and compare releases at the [GitHub release page](https://github.co
- Remove `ListOfType::$ofType`, `ListOfType::getOfType()` and `NonNull::getOfType()`
- Remove option `commentDescriptions` from `BuildSchema::buildAST()`, `BuildSchema::build()` and `Printer::doPrint()`
- Remove parameter `$options` from `ASTDefinitionBuilder`
- Remove `FieldDefinition::create()` in favor of `new FieldDefinition()`

## 14.11.3

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/Utils/SchemaGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ protected function createType(int $nestingLevel, ?string $typeName = null): Obje
}

/**
* @return array{0: ObjectType, 1: string}
* @return array{0: Type, 1: string}
*/
protected function getFieldTypeAndName(int $nestingLevel, int $fieldIndex): array
{
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"psr/http-message": "^1",
"react/promise": "^2",
"symfony/polyfill-php81": "^1.23",
"symfony/var-exporter": "^5.3"
"symfony/var-exporter": "^5.3",
"thecodingmachine/safe": "^1.3"
},
"suggest": {
"psr/http-message": "To use standard GraphQL server",
Expand Down
2 changes: 1 addition & 1 deletion docs/class-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2346,7 +2346,7 @@ static function toArray(GraphQL\Language\AST\Node $node): array
* | null | NullValue |
*
* @param Type|mixed|null $value
* @param ScalarType|EnumType|InputObjectType|ListOfType<Type &InputType>|NonNull $type
* @param ScalarType|EnumType|InputObjectType|ListOfType<Type&InputType>|NonNull $type
*
* @return ObjectValueNode|ListValueNode|BooleanValueNode|IntValueNode|FloatValueNode|EnumValueNode|StringValueNode|NullValueNode|null
*
Expand Down
4 changes: 4 additions & 0 deletions examples/00-hello-world/graphql.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
]);

$rawInput = file_get_contents('php://input');
if (false === $rawInput) {
throw new RuntimeException('Failed to get php://input');
}

$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = $input['variables'] ?? null;
Expand Down
13 changes: 9 additions & 4 deletions examples/01-blog/Blog/Type/NodeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
namespace GraphQL\Examples\Blog\Type;

use Exception;
use function get_class;
use GraphQL\Examples\Blog\Data\Image;
use GraphQL\Examples\Blog\Data\Story;
use GraphQL\Examples\Blog\Data\User;
use GraphQL\Examples\Blog\Types;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Utils\Utils;

class NodeType extends InterfaceType
{
Expand All @@ -26,7 +26,12 @@ public function __construct()
]);
}

public function resolveNodeType(object $object): Type
/**
* @param mixed $object
*
* @return callable(): ObjectType
*/
public function resolveNodeType($object)
{
if ($object instanceof User) {
return Types::user();
Expand All @@ -40,6 +45,6 @@ public function resolveNodeType(object $object): Type
return Types::story();
}

throw new Exception('Unknown type: ' . get_class($object));
throw new Exception('Unknown type: ' . Utils::printSafe($object));
}
}
2 changes: 1 addition & 1 deletion examples/01-blog/Blog/Type/Scalar/UrlType.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ public function parseLiteral(Node $valueNode, ?array $variables = null): string
private function isUrl($value): bool
{
return is_string($value)
&& filter_var($value, FILTER_VALIDATE_URL);
&& false !== filter_var($value, FILTER_VALIDATE_URL);
}
}
21 changes: 7 additions & 14 deletions examples/01-blog/Blog/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace GraphQL\Examples\Blog;

use function class_exists;
use Closure;
use function count;
use Exception;
Expand Down Expand Up @@ -94,35 +93,29 @@ public static function url(): callable
}

/**
* @param class-string<Type> $classname
*
* @return Closure(): Type
*/
private static function get(string $classname): Closure
{
return static fn () => self::byClassName($classname);
}

/**
* @param class-string<Type> $classname
*/
private static function byClassName(string $classname): Type
{
$parts = explode('\\', $classname);

$cacheName = strtolower(preg_replace('~Type$~', '', $parts[count($parts) - 1]));
$type = null;

if (! isset(self::$types[$cacheName])) {
if (class_exists($classname)) {
$type = new $classname();
}

self::$types[$cacheName] = $type;
return self::$types[$cacheName] = new $classname();
}

$type = self::$types[$cacheName];

if (! $type) {
throw new Exception('Unknown graphql type: ' . $classname);
}

return $type;
return self::$types[$cacheName];
}

public static function byTypeName(string $shortName): Type
Expand Down
4 changes: 4 additions & 0 deletions examples/02-schema-definition-language/graphql.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
];

$rawInput = file_get_contents('php://input');
if (false === $rawInput) {
throw new RuntimeException('Failed to get php://input');
}

$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = $input['variables'] ?? null;
Expand Down
11 changes: 4 additions & 7 deletions generate-class-reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,9 @@ function renderProp(ReflectionProperty $prop): string
return unpadDocblock($prop->getDocComment()) . "\n" . $signature;
}

/**
* @param string|false $docBlock
*/
function unwrapDocblock($docBlock): string
function unwrapDocblock(string $docBlock): string
{
if (! $docBlock) {
if ('' === $docBlock) {
return '';
}

Expand All @@ -196,7 +193,7 @@ function unwrapDocblock($docBlock): string
*/
function unpadDocblock($docBlock): string
{
if (! $docBlock) {
if (false === $docBlock) {
return '';
}

Expand All @@ -215,7 +212,7 @@ function unpadDocblock($docBlock): string
function isApi(Reflector $reflector): bool
{
$comment = $reflector->getDocComment();
if (! $comment) {
if (false === $comment) {
return false;
}

Expand Down
35 changes: 20 additions & 15 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ parameters:
count: 1
path: examples/01-blog/Blog/Types.php

-
message: "#^Strict comparison using \\=\\=\\= between non\\-empty\\-string and null will always evaluate to false\\.$#"
count: 1
path: src/Error/Error.php

-
message: "#^SplObjectStorage\\<GraphQL\\\\Type\\\\Definition\\\\ObjectType, SplObjectStorage\\<ArrayObject\\<int, GraphQL\\\\Language\\\\AST\\\\FieldNode\\>, ArrayObject\\<string, ArrayObject\\<int, GraphQL\\\\Language\\\\AST\\\\FieldNode\\>\\>\\>\\> does not accept SplObjectStorage\\<ArrayObject\\<int, GraphQL\\\\Language\\\\AST\\\\FieldNode\\>, ArrayObject\\<string, ArrayObject\\<int, GraphQL\\\\Language\\\\AST\\\\FieldNode\\>\\>\\>\\|SplObjectStorage\\<object, mixed\\>\\.$#"
count: 1
Expand All @@ -76,8 +71,8 @@ parameters:
path: src/Language/AST/Node.php

-
message: "#^Array \\(array\\<array\\<string, mixed\\>\\|T of GraphQL\\\\Language\\\\AST\\\\Node\\>\\) does not accept GraphQL\\\\Language\\\\AST\\\\Node\\.$#"
count: 2
message: "#^Parameter \\#4 \\$replacement of function array_splice expects array\\|string, array\\<T of GraphQL\\\\Language\\\\AST\\\\Node\\>\\|T of GraphQL\\\\Language\\\\AST\\\\Node\\|null given\\.$#"
count: 1
path: src/Language/AST/NodeList.php

-
Expand Down Expand Up @@ -110,6 +105,16 @@ parameters:
count: 1
path: src/Language/Visitor.php

-
message: "#^Parameter \\#1 \\$config of class GraphQL\\\\Type\\\\Definition\\\\Argument constructor expects array\\{name\\: string, type\\: \\(callable\\(\\)\\: GraphQL\\\\Type\\\\Definition\\\\InputType&GraphQL\\\\Type\\\\Definition\\\\Type\\)\\|\\(GraphQL\\\\Type\\\\Definition\\\\InputType&GraphQL\\\\Type\\\\Definition\\\\Type\\), defaultValue\\?\\: mixed, description\\?\\: string\\|null, astNode\\?\\: GraphQL\\\\Language\\\\AST\\\\InputValueDefinitionNode\\|null\\}, non\\-empty\\-array given\\.$#"
count: 1
path: src/Type/Definition/Argument.php

-
message: "#^Parameter \\#1 \\$config of class GraphQL\\\\Type\\\\Definition\\\\EnumValueDefinition constructor expects array\\{name\\: string, value\\?\\: mixed, deprecationReason\\?\\: string\\|null, description\\?\\: string\\|null, astNode\\?\\: GraphQL\\\\Language\\\\AST\\\\EnumValueDefinitionNode\\|null\\}, array given\\.$#"
count: 1
path: src/Type/Definition/EnumType.php

-
message: "#^Method GraphQL\\\\Type\\\\Definition\\\\FieldDefinition\\:\\:getType\\(\\) should return GraphQL\\\\Type\\\\Definition\\\\OutputType&GraphQL\\\\Type\\\\Definition\\\\Type but returns GraphQL\\\\Type\\\\Definition\\\\Type\\.$#"
count: 1
Expand All @@ -120,6 +125,11 @@ parameters:
count: 1
path: src/Type/Definition/FieldDefinition.php

-
message: "#^Method GraphQL\\\\Type\\\\Definition\\\\NonNull\\:\\:getWrappedType\\(\\) should return GraphQL\\\\Type\\\\Definition\\\\NullableType&GraphQL\\\\Type\\\\Definition\\\\Type but returns GraphQL\\\\Type\\\\Definition\\\\Type\\.$#"
count: 1
path: src/Type/Definition/NonNull.php

-
message: "#^Array \\(array\\<string, GraphQL\\\\Type\\\\Definition\\\\NamedType&GraphQL\\\\Type\\\\Definition\\\\Type\\>\\) does not accept GraphQL\\\\Type\\\\Definition\\\\Type\\.$#"
count: 1
Expand Down Expand Up @@ -161,19 +171,14 @@ parameters:
path: src/Validator/Rules/KnownDirectives.php

-
message: "#^SplObjectStorage\\<GraphQL\\\\Language\\\\AST\\\\SelectionSetNode, array\\{array\\<string, array\\<int, array\\{GraphQL\\\\Type\\\\Definition\\\\Type, GraphQL\\\\Language\\\\AST\\\\FieldNode, GraphQL\\\\Type\\\\Definition\\\\FieldDefinition\\|null\\}\\>\\>, array\\<int, string\\>\\}\\> does not accept array\\<int, mixed\\>\\.$#"
message: "#^Method GraphQL\\\\Validator\\\\Rules\\\\OverlappingFieldsCanBeMerged\\:\\:getFieldsAndFragmentNames\\(\\) should return array\\{array\\<string, array\\<int, array\\{GraphQL\\\\Type\\\\Definition\\\\Type, GraphQL\\\\Language\\\\AST\\\\FieldNode, GraphQL\\\\Type\\\\Definition\\\\FieldDefinition\\|null\\}\\>\\>, array\\<int, string\\>\\} but returns array\\{mixed, array\\<int, int\\|string\\>\\}\\.$#"
count: 1
path: src/Validator/Rules/OverlappingFieldsCanBeMerged.php

-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertArrayHasKey\\(\\) with int\\|string and GraphQL\\\\Language\\\\AST\\\\NodeList will always evaluate to false\\.$#"
count: 1
path: tests/Language/VisitorTest.php

-
message: "#^Instanceof between mixed and GraphQL\\\\Language\\\\AST\\\\NodeList will always evaluate to false\\.$#"
message: "#^SplObjectStorage\\<GraphQL\\\\Language\\\\AST\\\\SelectionSetNode, array\\{array\\<string, array\\<int, array\\{GraphQL\\\\Type\\\\Definition\\\\Type, GraphQL\\\\Language\\\\AST\\\\FieldNode, GraphQL\\\\Type\\\\Definition\\\\FieldDefinition\\|null\\}\\>\\>, array\\<int, string\\>\\}\\> does not accept array\\<int, mixed\\>\\.$#"
count: 1
path: tests/Language/VisitorTest.php
path: src/Validator/Rules/OverlappingFieldsCanBeMerged.php

-
message: "#^Method GraphQL\\\\Tests\\\\Language\\\\VisitorTest\\:\\:getNodeByPath\\(\\) return type with generic class GraphQL\\\\Language\\\\AST\\\\NodeList does not specify its types\\: T$#"
Expand Down
16 changes: 8 additions & 8 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
parameters:
# TODO increase to max
level: 6

# TODO revert this setting once we arrived at level: max
reportUnmatchedIgnoredErrors: false
level: 7

paths:
- benchmarks
Expand All @@ -22,7 +19,6 @@ parameters:
- "~Variable method call on GraphQL\\\\Language\\\\Parser\\.~"

# We utilize lazy initialization of non-nullable properties
- "~Property .+? in isset\\(\\) is not nullable~"
- "~Property .+? on left side of \\?\\?= is not nullable~"

# Useful/necessary in the default field resolver, deals with arbitrary user data
Expand All @@ -45,14 +41,18 @@ includes:

services:
-
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsInputTypeStaticMethodTypeSpecifyingExtension
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsAbstractTypeStaticMethodTypeSpecifyingExtension
tags:
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
-
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsOutputTypeStaticMethodTypeSpecifyingExtension
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsCompositeTypeStaticMethodTypeSpecifyingExtension
tags:
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
-
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsCompositeTypeStaticMethodTypeSpecifyingExtension
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsInputTypeStaticMethodTypeSpecifyingExtension
tags:
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
-
class: GraphQL\Tests\PhpStan\Type\Definition\Type\IsOutputTypeStaticMethodTypeSpecifyingExtension
tags:
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
7 changes: 5 additions & 2 deletions src/Deferred.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@

use GraphQL\Executor\Promise\Adapter\SyncPromise;

/**
* @phpstan-import-type Executor from SyncPromise
*/
class Deferred extends SyncPromise
{
/**
* @param callable() : mixed $executor
* @param Executor $executor
*/
public static function create(callable $executor): self
{
return new self($executor);
}

/**
* @param callable() : mixed $executor
* @param Executor $executor
*/
public function __construct(callable $executor)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Error/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Error extends Exception implements JsonSerializable, ClientAware, Provides
protected ?array $extensions;

/**
* @param iterable<array-key, Node>|Node|null $nodes
* @param iterable<array-key, Node|null>|Node|null $nodes
* @param array<int, int>|null $positions
* @param array<int, int|string>|null $path
* @param array<string, mixed>|null $extensions
Expand All @@ -89,9 +89,9 @@ public function __construct(

// Compute list of blame nodes.
if ($nodes instanceof Traversable) {
$this->nodes = iterator_to_array($nodes);
$this->nodes = array_filter(iterator_to_array($nodes));
} elseif (is_array($nodes)) {
$this->nodes = $nodes;
$this->nodes = array_filter($nodes);
} elseif (null !== $nodes) {
$this->nodes = [$nodes];
} else {
Expand Down Expand Up @@ -160,7 +160,7 @@ public static function createLocatedError($error, $nodes = null, ?array $path =
$message = (string) $error;
}

$nonEmptyMessage = '' === $message || null === $message
$nonEmptyMessage = '' === $message
? 'An unknown error occurred.'
: $message;

Expand Down