Completed
Pull Request — master (#391)
by Juliette
02:00
created

NewHeredocInitializeSniff   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 129
Duplicated Lines 27.13 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 3
dl 35
loc 129
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
C process() 35 65 15
B throwError() 0 29 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * PHPCompatibility_Sniffs_PHP_NewHeredocInitializeSniff.
4
 *
5
 * PHP version 5.3
6
 *
7
 * @category PHP
8
 * @package  PHPCompatibility
9
 * @author   Juliette Reinders Folmer <[email protected]>
10
 */
11
12
/**
13
 * PHPCompatibility_Sniffs_PHP_NewHeredocInitializeSniff.
14
 *
15
 * As of PHP 5.3.0, it's possible to initialize static variables and class
16
 * properties/constants using the Heredoc syntax.
17
 *
18
 * PHP version 5.3
19
 *
20
 * @category PHP
21
 * @package  PHPCompatibility
22
 * @author   Juliette Reinders Folmer <[email protected]>
23
 */
24
class PHPCompatibility_Sniffs_PHP_NewHeredocInitializeSniff extends PHPCompatibility_Sniff
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
25
{
26
27
    /**
28
     * Returns an array of tokens this test wants to listen for.
29
     *
30
     * @return array
31
     */
32
    public function register()
33
    {
34
        return array(T_START_HEREDOC);
35
    }
36
37
    /**
38
     * Processes this test, when one of its tokens is encountered.
39
     *
40
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
41
     * @param int                  $stackPtr  The position of the current token in the
42
     *                                        stack passed in $tokens.
43
     *
44
     * @return void
45
     */
46
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
47
    {
48
        if ($this->supportsBelow('5.2') !== true) {
49
            return;
50
        }
51
52
        $tokens = $phpcsFile->getTokens();
53
54
        $equalSign = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true);
55
        if ($equalSign === false || $tokens[$equalSign]['code'] !== T_EQUAL) {
56
            // Not an assignment.
57
            return;
58
        }
59
60
        $prevNonEmpty = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($equalSign - 1), null, true, null, true);
61
        if ($prevNonEmpty === false ||
62
            ($tokens[$prevNonEmpty]['code'] !== T_VARIABLE && $tokens[$prevNonEmpty]['code'] !== T_STRING)
63
        ) {
64
            // Not a variable or constant assignment.
65
            return;
66
        }
67
68
69
        switch ($tokens[$prevNonEmpty]['type']) {
70
            /*
71
             * Check class constant assignments.
72
             */
73 View Code Duplication
            case 'T_STRING':
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
                // Walk back to check for the const keyword.
75
                $constPtr = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true, null, true);
76
                if ($constPtr === false || $tokens[$constPtr]['code'] !== T_CONST) {
77
                    // Not a constant assignment.
78
                    return;
79
                }
80
81
                if ($this->isClassConstant($phpcsFile, $constPtr) === true) {
0 ignored issues
show
Bug introduced by
It seems like $constPtr defined by $phpcsFile->findPrevious...null, true, null, true) on line 75 can also be of type boolean; however, PHPCompatibility_Sniff::isClassConstant() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
82
                    $this->throwError($phpcsFile, $stackPtr, 'const');
83
                }
84
                return;
85
86 View Code Duplication
            case 'T_VARIABLE':
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
                /*
88
                 * Check class property assignments.
89
                 */
90
                if ($this->isClassProperty($phpcsFile, $prevNonEmpty) === true) {
0 ignored issues
show
Bug introduced by
It seems like $prevNonEmpty defined by $phpcsFile->findPrevious...null, true, null, true) on line 60 can also be of type boolean; however, PHPCompatibility_Sniff::isClassProperty() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
91
                    $this->throwError($phpcsFile, $stackPtr, 'property');
92
                }
93
94
                /*
95
                 * Check static variable assignments.
96
                 */
97
                else {
98
                    // Walk back to check this is a static variable `static $var =`.
99
                    $staticPtr = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true, null, true);
100
                    if ($staticPtr === false || $tokens[$staticPtr]['code'] !== T_STATIC) {
101
                        // Not a static variable assignment.
102
                        return;
103
                    }
104
105
                    // Still here ? Then we have a static variable assignment
106
                    $this->throwError($phpcsFile, $stackPtr, 'staticvar');
107
                }
108
                return;
109
        }
110
    }
111
112
113
    /**
114
     * Throw an error if a non-static value is found.
115
     *
116
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
117
     * @param int                  $stackPtr  The position of the token to link the error to.
118
     * @param string               $type      Type of usage found.
119
     *
120
     * @return void
121
     */
122
    protected function throwError(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $type)
123
    {
124
        switch($type) {
125
            case 'const':
126
                $phrase = 'class constants';
127
                break;
128
129
            case 'property':
130
                $phrase = 'class properties';
131
                break;
132
133
            case 'staticvar':
134
                $phrase = 'static variables';
135
                break;
136
137
            default:
138
                $phrase = '';
139
                break;
140
        }
141
142
        $errorCode = $this->stringToErrorCode($type) . 'Found';
143
144
        $phpcsFile->addError(
145
            'Initializing %s using the Heredoc syntax was not supported in PHP 5.2 or earlier',
146
            $stackPtr,
147
            $errorCode,
148
            array($phrase)
149
        );
150
    }
151
152
}
153