Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Pull Request — master (#801)
by Timur
20:26
created

DocBlockTypeGuesser   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 65
c 1
b 1
f 0
dl 0
loc 113
rs 9.92
wmc 31

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getName() 0 3 1
A supports() 0 3 2
F guessType() 0 72 21
A resolveCompound() 0 13 5
A getParser() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Config\Parser\MetadataParser\TypeGuesser;
6
7
use Exception;
8
use phpDocumentor\Reflection\DocBlock\Tags\TagWithType;
9
use phpDocumentor\Reflection\DocBlockFactory;
10
use phpDocumentor\Reflection\Type;
11
use phpDocumentor\Reflection\Types\AbstractList;
12
use phpDocumentor\Reflection\Types\Compound;
13
use phpDocumentor\Reflection\Types\ContextFactory;
14
use phpDocumentor\Reflection\Types\Mixed_;
15
use phpDocumentor\Reflection\Types\Null_;
16
use phpDocumentor\Reflection\Types\Nullable;
17
use phpDocumentor\Reflection\Types\Object_;
18
use ReflectionClass;
19
use ReflectionMethod;
20
use ReflectionProperty;
21
use Reflector;
22
use function sprintf;
23
24
class DocBlockTypeGuesser extends PhpTypeGuesser
25
{
26
    protected ?DocBlockFactory $factory;
27
28
    public function getName(): string
29
    {
30
        return 'Dock block';
31
    }
32
33
    public function supports(Reflector $reflector): bool
34
    {
35
        return $reflector instanceof ReflectionProperty || $reflector instanceof ReflectionMethod;
36
    }
37
38
    /**
39
     * @param ReflectionProperty|ReflectionMethod $reflector
40
     */
41
    public function guessType(ReflectionClass $reflectionClass, Reflector $reflector, array $filterGraphQLTypes = []): ?string
42
    {
43
        $contextFactory = new ContextFactory();
44
        $context = $contextFactory->createFromReflector($reflectionClass);
45
        $docBlockComment = $reflector->getDocComment();
0 ignored issues
show
Bug introduced by
The method getDocComment() does not exist on Reflector. It seems like you code against a sub-type of said class. However, the method does not exist in ReflectionExtension or ReflectionZendExtension or ReflectionParameter. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
        /** @scrutinizer ignore-call */ 
46
        $docBlockComment = $reflector->getDocComment();
Loading history...
46
        if (!$docBlockComment) {
47
            throw new TypeGuessingException(sprintf('Doc Block not found'));
48
        }
49
50
        try {
51
            $docBlock = $this->getParser()->create($docBlockComment, $context);
52
        } catch (Exception $e) {
53
            throw new TypeGuessingException(sprintf('Doc Block parsing failed with error: %s', $e->getMessage()));
54
        }
55
        $tagName = $reflector instanceof ReflectionProperty ? 'var' : 'return';
56
        $tags = $docBlock->getTagsByName($tagName);
57
        $tag = $tags[0] ?? null;
58
        if (!$tag || !$tag instanceof TagWithType) {
59
            throw new TypeGuessingException(sprintf('No @%s tag found in doc block or tag has no type', $tagName));
60
        }
61
        $type = $tag->getType();
62
        $isNullable = false;
63
        $isList = false;
64
        $isListNullable = false;
65
        $exceptionPrefix = sprintf('Tag @%s found', $tagName);
66
67
        if ($type instanceof Compound) {
68
            $type = $this->resolveCompound($type);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $type is correct as $this->resolveCompound($type) targeting Overblog\GraphQLBundle\C...sser::resolveCompound() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
69
            if (!$type) {
0 ignored issues
show
introduced by
$type is of type null, thus it always evaluated to false.
Loading history...
70
                throw new TypeGuessingException(sprintf('%s, but composite types are only allowed with null. Ex: string|null.', $exceptionPrefix));
71
            }
72
            $isNullable = true;
73
        } elseif ($type instanceof Nullable) {
74
            $isNullable = true;
75
            $type = $type->getActualType();
76
        }
77
78
        if ($type instanceof AbstractList) {
79
            $isList = true;
80
            $isListNullable = $isNullable;
81
            $isNullable = false;
82
            $type = $type->getValueType();
83
            if ($type instanceof Compound) {
84
                $type = $this->resolveCompound($type);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $type is correct as $this->resolveCompound($type) targeting Overblog\GraphQLBundle\C...sser::resolveCompound() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
85
                if (!$type) {
0 ignored issues
show
introduced by
$type is of type null, thus it always evaluated to false.
Loading history...
86
                    throw new TypeGuessingException(sprintf('%s, but composite types in array or iterable are only allowed with null. Ex: string|null.', $exceptionPrefix));
87
                }
88
                $isNullable = true;
89
            } elseif ($type instanceof Mixed_) {
90
                throw new TypeGuessingException(sprintf('%s, but the array values cannot be mixed type', $exceptionPrefix));
91
            }
92
        }
93
94
        if ($type instanceof Object_) {
95
            $className = $type->getFqsen();
96
            if (!$className) {
97
                throw new TypeGuessingException(sprintf('%s, but type "object" is too generic.', $exceptionPrefix));
98
            }
99
            // Remove first '\' from returned class name
100
            $className = substr((string) $className, 1);
101
            $gqlType = $this->map->resolveType((string) $className, $filterGraphQLTypes);
102
            if (!$gqlType) {
103
                throw new TypeGuessingException(sprintf('%s, but target object "%s" is not a GraphQL Type class.', $exceptionPrefix, $className));
104
            }
105
        } else {
106
            $gqlType = $this->resolveTypeFromPhpType((string) $type);
107
            if (!$gqlType) {
108
                throw new TypeGuessingException(sprintf('%s, but unable to resolve type "%s" to a GraphQL scalar.', $exceptionPrefix, (string) $type));
109
            }
110
        }
111
112
        return $isList ? sprintf('[%s%s]%s', $gqlType, $isNullable ? '' : '!', $isListNullable ? '' : '!') : sprintf('%s%s', $gqlType, $isNullable ? '' : '!');
113
    }
114
115
    protected function resolveCompound(Compound $compound): ?Type
116
    {
117
        $typeNull = new Null_();
118
        if (2 !== $compound->getIterator()->count() || !$compound->contains($typeNull)) {
119
            return null;
120
        }
121
        foreach ($compound as $type) {
122
            if (!$type instanceof Null_) {
123
                return $type;
124
            }
125
        }
126
127
        return null;
128
    }
129
130
    private function getParser(): DocBlockFactory
131
    {
132
        if (!isset($this->factory)) {
133
            $this->factory = DocBlockFactory::createInstance();
134
        }
135
136
        return $this->factory;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->factory could return the type null which is incompatible with the type-hinted return phpDocumentor\Reflection\DocBlockFactory. Consider adding an additional type-check to rule them out.
Loading history...
137
    }
138
}
139