AlphabeticClassContentSniff   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 3
dl 0
loc 121
c 0
b 0
f 0
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A checkAndRegisterSortingProblems() 0 14 3
A checkAndRegisterSortingProblemsOfTypes() 0 8 1
A getContentsOfTokenType() 0 28 5
A processToken() 0 8 2
A sortTokensWithoutPos() 0 10 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BestIt\Sniffs\Formatting;
6
7
use BestIt\CodeSniffer\Helper\PropertyHelper;
8
use BestIt\CodeSniffer\Helper\TokenHelper;
9
use BestIt\Sniffs\AbstractSniff;
10
use BestIt\Sniffs\ClassRegistrationTrait;
11
use function array_values;
12
use function natsort;
13
use const T_CONST;
14
use const T_FUNCTION;
15
use const T_STRING;
16
use const T_VARIABLE;
17
18
/**
19
 * Registers a warning, if the constants, properties or methods are not sorted alphabetically.
20
 *
21
 * @author blange <[email protected]>
22
 * @package BestIt\Sniffs\Formatting
23
 */
24
class AlphabeticClassContentSniff extends AbstractSniff
25
{
26
    use ClassRegistrationTrait;
27
28
    /**
29
     * You SHOULD sort you constants, methods and properties alphabetically.
30
     */
31
    public const CODE_SORT_ALPHABETICALLY = 'SortAlphabetically';
32
33
    /**
34
     * The message for the wrong sorting.
35
     */
36
    private const MESSAGE_SORT_ALPHABETICALLY = 'Please sort you contents alphabetically.';
37
38
    /**
39
     * Checks the sorting of both arrays and registered warnings, if a token is not on the correct position.
40
     *
41
     * @param array $foundContentsOrg The original contents with their position.
42
     * @param array $foundContentsSorted The sorted contents without their position as array key.
43
     *
44
     * @return void
45
     */
46
    private function checkAndRegisterSortingProblems(array $foundContentsOrg, array $foundContentsSorted): void
47
    {
48
        $checkIndex = 0;
49
50
        foreach ($foundContentsOrg as $foundContentPos => $foundContent) {
51
            if ($foundContentsSorted[$checkIndex++] !== $foundContent) {
52
                $this->file->addWarning(
53
                    self::MESSAGE_SORT_ALPHABETICALLY,
54
                    $foundContentPos,
55
                    static::CODE_SORT_ALPHABETICALLY
56
                );
57
            }
58
        }
59
    }
60
61
    /**
62
     * Loads every content for the token type and checks their sorting.
63
     *
64
     * @param int $token
65
     *
66
     * @return void
67
     */
68
    private function checkAndRegisterSortingProblemsOfTypes(int $token): void
69
    {
70
        $foundContentsOrg = $this->getContentsOfTokenType($token);
71
72
        $foundContentsSorted = $this->sortTokensWithoutPos($foundContentsOrg);
73
74
        $this->checkAndRegisterSortingProblems($foundContentsOrg, $foundContentsSorted);
75
    }
76
77
    /**
78
     * Returns the contents of the token type.
79
     *
80
     * @param int $token The contents with their position as array key.
81
     *
82
     * @return array
83
     */
84
    private function getContentsOfTokenType(int $token): array
85
    {
86
        $helper = new PropertyHelper($this->file);
87
        $tokenPoss = TokenHelper::findNextAll(
88
            $this->file,
0 ignored issues
show
Bug introduced by
It seems like $this->file can be null; however, findNextAll() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
89
            [$token],
90
            $this->stackPos + 1,
91
            $this->token['scope_closer']
92
        );
93
94
        $foundContentsOrg = [];
95
96
        foreach ($tokenPoss as $tokenPos) {
97
            $tokenContentPos = $tokenPos;
98
99
            if (($token === T_VARIABLE) && (!$helper->isProperty($tokenPos))) {
100
                continue;
101
            }
102
103
            if ($token !== T_VARIABLE) {
104
                $tokenContentPos = $this->file->findNext([T_STRING], $tokenPos);
105
            }
106
107
            $foundContentsOrg[$tokenContentPos] = $this->tokens[$tokenContentPos]['content'];
108
        }
109
110
        return $foundContentsOrg;
111
    }
112
113
    /**
114
     * Processes the token.
115
     *
116
     * @return void
117
     */
118
    protected function processToken(): void
119
    {
120
        $tokenTypes = [T_CONST, T_FUNCTION, T_VARIABLE];
121
122
        foreach ($tokenTypes as $tokenType) {
123
            $this->checkAndRegisterSortingProblemsOfTypes($tokenType);
124
        }
125
    }
126
127
    /**
128
     * Sorts the tokens and returns them without their position as array keys.
129
     *
130
     * @param array $foundContentsOrg
131
     *
132
     * @return array
133
     */
134
    private function sortTokensWithoutPos(array $foundContentsOrg): array
135
    {
136
        $foundContentsSorted = $foundContentsOrg;
137
138
        natsort($foundContentsSorted);
139
140
        return array_values($foundContentsSorted); // "remove" indices
141
142
        return $foundContentsSorted;
0 ignored issues
show
Unused Code introduced by
return $foundContentsSorted; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
143
    }
144
}
145