Passed
Push — master ( eefd9a...454770 )
by Björn
02:23
created

sortTokensWithoutPos()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 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\Sniffs\AbstractSniff;
9
use BestIt\Sniffs\ClassRegistrationTrait;
10
use SlevomatCodingStandard\Helpers\TokenHelper;
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
     * Error code for the sorting.
30
     *
31
     * @var string
32
     */
33
    public const CODE_SORT_ALPHABETICALLY = 'SortAlphabetically';
34
35
    /**
36
     * The message for the wrong sorting.
37
     *
38
     * @var string
39
     */
40
    private const MESSAGE_SORT_ALPHABETICALLY = 'Please sort you contents alphabetically.';
41
42
    /**
43
     * Checks the sorting of both arrays and registered warnings, if a token is not on the correct position.
44
     *
45
     * @param array $foundContentsOrg The original contents with their position.
46
     * @param array $foundContentsSorted The sorted contents without their position as array key.
47
     *
48
     * @return void
49
     */
50
    private function checkAndRegisterSortingProblems(array $foundContentsOrg, array $foundContentsSorted): void
51
    {
52
        $checkIndex = 0;
53
54
        foreach ($foundContentsOrg as $foundContentPos => $foundContent) {
55
            if ($foundContentsSorted[$checkIndex++] !== $foundContent) {
56
                $this->file->getBaseFile()->addWarning(
57
                    self::MESSAGE_SORT_ALPHABETICALLY,
58
                    $foundContentPos,
59
                    self::CODE_SORT_ALPHABETICALLY
60
                );
61
            }
62
        }
63
    }
64
65
    /**
66
     * Loads every content for the token type and checks their sorting.
67
     *
68
     * @param int $token
69
     *
70
     * @return void
71
     */
72
    private function checkAndRegisterSortingProblemsOfTypes(int $token): void
73
    {
74
        $foundContentsOrg = $this->getContentsOfTokenType($token);
75
76
        $foundContentsSorted = $this->sortTokensWithoutPos($foundContentsOrg);
77
78
        $this->checkAndRegisterSortingProblems($foundContentsOrg, $foundContentsSorted);
79
    }
80
81
    /**
82
     * Returns the contents of the token type.
83
     *
84
     * @param int $token The contents with their position as array key.
85
     *
86
     * @return array
87
     */
88
    private function getContentsOfTokenType(int $token): array
89
    {
90
        $helper = new PropertyHelper($this->file);
0 ignored issues
show
Bug introduced by
It seems like $this->file can be null; however, __construct() 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...
91
        $tokenPoss = TokenHelper::findNextAll(
92
            $this->file->getBaseFile(),
93
            [$token],
94
            $this->stackPos + 1,
95
            $this->token['scope_closer']
96
        );
97
98
        $foundContentsOrg = [];
99
100
        foreach ($tokenPoss as $tokenPos) {
101
            $tokenContentPos = $tokenPos;
102
103
            if (($token === T_VARIABLE) && (!$helper->isProperty($tokenPos))) {
104
                continue;
105
            }
106
107
            if ($token !== T_VARIABLE) {
108
                $tokenContentPos = $this->file->findNext([T_STRING], $tokenPos);
109
            }
110
111
            $foundContentsOrg[$tokenContentPos] = $this->tokens[$tokenContentPos]['content'];
112
        }
113
114
        return $foundContentsOrg;
115
    }
116
117
    /**
118
     * Processes the token.
119
     *
120
     * @return void
121
     */
122
    protected function processToken(): void
123
    {
124
        $tokenTypes = [T_CONST, T_FUNCTION, T_VARIABLE];
125
126
        foreach ($tokenTypes as $tokenType) {
127
            $this->checkAndRegisterSortingProblemsOfTypes($tokenType);
128
        }
129
    }
130
131
    /**
132
     * Sorts the tokens and returns them without their position as array keys.
133
     *
134
     * @param array $foundContentsOrg
135
     *
136
     * @return array
137
     */
138
    private function sortTokensWithoutPos(array $foundContentsOrg): array
139
    {
140
        $foundContentsSorted = $foundContentsOrg;
141
142
        natsort($foundContentsSorted);
143
144
        return array_values($foundContentsSorted); // "remove" indices
145
146
        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...
147
    }
148
}
149