GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( e5e542...80e7c7 )
by Gytis
04:34 queued 13s
created

FqcnPropSniff::hasNonNullAssignedProp()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 16
c 1
b 0
f 0
nc 5
nop 3
dl 0
loc 28
ccs 17
cts 17
cp 1
crap 5
rs 9.4222
1
<?php
2
3
namespace Gskema\TypeSniff\Sniffs\CodeElement;
4
5
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnElement;
6
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnMethodElement;
7
use Gskema\TypeSniff\Core\CodeElement\Element\ClassElement;
8
use Gskema\TypeSniff\Core\CodeElement\Element\ClassMethodElement;
9
use Gskema\TypeSniff\Core\CodeElement\Element\TraitElement;
10
use Gskema\TypeSniff\Core\CodeElement\Element\TraitMethodElement;
11
use Gskema\TypeSniff\Core\Type\DocBlock\NullType;
12
use Gskema\TypeSniff\Core\Type\TypeHelper;
13
use Gskema\TypeSniff\Inspection\DocTypeInspector;
14
use Gskema\TypeSniff\Inspection\Subject\PropTypeSubject;
15
use PHP_CodeSniffer\Files\File;
16
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnPropElement;
17
use Gskema\TypeSniff\Core\CodeElement\Element\ClassPropElement;
18
use Gskema\TypeSniff\Core\CodeElement\Element\CodeElementInterface;
19
use Gskema\TypeSniff\Core\CodeElement\Element\TraitPropElement;
20
21
class FqcnPropSniff implements CodeElementSniffInterface
22
{
23
    protected const CODE = 'FqcnPropSniff';
24
25
    /** @var bool */
26
    protected $reportUninitializedProp = true;
27
28
    /**
29
     * @inheritDoc
30
     */
31 11
    public function configure(array $config): void
32
    {
33 11
        $this->reportUninitializedProp = $config['reportUninitializedProp'] ?? true;
34 11
    }
35
36
    /**
37
     * @inheritDoc
38
     */
39 11
    public function register(): array
40
    {
41
        return [
42 11
            ClassPropElement::class,
43
            TraitPropElement::class,
44
        ];
45
    }
46
47
    /**
48
     * @inheritDoc
49
     * @param AbstractFqcnPropElement $prop
50
     * @param AbstractFqcnElement $parentElement
51
     */
52 8
    public function process(File $file, CodeElementInterface $prop, CodeElementInterface $parentElement): void
53
    {
54 8
        $subject = PropTypeSubject::fromElement($prop);
55
56 8
        DocTypeInspector::reportMandatoryTypes($subject);
57 8
        DocTypeInspector::reportReplaceableTypes($subject);
58 8
        DocTypeInspector::reportRemovableTypes($subject);
59 8
        DocTypeInspector::reportMissingOrWrongTypes($subject);
60
61 8
        static::reportInvalidDescription($subject);
62 8
        $this->reportUninitializedProp && static::reportUninitializedProp($subject, $prop, $parentElement);
63
64 8
        $subject->writeWarningsTo($file, static::CODE);
65 8
    }
66
67 8
    protected static function reportInvalidDescription(PropTypeSubject $subject): void
68
    {
69 8
        $varTag = $subject->getDocBlock()->getTagsByName('var')[0] ?? null;
70
71 8
        if ($varTag && null !== $varTag->getParamName()) {
72 1
            $subject->addDocTypeWarning('Remove property name $'.$varTag->getParamName().' from @var tag');
73
        }
74 8
    }
75
76
    /**
77
     * @param PropTypeSubject                                           $subject
78
     * @param AbstractFqcnPropElement|ClassPropElement|TraitPropElement $prop
79
     * @param AbstractFqcnElement|ClassElement|TraitElement             $parent
80
     */
81 8
    protected static function reportUninitializedProp(
82
        PropTypeSubject $subject,
83
        AbstractFqcnPropElement $prop,
84
        AbstractFqcnElement $parent
85
    ): void {
86
        // Report nothing for PHP7.4 instead of reporting wrong
87 8
        if (version_compare(PHP_VERSION, '7.4', '>=')) {
88
            return; // @TODO Exit when prop has defined fnType
89
        }
90
91 8
        $propHasDefaultValue = $prop->getMetadata()->hasDefaultValue(); // null = not detected
0 ignored issues
show
Bug introduced by
The method getMetadata() does not exist on Gskema\TypeSniff\Core\Co...AbstractFqcnPropElement. Since it exists in all sub-types, consider adding an abstract or default implementation to Gskema\TypeSniff\Core\Co...AbstractFqcnPropElement. ( Ignorable by Annotation )

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

91
        $propHasDefaultValue = $prop->/** @scrutinizer ignore-call */ getMetadata()->hasDefaultValue(); // null = not detected
Loading history...
92
93 8
        $ownConstructor = $parent->getOwnConstructor();
0 ignored issues
show
Bug introduced by
The method getOwnConstructor() does not exist on Gskema\TypeSniff\Core\Co...ent\AbstractFqcnElement. It seems like you code against a sub-type of Gskema\TypeSniff\Core\Co...ent\AbstractFqcnElement such as Gskema\TypeSniff\Core\Co...nt\Element\TraitElement or Gskema\TypeSniff\Core\Co...nt\Element\ClassElement. ( Ignorable by Annotation )

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

93
        /** @scrutinizer ignore-call */ 
94
        $ownConstructor = $parent->getOwnConstructor();
Loading history...
94
95 8
        if ((false === $propHasDefaultValue || $prop->getDefaultValueType() instanceof NullType)
96 8
            && !TypeHelper::containsType($subject->getDocType(), NullType::class)
97 8
            && (!$ownConstructor || !static::hasNonNullAssignedProp($parent, $ownConstructor, $prop->getPropName()))
98
        ) {
99 7
            $subject->addDocTypeWarning(':Subject: not initialized by __construct(), add null doc type or set a default value');
100
        }
101 8
    }
102
103
    /**
104
     * @param ClassElement|TraitElement|AbstractFqcnElement                   $parent
105
     * @param ClassMethodElement|TraitMethodElement|AbstractFqcnMethodElement $method
106
     * @param string                                                          $propName
107
     *
108
     * @return bool|null
109
     */
110 3
    public static function hasNonNullAssignedProp(
111
        AbstractFqcnElement $parent,
112
        AbstractFqcnMethodElement $method,
113
        string $propName
114
    ): ?bool {
115
        // Not ideal because we have to descend on every prop inspection.
116
        // However early exit is used, so we don't have to descend fully each time.
117 3
        $visitedNames = [];
118 3
        $unvisitedNames = [$method->getSignature()->getName()];
119 3
        while (!empty($unvisitedNames)) {
120 3
            $callNames = [];
121 3
            foreach ($unvisitedNames as $unvisitedName) {
122 3
                $unvisitedMethod = $parent->getMethod($unvisitedName);
0 ignored issues
show
Bug introduced by
The method getMethod() does not exist on Gskema\TypeSniff\Core\Co...ent\AbstractFqcnElement. It seems like you code against a sub-type of Gskema\TypeSniff\Core\Co...ent\AbstractFqcnElement such as Gskema\TypeSniff\Core\Co...nt\Element\TraitElement or Gskema\TypeSniff\Core\Co...nt\Element\ClassElement. ( Ignorable by Annotation )

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

122
                /** @scrutinizer ignore-call */ 
123
                $unvisitedMethod = $parent->getMethod($unvisitedName);
Loading history...
123 3
                if (null === $unvisitedMethod) {
124 2
                    continue;
125
                }
126 3
                $nonNullAssignedProps = $unvisitedMethod->getMetadata()->getNonNullAssignedProps() ?? []; // never null
127 3
                if (in_array($propName, $nonNullAssignedProps)) {
128 2
                    return true;
129
                }
130 3
                $callNameChunk = $unvisitedMethod->getMetadata()->getThisMethodCalls() ?? []; // never null
131 3
                $callNames = array_merge($callNames, $callNameChunk);
132
            }
133 3
            $visitedNames = array_merge($visitedNames, $unvisitedNames);
134 3
            $unvisitedNames = array_diff($callNames, $visitedNames);
135
        }
136
137 3
        return false;
138
    }
139
}
140