Completed
Pull Request — master (#32)
by Michel
08:14
created

SingleObjectOperatorSniff   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 0
Metric Value
wmc 9
lcom 0
cbo 2
dl 0
loc 89
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 6 1
A process() 0 18 3
A isValidOperator() 0 25 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BestIt\Sniffs\Formatting;
6
7
use PHP_CodeSniffer\Files\File;
8
use PHP_CodeSniffer\Sniffs\Sniff;
9
10
/**
11
 * Only allow a single object operator per line
12
 *
13
 * @author Michel Chowanski <[email protected]>
14
 * @package BestIt\Sniffs\Formatting
15
 */
16
class SingleObjectOperatorSniff implements Sniff
17
{
18
    /**
19
     * Error message when found more then one object operator per line.
20
     *
21
     * @var string
22
     */
23
    const ERROR_NOT_SINGLE_OBJECT_OPERATOR_STATEMENT = 'Only one object operator per line allowed';
24
25
    /**
26
     * Code when found more then one object operator per line.
27
     *
28
     * @var string
29
     */
30
    const CODE_NOT_SINGLE_OBJECT_OPERATOR_STATEMENT = 'NotSingleObjectOperatorStatement';
31
32
    /**
33
     * Registers the tokens that this sniff wants to listen for.
34
     *
35
     * @return int[] List of tokens to listen for
36
     */
37
    public function register(): array
38
    {
39
        return [
40
            T_OBJECT_OPERATOR
41
        ];
42
    }
43
44
    /**
45
     * Called when one of the token types that this sniff is listening for is found.
46
     *
47
     * @param File $phpcsFile The PHP_CodeSniffer file where the token was found.
48
     * @param int $stackPtr The position in the PHP_CodeSniffer file's token stack where the token was found.
49
     *
50
     * @return void|int Optionally returns a stack pointer.
51
     */
52
    public function process(File $phpcsFile, $stackPtr)
53
    {
54
        $tokens = $phpcsFile->getTokens();
55
56
        if ($this->isValidOperator($tokens, $stackPtr) === false) {
57
            $statement = $phpcsFile->addError(
58
                self::ERROR_NOT_SINGLE_OBJECT_OPERATOR_STATEMENT,
59
                $stackPtr,
60
                self::CODE_NOT_SINGLE_OBJECT_OPERATOR_STATEMENT
61
            );
62
63
            if ($statement) {
64
                $phpcsFile->fixer->beginChangeset();
65
                $phpcsFile->fixer->addNewlineBefore($stackPtr);
66
                $phpcsFile->fixer->endChangeset();
67
            }
68
        }
69
    }
70
71
    /**
72
     * Check if given position of object operator is valid
73
     *
74
     * @param array $tokens
75
     * @param int $stackPtr
76
     *
77
     * @return bool
78
     */
79
    private function isValidOperator($tokens, $stackPtr)
80
    {
81
        // First operator for variable
82
        if ($tokens[$stackPtr - 1]['code'] === T_VARIABLE) {
83
            return true;
84
        }
85
86
        // First operator of line
87
        $offset = $stackPtr;
88
        do {
89
            --$offset;
90
91
            $prevToken = $tokens[$offset] ?? null;
92
93
            if ($prevToken['code'] !== T_WHITESPACE) {
94
                break;
95
            }
96
97
            if ($prevToken['length'] === 0) {
98
                return true;
99
            }
100
        } while ($prevToken !== null);
101
102
        return false;
103
    }
104
}
105