• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPCSStandards / PHP_CodeSniffer / 9182515288

21 May 2024 10:49PM UTC coverage: 73.718% (+0.01%) from 73.705%
9182515288

push

github

jrfnl
Generic/ScopeIndent: add tests for issues 110 and 437

Both the mentioned issues are fixed by the improvements to the `File::findStartOfStatement()` method in this same PR.

Fixes 110
Fixes 437
Fixes squizlabs/PHP_CodeSniffer 3875

17937 of 24332 relevant lines covered (73.72%)

70.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.55
/src/Standards/Generic/Sniffs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceSniff.php
1
<?php
2
/**
3
 * Forbid mixing different binary boolean operators within a single expression without making precedence
4
 * clear using parentheses.
5
 *
6
 * <code>
7
 * $one = false;
8
 * $two = false;
9
 * $three = true;
10
 *
11
 * $result = $one && $two || $three;
12
 * $result3 = $one && !$two xor $three;
13
 * </code>
14
 *
15
 * {@internal The unary `!` operator is not handled, because its high precedence matches its visuals of
16
 * applying only to the sub-expression right next to it, making it unlikely that someone would
17
 * misinterpret its precedence. Requiring parentheses around it would reduce the readability of
18
 * expressions due to the additional characters, especially if multiple subexpressions / variables
19
 * need to be negated.}
20
 *
21
 * Sister-sniff to the `Squiz.ControlStructures.InlineIfDeclaration` and
22
 * `Squiz.Formatting.OperatorBracket.MissingBrackets` sniffs.
23
 *
24
 * @author    Tim Duesterhus <duesterhus@woltlab.com>
25
 * @copyright 2021-2023 WoltLab GmbH.
26
 * @copyright 2024 PHPCSStandards and contributors
27
 * @license   https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
28
 */
29

30
namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis;
31

32
use PHP_CodeSniffer\Files\File;
33
use PHP_CodeSniffer\Sniffs\Sniff;
34
use PHP_CodeSniffer\Util\Tokens;
35

36
class RequireExplicitBooleanOperatorPrecedenceSniff implements Sniff
37
{
38

39
    /**
40
     * Array of tokens this test searches for to find either a boolean
41
     * operator or the start of the current (sub-)expression. Used for
42
     * performance optimization purposes.
43
     *
44
     * @var array<int|string>
45
     */
46
    private $searchTargets = [];
47

48

49
    /**
50
     * Returns an array of tokens this test wants to listen for.
51
     *
52
     * @return array<int|string>
53
     */
54
    public function register()
3✔
55
    {
56
        $this->searchTargets  = Tokens::$booleanOperators;
3✔
57
        $this->searchTargets += Tokens::$blockOpeners;
3✔
58
        $this->searchTargets[T_INLINE_THEN] = T_INLINE_THEN;
3✔
59
        $this->searchTargets[T_INLINE_ELSE] = T_INLINE_ELSE;
3✔
60

61
        return Tokens::$booleanOperators;
3✔
62

63
    }//end register()
64

65

66
    /**
67
     * Processes this test, when one of its tokens is encountered.
68
     *
69
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
70
     * @param int                         $stackPtr  The position of the current token
71
     *                                               in the stack passed in $tokens.
72
     *
73
     * @return void
74
     */
75
    public function process(File $phpcsFile, $stackPtr)
3✔
76
    {
77
        $tokens = $phpcsFile->getTokens();
3✔
78

79
        $start = $phpcsFile->findStartOfStatement($stackPtr);
3✔
80

81
        $previous = $phpcsFile->findPrevious(
3✔
82
            $this->searchTargets,
3✔
83
            ($stackPtr - 1),
3✔
84
            $start,
3✔
85
            false,
3✔
86
            null,
3✔
87
            true
3✔
88
        );
2✔
89

90
        if ($previous === false) {
3✔
91
            // No token found.
92
            return;
3✔
93
        }
94

95
        if ($tokens[$previous]['code'] === $tokens[$stackPtr]['code']) {
3✔
96
            // Identical operator found.
97
            return;
3✔
98
        }
99

100
        if (in_array($tokens[$previous]['code'], [T_INLINE_THEN, T_INLINE_ELSE], true) === true) {
3✔
101
            // Beginning of the expression found for the ternary conditional operator.
102
            return;
3✔
103
        }
104

105
        if (isset(Tokens::$blockOpeners[$tokens[$previous]['code']]) === true) {
3✔
106
            // Beginning of the expression found for a block opener. Needed to
107
            // correctly handle match arms.
108
            return;
×
109
        }
110

111
        // We found a mismatching operator, thus we must report the error.
112
        $error  = 'Mixing different binary boolean operators within an expression';
3✔
113
        $error .= ' without using parentheses to clarify precedence is not allowed.';
3✔
114
        $phpcsFile->addError($error, $stackPtr, 'MissingParentheses');
3✔
115

116
    }//end process()
1✔
117

118

119
}//end class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc