FqcnConstSniff::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Gskema\TypeSniff\Sniffs\CodeElement;
4
5
use Gskema\TypeSniff\Core\DocBlock\Tag\VarTag;
6
use Gskema\TypeSniff\Core\Type\Common\ArrayType;
7
use Gskema\TypeSniff\Core\Type\DocBlock\TypedArrayType;
8
use Gskema\TypeSniff\Inspection\DocTypeInspector;
9
use Gskema\TypeSniff\Inspection\Subject\ConstTypeSubject;
10
use PHP_CodeSniffer\Files\File;
11
use Gskema\TypeSniff\Core\CodeElement\Element\AbstractFqcnConstElement;
12
use Gskema\TypeSniff\Core\CodeElement\Element\ClassConstElement;
13
use Gskema\TypeSniff\Core\CodeElement\Element\CodeElementInterface;
14
use Gskema\TypeSniff\Core\CodeElement\Element\InterfaceConstElement;
15
16
class FqcnConstSniff implements CodeElementSniffInterface
17
{
18
    protected const CODE = 'FqcnConstSniff';
19
20
    protected string $reportType = 'warning';
21
22
    protected bool $addViolationId = false;
23
24
    /**
25
     * @inheritDoc
26
     */
27 16
    public function configure(array $config): void
28
    {
29 16
        $this->reportType = (string)($config['reportType'] ?? 'warning');
30 16
        $this->addViolationId = (bool)($config['addViolationId'] ?? false);
31 16
    }
32
33
    /**
34
     * @inheritDoc
35
     */
36 16
    public function register(): array
37
    {
38
        return [
39 16
            ClassConstElement::class,
40
            InterfaceConstElement::class,
41
        ];
42
    }
43
44
    /**
45
     * @inheritDoc
46
     *
47
     * @param AbstractFqcnConstElement $const
48
     */
49 7
    public function process(File $file, CodeElementInterface $const, CodeElementInterface $parentElement): void
50
    {
51 7
        $subject = ConstTypeSubject::fromElement($const);
52
53 7
        DocTypeInspector::reportMandatoryTypes($subject);
54 7
        DocTypeInspector::reportReplaceableTypes($subject);
55
56 7
        DocTypeInspector::reportRemovableTypes($subject);
57 7
        DocTypeInspector::reportMissingOrWrongTypes($subject);
58
59 7
        static::reportUselessDocBlock($subject);
60
61 7
        $subject->writeViolationsTo($file, static::CODE, $this->reportType, $this->addViolationId);
62 7
    }
63
64 7
    protected static function reportUselessDocBlock(ConstTypeSubject $subject): void
65
    {
66 7
        if (!$subject->hasDefinedDocBlock()) {
67 4
            return;
68
        }
69
70 5
        $hasArrayShape = $subject->hasAttribute('ArrayShape');
71 5
        $docBlock = $subject->getDocBlock();
72
73
        /** @var VarTag|null $varTag */
74 5
        $varTag = $docBlock->getTagsByName('var')[0] ?? null;
75 5
        $docType = $varTag ? $varTag->getType() : null;
76
77 5
        $tagCount = count($docBlock->getTags());
78 5
        $hasOtherTags = (!$varTag && $tagCount >= 1) || ($varTag && $tagCount >= 2);
79
80 5
        $hasSpecificDocType = $docType != $subject->getValueType(); // intentional non strict
81 5
        $hasIncompleteDocType = $docType instanceof ArrayType;
82
83 5
        $isUseful = $hasOtherTags
84 5
            || $docBlock->hasDescription()
85 5
            || ($varTag && $varTag->hasDescription())
86 5
            || $hasSpecificDocType
87 2
            || $hasIncompleteDocType
88 5
            || $hasArrayShape && !($docType instanceof TypedArrayType) && !($docType instanceof ArrayType);
89
90 5
        if (!$isUseful) {
91 2
            $subject->addFnTypeWarning('Useless PHPDoc');
92
        }
93 5
    }
94
}
95