FqcnPropSniff   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 13
Bugs 0 Features 2
Metric Value
eloc 35
dl 0
loc 84
ccs 37
cts 37
cp 1
rs 10
c 13
b 0
f 2
wmc 15

5 Methods

Rating   Name   Duplication   Size   Complexity  
B reportUselessPHPDoc() 0 22 9
A reportInvalidDescription() 0 7 3
A configure() 0 4 1
A register() 0 5 1
A process() 0 16 1
1
<?php
2
3
namespace Gskema\TypeSniff\Sniffs\CodeElement;
4
5
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnElement;
6
use Gskema\TypeSniff\Core\DocBlock\Tag\VarTag;
7
use Gskema\TypeSniff\Core\Type\Declaration\NullableType;
8
use Gskema\TypeSniff\Inspection\DocTypeInspector;
9
use Gskema\TypeSniff\Inspection\FnTypeInspector;
10
use Gskema\TypeSniff\Inspection\Subject\PropTypeSubject;
11
use PHP_CodeSniffer\Files\File;
12
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnPropElement;
13
use Gskema\TypeSniff\Core\CodeElement\Element\ClassPropElement;
14
use Gskema\TypeSniff\Core\CodeElement\Element\CodeElementInterface;
15
use Gskema\TypeSniff\Core\CodeElement\Element\TraitPropElement;
16
17
class FqcnPropSniff implements CodeElementSniffInterface
18
{
19
    protected const CODE = 'FqcnPropSniff';
20
21
    protected string $reportType = 'warning';
22
23
    protected bool $addViolationId = false;
24
25
    /**
26
     * @inheritDoc
27
     */
28 16
    public function configure(array $config): void
29
    {
30 16
        $this->reportType = (string)($config['reportType'] ?? 'warning');
31 16
        $this->addViolationId = (bool)($config['addViolationId'] ?? false);
32 16
    }
33
34
    /**
35
     * @inheritDoc
36
     */
37 16
    public function register(): array
38
    {
39
        return [
40 16
            ClassPropElement::class,
41
            TraitPropElement::class,
42
        ];
43
    }
44
45
    /**
46
     * @inheritDoc
47
     *
48
     * @param AbstractFqcnPropElement $prop
49
     * @param AbstractFqcnElement     $parentElement
50
     */
51 12
    public function process(File $file, CodeElementInterface $prop, CodeElementInterface $parentElement): void
52
    {
53 12
        $subject = PropTypeSubject::fromElement($prop);
54
55 12
        FnTypeInspector::reportSuggestedTypes($subject);
56 12
        FnTypeInspector::reportReplaceableTypes($subject);
57
58 12
        DocTypeInspector::reportMandatoryTypes($subject);
59 12
        DocTypeInspector::reportReplaceableTypes($subject);
60 12
        DocTypeInspector::reportRemovableTypes($subject);
61 12
        DocTypeInspector::reportMissingOrWrongTypes($subject);
62
63 12
        static::reportInvalidDescription($subject);
64 12
        static::reportUselessPHPDoc($subject);
65
66 12
        $subject->writeViolationsTo($file, static::CODE, $this->reportType, $this->addViolationId);
67 12
    }
68
69 12
    protected static function reportInvalidDescription(PropTypeSubject $subject): void
70
    {
71
        /** @var VarTag|null $varTag */
72 12
        $varTag = $subject->getDocBlock()->getTagsByName('var')[0] ?? null;
73
74 12
        if ($varTag && null !== $varTag->getParamName()) {
75 1
            $subject->addDocTypeWarning('Remove property name $' . $varTag->getParamName() . ' from @var tag');
76
        }
77 12
    }
78
79 12
    protected static function reportUselessPHPDoc(PropTypeSubject $subject): void
80
    {
81 12
        if (!$subject->hasDefinedFnType() || !$subject->hasDefinedDocBlock()) {
82 12
            return; // nothing to do
83
        }
84
85 1
        $docBlock = $subject->getDocBlock();
86
87
        /** @var VarTag|null $varTag */
88 1
        $varTag = $docBlock->getTagsByName('var')[0] ?? null;
89
90 1
        $fnType = $subject->getFnType();
91 1
        $rawFnType = $fnType instanceof NullableType ? $fnType->toDocString() : $fnType->toString();
92 1
        $rawDocType = $subject->getDocType()->toString();
93
94 1
        $isUseful = $rawFnType !== $rawDocType
95 1
            || $docBlock->hasDescription()
96 1
            || ($varTag && $varTag->hasDescription())
97 1
            || array_diff($docBlock->getTagNames(), ['var']);
98
99 1
        if (!$isUseful) {
100 1
            $subject->addFnTypeWarning('Useless PHPDoc');
101
        }
102 1
    }
103
}
104