@@ -29,56 +29,56 @@ |
||
29 | 29 | class NewEmptyNonVariableSniff extends Sniff |
30 | 30 | { |
31 | 31 | |
32 | - /** |
|
33 | - * Returns an array of tokens this test wants to listen for. |
|
34 | - * |
|
35 | - * @return array |
|
36 | - */ |
|
37 | - public function register() |
|
38 | - { |
|
39 | - return array(\T_EMPTY); |
|
40 | - } |
|
32 | + /** |
|
33 | + * Returns an array of tokens this test wants to listen for. |
|
34 | + * |
|
35 | + * @return array |
|
36 | + */ |
|
37 | + public function register() |
|
38 | + { |
|
39 | + return array(\T_EMPTY); |
|
40 | + } |
|
41 | 41 | |
42 | - /** |
|
43 | - * Processes this test, when one of its tokens is encountered. |
|
44 | - * |
|
45 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
46 | - * @param int $stackPtr The position of the current token in the |
|
47 | - * stack passed in $tokens. |
|
48 | - * |
|
49 | - * @return void |
|
50 | - */ |
|
51 | - public function process(File $phpcsFile, $stackPtr) |
|
52 | - { |
|
53 | - if ($this->supportsBelow('5.4') === false) { |
|
54 | - return; |
|
55 | - } |
|
42 | + /** |
|
43 | + * Processes this test, when one of its tokens is encountered. |
|
44 | + * |
|
45 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
46 | + * @param int $stackPtr The position of the current token in the |
|
47 | + * stack passed in $tokens. |
|
48 | + * |
|
49 | + * @return void |
|
50 | + */ |
|
51 | + public function process(File $phpcsFile, $stackPtr) |
|
52 | + { |
|
53 | + if ($this->supportsBelow('5.4') === false) { |
|
54 | + return; |
|
55 | + } |
|
56 | 56 | |
57 | - $tokens = $phpcsFile->getTokens(); |
|
57 | + $tokens = $phpcsFile->getTokens(); |
|
58 | 58 | |
59 | - $open = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); |
|
60 | - if ($open === false |
|
61 | - || $tokens[$open]['code'] !== \T_OPEN_PARENTHESIS |
|
62 | - || isset($tokens[$open]['parenthesis_closer']) === false |
|
63 | - ) { |
|
64 | - return; |
|
65 | - } |
|
59 | + $open = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); |
|
60 | + if ($open === false |
|
61 | + || $tokens[$open]['code'] !== \T_OPEN_PARENTHESIS |
|
62 | + || isset($tokens[$open]['parenthesis_closer']) === false |
|
63 | + ) { |
|
64 | + return; |
|
65 | + } |
|
66 | 66 | |
67 | - $close = $tokens[$open]['parenthesis_closer']; |
|
67 | + $close = $tokens[$open]['parenthesis_closer']; |
|
68 | 68 | |
69 | - $nestingLevel = 0; |
|
70 | - if ($close !== ($open + 1) && isset($tokens[$open + 1]['nested_parenthesis'])) { |
|
71 | - $nestingLevel = \count($tokens[$open + 1]['nested_parenthesis']); |
|
72 | - } |
|
69 | + $nestingLevel = 0; |
|
70 | + if ($close !== ($open + 1) && isset($tokens[$open + 1]['nested_parenthesis'])) { |
|
71 | + $nestingLevel = \count($tokens[$open + 1]['nested_parenthesis']); |
|
72 | + } |
|
73 | 73 | |
74 | - if ($this->isVariable($phpcsFile, ($open + 1), $close, $nestingLevel) === true) { |
|
75 | - return; |
|
76 | - } |
|
74 | + if ($this->isVariable($phpcsFile, ($open + 1), $close, $nestingLevel) === true) { |
|
75 | + return; |
|
76 | + } |
|
77 | 77 | |
78 | - $phpcsFile->addError( |
|
79 | - 'Only variables can be passed to empty() prior to PHP 5.5.', |
|
80 | - $stackPtr, |
|
81 | - 'Found' |
|
82 | - ); |
|
83 | - } |
|
78 | + $phpcsFile->addError( |
|
79 | + 'Only variables can be passed to empty() prior to PHP 5.5.', |
|
80 | + $stackPtr, |
|
81 | + 'Found' |
|
82 | + ); |
|
83 | + } |
|
84 | 84 | } |
@@ -24,117 +24,117 @@ |
||
24 | 24 | class NewLanguageConstructsSniff extends AbstractNewFeatureSniff |
25 | 25 | { |
26 | 26 | |
27 | - /** |
|
28 | - * A list of new language constructs, not present in older versions. |
|
29 | - * |
|
30 | - * The array lists : version number with false (not present) or true (present). |
|
31 | - * If's sufficient to list the first version where the keyword appears. |
|
32 | - * |
|
33 | - * @var array(string => array(string => int|string|null)) |
|
34 | - */ |
|
35 | - protected $newConstructs = array( |
|
36 | - 'T_NS_SEPARATOR' => array( |
|
37 | - '5.2' => false, |
|
38 | - '5.3' => true, |
|
39 | - 'description' => 'the \ operator (for namespaces)', |
|
40 | - ), |
|
41 | - 'T_ELLIPSIS' => array( |
|
42 | - '5.5' => false, |
|
43 | - '5.6' => true, |
|
44 | - 'description' => 'the ... spread operator', |
|
45 | - ), |
|
46 | - ); |
|
47 | - |
|
48 | - |
|
49 | - /** |
|
50 | - * Returns an array of tokens this test wants to listen for. |
|
51 | - * |
|
52 | - * @return array |
|
53 | - */ |
|
54 | - public function register() |
|
55 | - { |
|
56 | - $tokens = array(); |
|
57 | - foreach ($this->newConstructs as $token => $versions) { |
|
58 | - $tokens[] = constant($token); |
|
59 | - } |
|
60 | - return $tokens; |
|
61 | - } |
|
62 | - |
|
63 | - |
|
64 | - /** |
|
65 | - * Processes this test, when one of its tokens is encountered. |
|
66 | - * |
|
67 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
68 | - * @param int $stackPtr The position of the current token in |
|
69 | - * the stack passed in $tokens. |
|
70 | - * |
|
71 | - * @return void |
|
72 | - */ |
|
73 | - public function process(File $phpcsFile, $stackPtr) |
|
74 | - { |
|
75 | - $tokens = $phpcsFile->getTokens(); |
|
76 | - $tokenType = $tokens[$stackPtr]['type']; |
|
77 | - |
|
78 | - $itemInfo = array( |
|
79 | - 'name' => $tokenType, |
|
80 | - ); |
|
81 | - $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); |
|
82 | - } |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * Get the relevant sub-array for a specific item from a multi-dimensional array. |
|
87 | - * |
|
88 | - * @param array $itemInfo Base information about the item. |
|
89 | - * |
|
90 | - * @return array Version and other information about the item. |
|
91 | - */ |
|
92 | - public function getItemArray(array $itemInfo) |
|
93 | - { |
|
94 | - return $this->newConstructs[$itemInfo['name']]; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * Get an array of the non-PHP-version array keys used in a sub-array. |
|
100 | - * |
|
101 | - * @return array |
|
102 | - */ |
|
103 | - protected function getNonVersionArrayKeys() |
|
104 | - { |
|
105 | - return array('description'); |
|
106 | - } |
|
107 | - |
|
108 | - |
|
109 | - /** |
|
110 | - * Retrieve the relevant detail (version) information for use in an error message. |
|
111 | - * |
|
112 | - * @param array $itemArray Version and other information about the item. |
|
113 | - * @param array $itemInfo Base information about the item. |
|
114 | - * |
|
115 | - * @return array |
|
116 | - */ |
|
117 | - public function getErrorInfo(array $itemArray, array $itemInfo) |
|
118 | - { |
|
119 | - $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); |
|
120 | - $errorInfo['description'] = $itemArray['description']; |
|
121 | - |
|
122 | - return $errorInfo; |
|
123 | - } |
|
124 | - |
|
125 | - |
|
126 | - /** |
|
127 | - * Allow for concrete child classes to filter the error data before it's passed to PHPCS. |
|
128 | - * |
|
129 | - * @param array $data The error data array which was created. |
|
130 | - * @param array $itemInfo Base information about the item this error message applies to. |
|
131 | - * @param array $errorInfo Detail information about an item this error message applies to. |
|
132 | - * |
|
133 | - * @return array |
|
134 | - */ |
|
135 | - protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) |
|
136 | - { |
|
137 | - $data[0] = $errorInfo['description']; |
|
138 | - return $data; |
|
139 | - } |
|
27 | + /** |
|
28 | + * A list of new language constructs, not present in older versions. |
|
29 | + * |
|
30 | + * The array lists : version number with false (not present) or true (present). |
|
31 | + * If's sufficient to list the first version where the keyword appears. |
|
32 | + * |
|
33 | + * @var array(string => array(string => int|string|null)) |
|
34 | + */ |
|
35 | + protected $newConstructs = array( |
|
36 | + 'T_NS_SEPARATOR' => array( |
|
37 | + '5.2' => false, |
|
38 | + '5.3' => true, |
|
39 | + 'description' => 'the \ operator (for namespaces)', |
|
40 | + ), |
|
41 | + 'T_ELLIPSIS' => array( |
|
42 | + '5.5' => false, |
|
43 | + '5.6' => true, |
|
44 | + 'description' => 'the ... spread operator', |
|
45 | + ), |
|
46 | + ); |
|
47 | + |
|
48 | + |
|
49 | + /** |
|
50 | + * Returns an array of tokens this test wants to listen for. |
|
51 | + * |
|
52 | + * @return array |
|
53 | + */ |
|
54 | + public function register() |
|
55 | + { |
|
56 | + $tokens = array(); |
|
57 | + foreach ($this->newConstructs as $token => $versions) { |
|
58 | + $tokens[] = constant($token); |
|
59 | + } |
|
60 | + return $tokens; |
|
61 | + } |
|
62 | + |
|
63 | + |
|
64 | + /** |
|
65 | + * Processes this test, when one of its tokens is encountered. |
|
66 | + * |
|
67 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
68 | + * @param int $stackPtr The position of the current token in |
|
69 | + * the stack passed in $tokens. |
|
70 | + * |
|
71 | + * @return void |
|
72 | + */ |
|
73 | + public function process(File $phpcsFile, $stackPtr) |
|
74 | + { |
|
75 | + $tokens = $phpcsFile->getTokens(); |
|
76 | + $tokenType = $tokens[$stackPtr]['type']; |
|
77 | + |
|
78 | + $itemInfo = array( |
|
79 | + 'name' => $tokenType, |
|
80 | + ); |
|
81 | + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); |
|
82 | + } |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * Get the relevant sub-array for a specific item from a multi-dimensional array. |
|
87 | + * |
|
88 | + * @param array $itemInfo Base information about the item. |
|
89 | + * |
|
90 | + * @return array Version and other information about the item. |
|
91 | + */ |
|
92 | + public function getItemArray(array $itemInfo) |
|
93 | + { |
|
94 | + return $this->newConstructs[$itemInfo['name']]; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * Get an array of the non-PHP-version array keys used in a sub-array. |
|
100 | + * |
|
101 | + * @return array |
|
102 | + */ |
|
103 | + protected function getNonVersionArrayKeys() |
|
104 | + { |
|
105 | + return array('description'); |
|
106 | + } |
|
107 | + |
|
108 | + |
|
109 | + /** |
|
110 | + * Retrieve the relevant detail (version) information for use in an error message. |
|
111 | + * |
|
112 | + * @param array $itemArray Version and other information about the item. |
|
113 | + * @param array $itemInfo Base information about the item. |
|
114 | + * |
|
115 | + * @return array |
|
116 | + */ |
|
117 | + public function getErrorInfo(array $itemArray, array $itemInfo) |
|
118 | + { |
|
119 | + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); |
|
120 | + $errorInfo['description'] = $itemArray['description']; |
|
121 | + |
|
122 | + return $errorInfo; |
|
123 | + } |
|
124 | + |
|
125 | + |
|
126 | + /** |
|
127 | + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. |
|
128 | + * |
|
129 | + * @param array $data The error data array which was created. |
|
130 | + * @param array $itemInfo Base information about the item this error message applies to. |
|
131 | + * @param array $errorInfo Detail information about an item this error message applies to. |
|
132 | + * |
|
133 | + * @return array |
|
134 | + */ |
|
135 | + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) |
|
136 | + { |
|
137 | + $data[0] = $errorInfo['description']; |
|
138 | + return $data; |
|
139 | + } |
|
140 | 140 | } |
@@ -22,126 +22,126 @@ |
||
22 | 22 | { |
23 | 23 | |
24 | 24 | |
25 | - /** |
|
26 | - * Determine whether an error/warning should be thrown for an item based on collected information. |
|
27 | - * |
|
28 | - * @param array $errorInfo Detail information about an item. |
|
29 | - * |
|
30 | - * @return bool |
|
31 | - */ |
|
32 | - protected function shouldThrowError(array $errorInfo) |
|
33 | - { |
|
34 | - return ($errorInfo['deprecated'] !== '' || $errorInfo['removed'] !== ''); |
|
35 | - } |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * Get an array of the non-PHP-version array keys used in a sub-array. |
|
40 | - * |
|
41 | - * By default, removed feature version arrays, contain an additional 'alternative' array key. |
|
42 | - * |
|
43 | - * @return array |
|
44 | - */ |
|
45 | - protected function getNonVersionArrayKeys() |
|
46 | - { |
|
47 | - return array('alternative'); |
|
48 | - } |
|
49 | - |
|
50 | - |
|
51 | - /** |
|
52 | - * Retrieve the relevant detail (version) information for use in an error message. |
|
53 | - * |
|
54 | - * @param array $itemArray Version and other information about the item. |
|
55 | - * @param array $itemInfo Base information about the item. |
|
56 | - * |
|
57 | - * @return array |
|
58 | - */ |
|
59 | - public function getErrorInfo(array $itemArray, array $itemInfo) |
|
60 | - { |
|
61 | - $errorInfo = array( |
|
62 | - 'deprecated' => '', |
|
63 | - 'removed' => '', |
|
64 | - 'alternative' => '', |
|
65 | - 'error' => false, |
|
66 | - ); |
|
67 | - |
|
68 | - $versionArray = $this->getVersionArray($itemArray); |
|
69 | - |
|
70 | - if (empty($versionArray) === false) { |
|
71 | - foreach ($versionArray as $version => $removed) { |
|
72 | - if ($this->supportsAbove($version) === true) { |
|
73 | - if ($removed === true && $errorInfo['removed'] === '') { |
|
74 | - $errorInfo['removed'] = $version; |
|
75 | - $errorInfo['error'] = true; |
|
76 | - } elseif ($errorInfo['deprecated'] === '') { |
|
77 | - $errorInfo['deprecated'] = $version; |
|
78 | - } |
|
79 | - } |
|
80 | - } |
|
81 | - } |
|
82 | - |
|
83 | - if (isset($itemArray['alternative']) === true) { |
|
84 | - $errorInfo['alternative'] = $itemArray['alternative']; |
|
85 | - } |
|
86 | - |
|
87 | - return $errorInfo; |
|
88 | - } |
|
89 | - |
|
90 | - |
|
91 | - /** |
|
92 | - * Get the error message template for suggesting an alternative for a specific sniff. |
|
93 | - * |
|
94 | - * @return string |
|
95 | - */ |
|
96 | - protected function getAlternativeOptionTemplate() |
|
97 | - { |
|
98 | - return '; Use %s instead'; |
|
99 | - } |
|
100 | - |
|
101 | - |
|
102 | - /** |
|
103 | - * Generates the error or warning for this item. |
|
104 | - * |
|
105 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
106 | - * @param int $stackPtr The position of the relevant token in |
|
107 | - * the stack. |
|
108 | - * @param array $itemInfo Base information about the item. |
|
109 | - * @param array $errorInfo Array with detail (version) information |
|
110 | - * relevant to the item. |
|
111 | - * |
|
112 | - * @return void |
|
113 | - */ |
|
114 | - public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) |
|
115 | - { |
|
116 | - $itemName = $this->getItemName($itemInfo, $errorInfo); |
|
117 | - $error = $this->getErrorMsgTemplate(); |
|
118 | - |
|
119 | - $errorCode = $this->stringToErrorCode($itemName); |
|
120 | - $data = array($itemName); |
|
121 | - |
|
122 | - if ($errorInfo['deprecated'] !== '') { |
|
123 | - $error .= 'deprecated since PHP %s and '; |
|
124 | - $errorCode .= 'Deprecated'; |
|
125 | - $data[] = $errorInfo['deprecated']; |
|
126 | - } |
|
127 | - |
|
128 | - if ($errorInfo['removed'] !== '') { |
|
129 | - $error .= 'removed since PHP %s and '; |
|
130 | - $errorCode .= 'Removed'; |
|
131 | - $data[] = $errorInfo['removed']; |
|
132 | - } |
|
133 | - |
|
134 | - // Remove the last 'and' from the message. |
|
135 | - $error = substr($error, 0, (\strlen($error) - 5)); |
|
136 | - |
|
137 | - if ($errorInfo['alternative'] !== '') { |
|
138 | - $error .= $this->getAlternativeOptionTemplate(); |
|
139 | - $data[] = $errorInfo['alternative']; |
|
140 | - } |
|
141 | - |
|
142 | - $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); |
|
143 | - $data = $this->filterErrorData($data, $itemInfo, $errorInfo); |
|
144 | - |
|
145 | - $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); |
|
146 | - } |
|
25 | + /** |
|
26 | + * Determine whether an error/warning should be thrown for an item based on collected information. |
|
27 | + * |
|
28 | + * @param array $errorInfo Detail information about an item. |
|
29 | + * |
|
30 | + * @return bool |
|
31 | + */ |
|
32 | + protected function shouldThrowError(array $errorInfo) |
|
33 | + { |
|
34 | + return ($errorInfo['deprecated'] !== '' || $errorInfo['removed'] !== ''); |
|
35 | + } |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * Get an array of the non-PHP-version array keys used in a sub-array. |
|
40 | + * |
|
41 | + * By default, removed feature version arrays, contain an additional 'alternative' array key. |
|
42 | + * |
|
43 | + * @return array |
|
44 | + */ |
|
45 | + protected function getNonVersionArrayKeys() |
|
46 | + { |
|
47 | + return array('alternative'); |
|
48 | + } |
|
49 | + |
|
50 | + |
|
51 | + /** |
|
52 | + * Retrieve the relevant detail (version) information for use in an error message. |
|
53 | + * |
|
54 | + * @param array $itemArray Version and other information about the item. |
|
55 | + * @param array $itemInfo Base information about the item. |
|
56 | + * |
|
57 | + * @return array |
|
58 | + */ |
|
59 | + public function getErrorInfo(array $itemArray, array $itemInfo) |
|
60 | + { |
|
61 | + $errorInfo = array( |
|
62 | + 'deprecated' => '', |
|
63 | + 'removed' => '', |
|
64 | + 'alternative' => '', |
|
65 | + 'error' => false, |
|
66 | + ); |
|
67 | + |
|
68 | + $versionArray = $this->getVersionArray($itemArray); |
|
69 | + |
|
70 | + if (empty($versionArray) === false) { |
|
71 | + foreach ($versionArray as $version => $removed) { |
|
72 | + if ($this->supportsAbove($version) === true) { |
|
73 | + if ($removed === true && $errorInfo['removed'] === '') { |
|
74 | + $errorInfo['removed'] = $version; |
|
75 | + $errorInfo['error'] = true; |
|
76 | + } elseif ($errorInfo['deprecated'] === '') { |
|
77 | + $errorInfo['deprecated'] = $version; |
|
78 | + } |
|
79 | + } |
|
80 | + } |
|
81 | + } |
|
82 | + |
|
83 | + if (isset($itemArray['alternative']) === true) { |
|
84 | + $errorInfo['alternative'] = $itemArray['alternative']; |
|
85 | + } |
|
86 | + |
|
87 | + return $errorInfo; |
|
88 | + } |
|
89 | + |
|
90 | + |
|
91 | + /** |
|
92 | + * Get the error message template for suggesting an alternative for a specific sniff. |
|
93 | + * |
|
94 | + * @return string |
|
95 | + */ |
|
96 | + protected function getAlternativeOptionTemplate() |
|
97 | + { |
|
98 | + return '; Use %s instead'; |
|
99 | + } |
|
100 | + |
|
101 | + |
|
102 | + /** |
|
103 | + * Generates the error or warning for this item. |
|
104 | + * |
|
105 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
106 | + * @param int $stackPtr The position of the relevant token in |
|
107 | + * the stack. |
|
108 | + * @param array $itemInfo Base information about the item. |
|
109 | + * @param array $errorInfo Array with detail (version) information |
|
110 | + * relevant to the item. |
|
111 | + * |
|
112 | + * @return void |
|
113 | + */ |
|
114 | + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) |
|
115 | + { |
|
116 | + $itemName = $this->getItemName($itemInfo, $errorInfo); |
|
117 | + $error = $this->getErrorMsgTemplate(); |
|
118 | + |
|
119 | + $errorCode = $this->stringToErrorCode($itemName); |
|
120 | + $data = array($itemName); |
|
121 | + |
|
122 | + if ($errorInfo['deprecated'] !== '') { |
|
123 | + $error .= 'deprecated since PHP %s and '; |
|
124 | + $errorCode .= 'Deprecated'; |
|
125 | + $data[] = $errorInfo['deprecated']; |
|
126 | + } |
|
127 | + |
|
128 | + if ($errorInfo['removed'] !== '') { |
|
129 | + $error .= 'removed since PHP %s and '; |
|
130 | + $errorCode .= 'Removed'; |
|
131 | + $data[] = $errorInfo['removed']; |
|
132 | + } |
|
133 | + |
|
134 | + // Remove the last 'and' from the message. |
|
135 | + $error = substr($error, 0, (\strlen($error) - 5)); |
|
136 | + |
|
137 | + if ($errorInfo['alternative'] !== '') { |
|
138 | + $error .= $this->getAlternativeOptionTemplate(); |
|
139 | + $data[] = $errorInfo['alternative']; |
|
140 | + } |
|
141 | + |
|
142 | + $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); |
|
143 | + $data = $this->filterErrorData($data, $itemInfo, $errorInfo); |
|
144 | + |
|
145 | + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); |
|
146 | + } |
|
147 | 147 | } |
@@ -24,157 +24,157 @@ |
||
24 | 24 | */ |
25 | 25 | abstract class AbstractFunctionCallParameterSniff extends Sniff |
26 | 26 | { |
27 | - /** |
|
28 | - * Is the sniff looking for a function call or a method call ? |
|
29 | - * |
|
30 | - * Note: the child class may need to do additional checks to make sure that |
|
31 | - * the method called is of the right class/object. |
|
32 | - * Checking that is outside of the scope of this abstract sniff. |
|
33 | - * |
|
34 | - * @var bool False (default) if the sniff is looking for function calls. |
|
35 | - * True if the sniff is looking for method calls. |
|
36 | - */ |
|
37 | - protected $isMethod = false; |
|
38 | - |
|
39 | - /** |
|
40 | - * Functions the sniff is looking for. Should be defined in the child class. |
|
41 | - * |
|
42 | - * @var array The only requirement for this array is that the top level |
|
43 | - * array keys are the names of the functions you're looking for. |
|
44 | - * Other than that, the array can have arbitrary content |
|
45 | - * depending on your needs. |
|
46 | - */ |
|
47 | - protected $targetFunctions = array(); |
|
48 | - |
|
49 | - /** |
|
50 | - * List of tokens which when they preceed the $stackPtr indicate that this |
|
51 | - * is not a function call. |
|
52 | - * |
|
53 | - * @var array |
|
54 | - */ |
|
55 | - private $ignoreTokens = array( |
|
56 | - \T_DOUBLE_COLON => true, |
|
57 | - \T_OBJECT_OPERATOR => true, |
|
58 | - \T_FUNCTION => true, |
|
59 | - \T_NEW => true, |
|
60 | - \T_CONST => true, |
|
61 | - \T_USE => true, |
|
62 | - ); |
|
63 | - |
|
64 | - |
|
65 | - /** |
|
66 | - * Returns an array of tokens this test wants to listen for. |
|
67 | - * |
|
68 | - * @return array |
|
69 | - */ |
|
70 | - public function register() |
|
71 | - { |
|
72 | - // Handle case-insensitivity of function names. |
|
73 | - $this->targetFunctions = $this->arrayKeysToLowercase($this->targetFunctions); |
|
74 | - |
|
75 | - return array(\T_STRING); |
|
76 | - } |
|
77 | - |
|
78 | - |
|
79 | - /** |
|
80 | - * Processes this test, when one of its tokens is encountered. |
|
81 | - * |
|
82 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
83 | - * @param int $stackPtr The position of the current token in |
|
84 | - * the stack passed in $tokens. |
|
85 | - * |
|
86 | - * @return int|void Integer stack pointer to skip forward or void to continue |
|
87 | - * normal file processing. |
|
88 | - */ |
|
89 | - public function process(File $phpcsFile, $stackPtr) |
|
90 | - { |
|
91 | - if ($this->bowOutEarly() === true) { |
|
92 | - return; |
|
93 | - } |
|
94 | - |
|
95 | - $tokens = $phpcsFile->getTokens(); |
|
96 | - $function = $tokens[$stackPtr]['content']; |
|
97 | - $functionLc = strtolower($function); |
|
98 | - |
|
99 | - if (isset($this->targetFunctions[$functionLc]) === false) { |
|
100 | - return; |
|
101 | - } |
|
102 | - |
|
103 | - $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); |
|
104 | - |
|
105 | - if ($this->isMethod === true) { |
|
106 | - if ($tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON |
|
107 | - && $tokens[$prevNonEmpty]['code'] !== \T_OBJECT_OPERATOR |
|
108 | - ) { |
|
109 | - // Not a call to a PHP method. |
|
110 | - return; |
|
111 | - } |
|
112 | - } else { |
|
113 | - if (isset($this->ignoreTokens[$tokens[$prevNonEmpty]['code']]) === true) { |
|
114 | - // Not a call to a PHP function. |
|
115 | - return; |
|
116 | - } |
|
117 | - |
|
118 | - if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR |
|
119 | - && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING |
|
120 | - ) { |
|
121 | - // Namespaced function. |
|
122 | - return; |
|
123 | - } |
|
124 | - } |
|
125 | - |
|
126 | - $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); |
|
127 | - |
|
128 | - if (empty($parameters)) { |
|
129 | - return $this->processNoParameters($phpcsFile, $stackPtr, $function); |
|
130 | - } else { |
|
131 | - return $this->processParameters($phpcsFile, $stackPtr, $function, $parameters); |
|
132 | - } |
|
133 | - } |
|
134 | - |
|
135 | - |
|
136 | - /** |
|
137 | - * Do a version check to determine if this sniff needs to run at all. |
|
138 | - * |
|
139 | - * If the check done in a child class is not specific to one PHP version, |
|
140 | - * this function should return `false`. |
|
141 | - * |
|
142 | - * @return bool |
|
143 | - */ |
|
144 | - abstract protected function bowOutEarly(); |
|
145 | - |
|
146 | - |
|
147 | - /** |
|
148 | - * Process the parameters of a matched function. |
|
149 | - * |
|
150 | - * This method has to be made concrete in child classes. |
|
151 | - * |
|
152 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
153 | - * @param int $stackPtr The position of the current token in the stack. |
|
154 | - * @param string $functionName The token content (function name) which was matched. |
|
155 | - * @param array $parameters Array with information about the parameters. |
|
156 | - * |
|
157 | - * @return int|void Integer stack pointer to skip forward or void to continue |
|
158 | - * normal file processing. |
|
159 | - */ |
|
160 | - abstract public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters); |
|
161 | - |
|
162 | - |
|
163 | - /** |
|
164 | - * Process the function if no parameters were found. |
|
165 | - * |
|
166 | - * Defaults to doing nothing. Can be overloaded in child classes to handle functions |
|
167 | - * were parameters are expected, but none found. |
|
168 | - * |
|
169 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
170 | - * @param int $stackPtr The position of the current token in the stack. |
|
171 | - * @param string $functionName The token content (function name) which was matched. |
|
172 | - * |
|
173 | - * @return int|void Integer stack pointer to skip forward or void to continue |
|
174 | - * normal file processing. |
|
175 | - */ |
|
176 | - public function processNoParameters(File $phpcsFile, $stackPtr, $functionName) |
|
177 | - { |
|
178 | - return; |
|
179 | - } |
|
27 | + /** |
|
28 | + * Is the sniff looking for a function call or a method call ? |
|
29 | + * |
|
30 | + * Note: the child class may need to do additional checks to make sure that |
|
31 | + * the method called is of the right class/object. |
|
32 | + * Checking that is outside of the scope of this abstract sniff. |
|
33 | + * |
|
34 | + * @var bool False (default) if the sniff is looking for function calls. |
|
35 | + * True if the sniff is looking for method calls. |
|
36 | + */ |
|
37 | + protected $isMethod = false; |
|
38 | + |
|
39 | + /** |
|
40 | + * Functions the sniff is looking for. Should be defined in the child class. |
|
41 | + * |
|
42 | + * @var array The only requirement for this array is that the top level |
|
43 | + * array keys are the names of the functions you're looking for. |
|
44 | + * Other than that, the array can have arbitrary content |
|
45 | + * depending on your needs. |
|
46 | + */ |
|
47 | + protected $targetFunctions = array(); |
|
48 | + |
|
49 | + /** |
|
50 | + * List of tokens which when they preceed the $stackPtr indicate that this |
|
51 | + * is not a function call. |
|
52 | + * |
|
53 | + * @var array |
|
54 | + */ |
|
55 | + private $ignoreTokens = array( |
|
56 | + \T_DOUBLE_COLON => true, |
|
57 | + \T_OBJECT_OPERATOR => true, |
|
58 | + \T_FUNCTION => true, |
|
59 | + \T_NEW => true, |
|
60 | + \T_CONST => true, |
|
61 | + \T_USE => true, |
|
62 | + ); |
|
63 | + |
|
64 | + |
|
65 | + /** |
|
66 | + * Returns an array of tokens this test wants to listen for. |
|
67 | + * |
|
68 | + * @return array |
|
69 | + */ |
|
70 | + public function register() |
|
71 | + { |
|
72 | + // Handle case-insensitivity of function names. |
|
73 | + $this->targetFunctions = $this->arrayKeysToLowercase($this->targetFunctions); |
|
74 | + |
|
75 | + return array(\T_STRING); |
|
76 | + } |
|
77 | + |
|
78 | + |
|
79 | + /** |
|
80 | + * Processes this test, when one of its tokens is encountered. |
|
81 | + * |
|
82 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
83 | + * @param int $stackPtr The position of the current token in |
|
84 | + * the stack passed in $tokens. |
|
85 | + * |
|
86 | + * @return int|void Integer stack pointer to skip forward or void to continue |
|
87 | + * normal file processing. |
|
88 | + */ |
|
89 | + public function process(File $phpcsFile, $stackPtr) |
|
90 | + { |
|
91 | + if ($this->bowOutEarly() === true) { |
|
92 | + return; |
|
93 | + } |
|
94 | + |
|
95 | + $tokens = $phpcsFile->getTokens(); |
|
96 | + $function = $tokens[$stackPtr]['content']; |
|
97 | + $functionLc = strtolower($function); |
|
98 | + |
|
99 | + if (isset($this->targetFunctions[$functionLc]) === false) { |
|
100 | + return; |
|
101 | + } |
|
102 | + |
|
103 | + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); |
|
104 | + |
|
105 | + if ($this->isMethod === true) { |
|
106 | + if ($tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON |
|
107 | + && $tokens[$prevNonEmpty]['code'] !== \T_OBJECT_OPERATOR |
|
108 | + ) { |
|
109 | + // Not a call to a PHP method. |
|
110 | + return; |
|
111 | + } |
|
112 | + } else { |
|
113 | + if (isset($this->ignoreTokens[$tokens[$prevNonEmpty]['code']]) === true) { |
|
114 | + // Not a call to a PHP function. |
|
115 | + return; |
|
116 | + } |
|
117 | + |
|
118 | + if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR |
|
119 | + && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING |
|
120 | + ) { |
|
121 | + // Namespaced function. |
|
122 | + return; |
|
123 | + } |
|
124 | + } |
|
125 | + |
|
126 | + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); |
|
127 | + |
|
128 | + if (empty($parameters)) { |
|
129 | + return $this->processNoParameters($phpcsFile, $stackPtr, $function); |
|
130 | + } else { |
|
131 | + return $this->processParameters($phpcsFile, $stackPtr, $function, $parameters); |
|
132 | + } |
|
133 | + } |
|
134 | + |
|
135 | + |
|
136 | + /** |
|
137 | + * Do a version check to determine if this sniff needs to run at all. |
|
138 | + * |
|
139 | + * If the check done in a child class is not specific to one PHP version, |
|
140 | + * this function should return `false`. |
|
141 | + * |
|
142 | + * @return bool |
|
143 | + */ |
|
144 | + abstract protected function bowOutEarly(); |
|
145 | + |
|
146 | + |
|
147 | + /** |
|
148 | + * Process the parameters of a matched function. |
|
149 | + * |
|
150 | + * This method has to be made concrete in child classes. |
|
151 | + * |
|
152 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
153 | + * @param int $stackPtr The position of the current token in the stack. |
|
154 | + * @param string $functionName The token content (function name) which was matched. |
|
155 | + * @param array $parameters Array with information about the parameters. |
|
156 | + * |
|
157 | + * @return int|void Integer stack pointer to skip forward or void to continue |
|
158 | + * normal file processing. |
|
159 | + */ |
|
160 | + abstract public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters); |
|
161 | + |
|
162 | + |
|
163 | + /** |
|
164 | + * Process the function if no parameters were found. |
|
165 | + * |
|
166 | + * Defaults to doing nothing. Can be overloaded in child classes to handle functions |
|
167 | + * were parameters are expected, but none found. |
|
168 | + * |
|
169 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
170 | + * @param int $stackPtr The position of the current token in the stack. |
|
171 | + * @param string $functionName The token content (function name) which was matched. |
|
172 | + * |
|
173 | + * @return int|void Integer stack pointer to skip forward or void to continue |
|
174 | + * normal file processing. |
|
175 | + */ |
|
176 | + public function processNoParameters(File $phpcsFile, $stackPtr, $functionName) |
|
177 | + { |
|
178 | + return; |
|
179 | + } |
|
180 | 180 | } |
@@ -30,623 +30,623 @@ |
||
30 | 30 | class PHPCSHelper |
31 | 31 | { |
32 | 32 | |
33 | - /** |
|
34 | - * Get the PHPCS version number. |
|
35 | - * |
|
36 | - * @return string |
|
37 | - */ |
|
38 | - public static function getVersion() |
|
39 | - { |
|
40 | - if (\defined('\PHP_CodeSniffer\Config::VERSION')) { |
|
41 | - // PHPCS 3.x. |
|
42 | - return \PHP_CodeSniffer\Config::VERSION; |
|
43 | - } else { |
|
44 | - // PHPCS 2.x. |
|
45 | - return \PHP_CodeSniffer::VERSION; |
|
46 | - } |
|
47 | - } |
|
48 | - |
|
49 | - |
|
50 | - /** |
|
51 | - * Pass config data to PHPCS. |
|
52 | - * |
|
53 | - * PHPCS cross-version compatibility helper. |
|
54 | - * |
|
55 | - * @param string $key The name of the config value. |
|
56 | - * @param string|null $value The value to set. If null, the config entry |
|
57 | - * is deleted, reverting it to the default value. |
|
58 | - * @param boolean $temp Set this config data temporarily for this script run. |
|
59 | - * This will not write the config data to the config file. |
|
60 | - * |
|
61 | - * @return void |
|
62 | - */ |
|
63 | - public static function setConfigData($key, $value, $temp = false) |
|
64 | - { |
|
65 | - if (method_exists('\PHP_CodeSniffer\Config', 'setConfigData')) { |
|
66 | - // PHPCS 3.x. |
|
67 | - \PHP_CodeSniffer\Config::setConfigData($key, $value, $temp); |
|
68 | - } else { |
|
69 | - // PHPCS 2.x. |
|
70 | - \PHP_CodeSniffer::setConfigData($key, $value, $temp); |
|
71 | - } |
|
72 | - } |
|
73 | - |
|
74 | - |
|
75 | - /** |
|
76 | - * Get the value of a single PHPCS config key. |
|
77 | - * |
|
78 | - * @param string $key The name of the config value. |
|
79 | - * |
|
80 | - * @return string|null |
|
81 | - */ |
|
82 | - public static function getConfigData($key) |
|
83 | - { |
|
84 | - if (method_exists('\PHP_CodeSniffer\Config', 'getConfigData')) { |
|
85 | - // PHPCS 3.x. |
|
86 | - return \PHP_CodeSniffer\Config::getConfigData($key); |
|
87 | - } else { |
|
88 | - // PHPCS 2.x. |
|
89 | - return \PHP_CodeSniffer::getConfigData($key); |
|
90 | - } |
|
91 | - } |
|
92 | - |
|
93 | - |
|
94 | - /** |
|
95 | - * Get the value of a single PHPCS config key. |
|
96 | - * |
|
97 | - * This config key can be set in the `CodeSniffer.conf` file, on the |
|
98 | - * command-line or in a ruleset. |
|
99 | - * |
|
100 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
101 | - * @param string $key The name of the config value. |
|
102 | - * |
|
103 | - * @return string|null |
|
104 | - */ |
|
105 | - public static function getCommandLineData(File $phpcsFile, $key) |
|
106 | - { |
|
107 | - if (class_exists('\PHP_CodeSniffer\Config')) { |
|
108 | - // PHPCS 3.x. |
|
109 | - $config = $phpcsFile->config; |
|
110 | - if (isset($config->{$key})) { |
|
111 | - return $config->{$key}; |
|
112 | - } |
|
113 | - } else { |
|
114 | - // PHPCS 2.x. |
|
115 | - $config = $phpcsFile->phpcs->cli->getCommandLineValues(); |
|
116 | - if (isset($config[$key])) { |
|
117 | - return $config[$key]; |
|
118 | - } |
|
119 | - } |
|
120 | - |
|
121 | - return null; |
|
122 | - } |
|
123 | - |
|
124 | - |
|
125 | - /** |
|
126 | - * Returns the position of the first non-whitespace token in a statement. |
|
127 | - * |
|
128 | - * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
129 | - * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1. |
|
130 | - * |
|
131 | - * Once the minimum supported PHPCS version for this standard goes beyond |
|
132 | - * that, this method can be removed and calls to it replaced with |
|
133 | - * `$phpcsFile->findStartOfStatement($start, $ignore)` calls. |
|
134 | - * |
|
135 | - * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e}} |
|
136 | - * |
|
137 | - * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
138 | - * @param int $start The position to start searching from in the token stack. |
|
139 | - * @param int|array $ignore Token types that should not be considered stop points. |
|
140 | - * |
|
141 | - * @return int |
|
142 | - */ |
|
143 | - public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null) |
|
144 | - { |
|
145 | - if (version_compare(self::getVersion(), '2.7.1', '>=') === true) { |
|
146 | - return $phpcsFile->findStartOfStatement($start, $ignore); |
|
147 | - } |
|
148 | - |
|
149 | - $tokens = $phpcsFile->getTokens(); |
|
150 | - $endTokens = Tokens::$blockOpeners; |
|
151 | - |
|
152 | - $endTokens[\T_COLON] = true; |
|
153 | - $endTokens[\T_COMMA] = true; |
|
154 | - $endTokens[\T_DOUBLE_ARROW] = true; |
|
155 | - $endTokens[\T_SEMICOLON] = true; |
|
156 | - $endTokens[\T_OPEN_TAG] = true; |
|
157 | - $endTokens[\T_CLOSE_TAG] = true; |
|
158 | - $endTokens[\T_OPEN_SHORT_ARRAY] = true; |
|
159 | - |
|
160 | - if ($ignore !== null) { |
|
161 | - $ignore = (array) $ignore; |
|
162 | - foreach ($ignore as $code) { |
|
163 | - if (isset($endTokens[$code]) === true) { |
|
164 | - unset($endTokens[$code]); |
|
165 | - } |
|
166 | - } |
|
167 | - } |
|
168 | - |
|
169 | - $lastNotEmpty = $start; |
|
170 | - |
|
171 | - for ($i = $start; $i >= 0; $i--) { |
|
172 | - if (isset($endTokens[$tokens[$i]['code']]) === true) { |
|
173 | - // Found the end of the previous statement. |
|
174 | - return $lastNotEmpty; |
|
175 | - } |
|
176 | - |
|
177 | - if (isset($tokens[$i]['scope_opener']) === true |
|
178 | - && $i === $tokens[$i]['scope_closer'] |
|
179 | - ) { |
|
180 | - // Found the end of the previous scope block. |
|
181 | - return $lastNotEmpty; |
|
182 | - } |
|
183 | - |
|
184 | - // Skip nested statements. |
|
185 | - if (isset($tokens[$i]['bracket_opener']) === true |
|
186 | - && $i === $tokens[$i]['bracket_closer'] |
|
187 | - ) { |
|
188 | - $i = $tokens[$i]['bracket_opener']; |
|
189 | - } elseif (isset($tokens[$i]['parenthesis_opener']) === true |
|
190 | - && $i === $tokens[$i]['parenthesis_closer'] |
|
191 | - ) { |
|
192 | - $i = $tokens[$i]['parenthesis_opener']; |
|
193 | - } |
|
194 | - |
|
195 | - if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { |
|
196 | - $lastNotEmpty = $i; |
|
197 | - } |
|
198 | - }//end for |
|
199 | - |
|
200 | - return 0; |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * Returns the position of the last non-whitespace token in a statement. |
|
206 | - * |
|
207 | - * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
208 | - * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0. |
|
209 | - * |
|
210 | - * Once the minimum supported PHPCS version for this standard goes beyond |
|
211 | - * that, this method can be removed and calls to it replaced with |
|
212 | - * `$phpcsFile->findEndOfStatement($start, $ignore)` calls. |
|
213 | - * |
|
214 | - * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823}} |
|
215 | - * |
|
216 | - * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
217 | - * @param int $start The position to start searching from in the token stack. |
|
218 | - * @param int|array $ignore Token types that should not be considered stop points. |
|
219 | - * |
|
220 | - * @return int |
|
221 | - */ |
|
222 | - public static function findEndOfStatement(File $phpcsFile, $start, $ignore = null) |
|
223 | - { |
|
224 | - if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { |
|
225 | - return $phpcsFile->findEndOfStatement($start, $ignore); |
|
226 | - } |
|
227 | - |
|
228 | - $tokens = $phpcsFile->getTokens(); |
|
229 | - $endTokens = array( |
|
230 | - \T_COLON => true, |
|
231 | - \T_COMMA => true, |
|
232 | - \T_DOUBLE_ARROW => true, |
|
233 | - \T_SEMICOLON => true, |
|
234 | - \T_CLOSE_PARENTHESIS => true, |
|
235 | - \T_CLOSE_SQUARE_BRACKET => true, |
|
236 | - \T_CLOSE_CURLY_BRACKET => true, |
|
237 | - \T_CLOSE_SHORT_ARRAY => true, |
|
238 | - \T_OPEN_TAG => true, |
|
239 | - \T_CLOSE_TAG => true, |
|
240 | - ); |
|
241 | - |
|
242 | - if ($ignore !== null) { |
|
243 | - $ignore = (array) $ignore; |
|
244 | - foreach ($ignore as $code) { |
|
245 | - if (isset($endTokens[$code]) === true) { |
|
246 | - unset($endTokens[$code]); |
|
247 | - } |
|
248 | - } |
|
249 | - } |
|
250 | - |
|
251 | - $lastNotEmpty = $start; |
|
252 | - |
|
253 | - for ($i = $start; $i < $phpcsFile->numTokens; $i++) { |
|
254 | - if ($i !== $start && isset($endTokens[$tokens[$i]['code']]) === true) { |
|
255 | - // Found the end of the statement. |
|
256 | - if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS |
|
257 | - || $tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET |
|
258 | - || $tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET |
|
259 | - || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY |
|
260 | - || $tokens[$i]['code'] === \T_OPEN_TAG |
|
261 | - || $tokens[$i]['code'] === \T_CLOSE_TAG |
|
262 | - ) { |
|
263 | - return $lastNotEmpty; |
|
264 | - } |
|
265 | - |
|
266 | - return $i; |
|
267 | - } |
|
268 | - |
|
269 | - // Skip nested statements. |
|
270 | - if (isset($tokens[$i]['scope_closer']) === true |
|
271 | - && ($i === $tokens[$i]['scope_opener'] |
|
272 | - || $i === $tokens[$i]['scope_condition']) |
|
273 | - ) { |
|
274 | - if ($i === $start && isset(Tokens::$scopeOpeners[$tokens[$i]['code']]) === true) { |
|
275 | - return $tokens[$i]['scope_closer']; |
|
276 | - } |
|
277 | - |
|
278 | - $i = $tokens[$i]['scope_closer']; |
|
279 | - } elseif (isset($tokens[$i]['bracket_closer']) === true |
|
280 | - && $i === $tokens[$i]['bracket_opener'] |
|
281 | - ) { |
|
282 | - $i = $tokens[$i]['bracket_closer']; |
|
283 | - } elseif (isset($tokens[$i]['parenthesis_closer']) === true |
|
284 | - && $i === $tokens[$i]['parenthesis_opener'] |
|
285 | - ) { |
|
286 | - $i = $tokens[$i]['parenthesis_closer']; |
|
287 | - } |
|
288 | - |
|
289 | - if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { |
|
290 | - $lastNotEmpty = $i; |
|
291 | - } |
|
292 | - }//end for |
|
293 | - |
|
294 | - return ($phpcsFile->numTokens - 1); |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * Returns the name of the class that the specified class extends |
|
300 | - * (works for classes, anonymous classes and interfaces). |
|
301 | - * |
|
302 | - * Returns FALSE on error or if there is no extended class name. |
|
303 | - * |
|
304 | - * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
305 | - * class, but with some improvements which have been introduced in |
|
306 | - * PHPCS 2.8.0. |
|
307 | - * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}. |
|
308 | - * |
|
309 | - * Once the minimum supported PHPCS version for this standard goes beyond |
|
310 | - * that, this method can be removed and calls to it replaced with |
|
311 | - * `$phpcsFile->findExtendedClassName($stackPtr)` calls. |
|
312 | - * |
|
313 | - * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6}} |
|
314 | - * |
|
315 | - * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
316 | - * @param int $stackPtr The position of the class token in the stack. |
|
317 | - * |
|
318 | - * @return string|false |
|
319 | - */ |
|
320 | - public static function findExtendedClassName(File $phpcsFile, $stackPtr) |
|
321 | - { |
|
322 | - if (version_compare(self::getVersion(), '3.1.0', '>=') === true) { |
|
323 | - return $phpcsFile->findExtendedClassName($stackPtr); |
|
324 | - } |
|
325 | - |
|
326 | - $tokens = $phpcsFile->getTokens(); |
|
327 | - |
|
328 | - // Check for the existence of the token. |
|
329 | - if (isset($tokens[$stackPtr]) === false) { |
|
330 | - return false; |
|
331 | - } |
|
332 | - |
|
333 | - if ($tokens[$stackPtr]['code'] !== \T_CLASS |
|
334 | - && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' |
|
335 | - && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' |
|
336 | - ) { |
|
337 | - return false; |
|
338 | - } |
|
339 | - |
|
340 | - if (isset($tokens[$stackPtr]['scope_closer']) === false) { |
|
341 | - return false; |
|
342 | - } |
|
343 | - |
|
344 | - $classCloserIndex = $tokens[$stackPtr]['scope_closer']; |
|
345 | - $extendsIndex = $phpcsFile->findNext(\T_EXTENDS, $stackPtr, $classCloserIndex); |
|
346 | - if ($extendsIndex === false) { |
|
347 | - return false; |
|
348 | - } |
|
349 | - |
|
350 | - $find = array( |
|
351 | - \T_NS_SEPARATOR, |
|
352 | - \T_STRING, |
|
353 | - \T_WHITESPACE, |
|
354 | - ); |
|
355 | - |
|
356 | - $end = $phpcsFile->findNext($find, ($extendsIndex + 1), $classCloserIndex, true); |
|
357 | - $name = $phpcsFile->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); |
|
358 | - $name = trim($name); |
|
359 | - |
|
360 | - if ($name === '') { |
|
361 | - return false; |
|
362 | - } |
|
363 | - |
|
364 | - return $name; |
|
365 | - } |
|
366 | - |
|
367 | - |
|
368 | - /** |
|
369 | - * Returns the name(s) of the interface(s) that the specified class implements. |
|
370 | - * |
|
371 | - * Returns FALSE on error or if there are no implemented interface names. |
|
372 | - * |
|
373 | - * {@internal Duplicate of same method as introduced in PHPCS 2.7. |
|
374 | - * This method also includes an improvement we use which was only introduced |
|
375 | - * in PHPCS 2.8.0, so only defer to upstream for higher versions. |
|
376 | - * Once the minimum supported PHPCS version for this sniff library goes beyond |
|
377 | - * that, this method can be removed and calls to it replaced with |
|
378 | - * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.}} |
|
379 | - * |
|
380 | - * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
381 | - * @param int $stackPtr The position of the class token. |
|
382 | - * |
|
383 | - * @return array|false |
|
384 | - */ |
|
385 | - public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr) |
|
386 | - { |
|
387 | - if (version_compare(self::getVersion(), '2.7.1', '>') === true) { |
|
388 | - return $phpcsFile->findImplementedInterfaceNames($stackPtr); |
|
389 | - } |
|
390 | - |
|
391 | - $tokens = $phpcsFile->getTokens(); |
|
392 | - |
|
393 | - // Check for the existence of the token. |
|
394 | - if (isset($tokens[$stackPtr]) === false) { |
|
395 | - return false; |
|
396 | - } |
|
397 | - |
|
398 | - if ($tokens[$stackPtr]['code'] !== \T_CLASS |
|
399 | - && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' |
|
400 | - ) { |
|
401 | - return false; |
|
402 | - } |
|
403 | - |
|
404 | - if (isset($tokens[$stackPtr]['scope_closer']) === false) { |
|
405 | - return false; |
|
406 | - } |
|
407 | - |
|
408 | - $classOpenerIndex = $tokens[$stackPtr]['scope_opener']; |
|
409 | - $implementsIndex = $phpcsFile->findNext(\T_IMPLEMENTS, $stackPtr, $classOpenerIndex); |
|
410 | - if ($implementsIndex === false) { |
|
411 | - return false; |
|
412 | - } |
|
413 | - |
|
414 | - $find = array( |
|
415 | - \T_NS_SEPARATOR, |
|
416 | - \T_STRING, |
|
417 | - \T_WHITESPACE, |
|
418 | - \T_COMMA, |
|
419 | - ); |
|
420 | - |
|
421 | - $end = $phpcsFile->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); |
|
422 | - $name = $phpcsFile->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); |
|
423 | - $name = trim($name); |
|
424 | - |
|
425 | - if ($name === '') { |
|
426 | - return false; |
|
427 | - } else { |
|
428 | - $names = explode(',', $name); |
|
429 | - $names = array_map('trim', $names); |
|
430 | - return $names; |
|
431 | - } |
|
432 | - } |
|
433 | - |
|
434 | - |
|
435 | - /** |
|
436 | - * Returns the method parameters for the specified function token. |
|
437 | - * |
|
438 | - * Each parameter is in the following format: |
|
439 | - * |
|
440 | - * <code> |
|
441 | - * 0 => array( |
|
442 | - * 'name' => '$var', // The variable name. |
|
443 | - * 'token' => integer, // The stack pointer to the variable name. |
|
444 | - * 'content' => string, // The full content of the variable definition. |
|
445 | - * 'pass_by_reference' => boolean, // Is the variable passed by reference? |
|
446 | - * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? |
|
447 | - * 'type_hint' => string, // The type hint for the variable. |
|
448 | - * 'type_hint_token' => integer, // The stack pointer to the type hint |
|
449 | - * // or false if there is no type hint. |
|
450 | - * 'nullable_type' => boolean, // Is the variable using a nullable type? |
|
451 | - * ) |
|
452 | - * </code> |
|
453 | - * |
|
454 | - * Parameters with default values have an additional array index of |
|
455 | - * 'default' with the value of the default as a string. |
|
456 | - * |
|
457 | - * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
458 | - * class. |
|
459 | - * |
|
460 | - * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9}} |
|
461 | - * |
|
462 | - * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
463 | - * @param int $stackPtr The position in the stack of the |
|
464 | - * function token to acquire the |
|
465 | - * parameters for. |
|
466 | - * |
|
467 | - * @return array|false |
|
468 | - * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of |
|
469 | - * type T_FUNCTION or T_CLOSURE. |
|
470 | - */ |
|
471 | - public static function getMethodParameters(File $phpcsFile, $stackPtr) |
|
472 | - { |
|
473 | - if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { |
|
474 | - return $phpcsFile->getMethodParameters($stackPtr); |
|
475 | - } |
|
476 | - |
|
477 | - $tokens = $phpcsFile->getTokens(); |
|
478 | - |
|
479 | - // Check for the existence of the token. |
|
480 | - if (isset($tokens[$stackPtr]) === false) { |
|
481 | - return false; |
|
482 | - } |
|
483 | - |
|
484 | - if ($tokens[$stackPtr]['code'] !== \T_FUNCTION |
|
485 | - && $tokens[$stackPtr]['code'] !== \T_CLOSURE |
|
486 | - ) { |
|
487 | - throw new PHPCS_Exception('$stackPtr must be of type T_FUNCTION or T_CLOSURE'); |
|
488 | - } |
|
489 | - |
|
490 | - $opener = $tokens[$stackPtr]['parenthesis_opener']; |
|
491 | - $closer = $tokens[$stackPtr]['parenthesis_closer']; |
|
492 | - |
|
493 | - $vars = array(); |
|
494 | - $currVar = null; |
|
495 | - $paramStart = ($opener + 1); |
|
496 | - $defaultStart = null; |
|
497 | - $paramCount = 0; |
|
498 | - $passByReference = false; |
|
499 | - $variableLength = false; |
|
500 | - $typeHint = ''; |
|
501 | - $typeHintToken = false; |
|
502 | - $nullableType = false; |
|
503 | - |
|
504 | - for ($i = $paramStart; $i <= $closer; $i++) { |
|
505 | - // Check to see if this token has a parenthesis or bracket opener. If it does |
|
506 | - // it's likely to be an array which might have arguments in it. This |
|
507 | - // could cause problems in our parsing below, so lets just skip to the |
|
508 | - // end of it. |
|
509 | - if (isset($tokens[$i]['parenthesis_opener']) === true) { |
|
510 | - // Don't do this if it's the close parenthesis for the method. |
|
511 | - if ($i !== $tokens[$i]['parenthesis_closer']) { |
|
512 | - $i = ($tokens[$i]['parenthesis_closer'] + 1); |
|
513 | - } |
|
514 | - } |
|
515 | - |
|
516 | - if (isset($tokens[$i]['bracket_opener']) === true) { |
|
517 | - // Don't do this if it's the close parenthesis for the method. |
|
518 | - if ($i !== $tokens[$i]['bracket_closer']) { |
|
519 | - $i = ($tokens[$i]['bracket_closer'] + 1); |
|
520 | - } |
|
521 | - } |
|
522 | - |
|
523 | - switch ($tokens[$i]['type']) { |
|
524 | - case 'T_BITWISE_AND': |
|
525 | - if ($defaultStart === null) { |
|
526 | - $passByReference = true; |
|
527 | - } |
|
528 | - break; |
|
529 | - case 'T_VARIABLE': |
|
530 | - $currVar = $i; |
|
531 | - break; |
|
532 | - case 'T_ELLIPSIS': |
|
533 | - $variableLength = true; |
|
534 | - break; |
|
535 | - case 'T_ARRAY_HINT': // Pre-PHPCS 3.3.0. |
|
536 | - case 'T_CALLABLE': |
|
537 | - if ($typeHintToken === false) { |
|
538 | - $typeHintToken = $i; |
|
539 | - } |
|
540 | - |
|
541 | - $typeHint .= $tokens[$i]['content']; |
|
542 | - break; |
|
543 | - case 'T_SELF': |
|
544 | - case 'T_PARENT': |
|
545 | - case 'T_STATIC': |
|
546 | - // Self and parent are valid, static invalid, but was probably intended as type hint. |
|
547 | - if (isset($defaultStart) === false) { |
|
548 | - if ($typeHintToken === false) { |
|
549 | - $typeHintToken = $i; |
|
550 | - } |
|
551 | - |
|
552 | - $typeHint .= $tokens[$i]['content']; |
|
553 | - } |
|
554 | - break; |
|
555 | - case 'T_STRING': |
|
556 | - // This is a string, so it may be a type hint, but it could |
|
557 | - // also be a constant used as a default value. |
|
558 | - $prevComma = false; |
|
559 | - for ($t = $i; $t >= $opener; $t--) { |
|
560 | - if ($tokens[$t]['code'] === \T_COMMA) { |
|
561 | - $prevComma = $t; |
|
562 | - break; |
|
563 | - } |
|
564 | - } |
|
565 | - |
|
566 | - if ($prevComma !== false) { |
|
567 | - $nextEquals = false; |
|
568 | - for ($t = $prevComma; $t < $i; $t++) { |
|
569 | - if ($tokens[$t]['code'] === \T_EQUAL) { |
|
570 | - $nextEquals = $t; |
|
571 | - break; |
|
572 | - } |
|
573 | - } |
|
574 | - |
|
575 | - if ($nextEquals !== false) { |
|
576 | - break; |
|
577 | - } |
|
578 | - } |
|
579 | - |
|
580 | - if ($defaultStart === null) { |
|
581 | - if ($typeHintToken === false) { |
|
582 | - $typeHintToken = $i; |
|
583 | - } |
|
584 | - |
|
585 | - $typeHint .= $tokens[$i]['content']; |
|
586 | - } |
|
587 | - break; |
|
588 | - case 'T_NS_SEPARATOR': |
|
589 | - // Part of a type hint or default value. |
|
590 | - if ($defaultStart === null) { |
|
591 | - if ($typeHintToken === false) { |
|
592 | - $typeHintToken = $i; |
|
593 | - } |
|
594 | - |
|
595 | - $typeHint .= $tokens[$i]['content']; |
|
596 | - } |
|
597 | - break; |
|
598 | - case 'T_NULLABLE': |
|
599 | - case 'T_INLINE_THEN': // Pre-PHPCS 2.8.0. |
|
600 | - if ($defaultStart === null) { |
|
601 | - $nullableType = true; |
|
602 | - $typeHint .= $tokens[$i]['content']; |
|
603 | - } |
|
604 | - break; |
|
605 | - case 'T_CLOSE_PARENTHESIS': |
|
606 | - case 'T_COMMA': |
|
607 | - // If it's null, then there must be no parameters for this |
|
608 | - // method. |
|
609 | - if ($currVar === null) { |
|
610 | - break; |
|
611 | - } |
|
612 | - |
|
613 | - $vars[$paramCount] = array(); |
|
614 | - $vars[$paramCount]['token'] = $currVar; |
|
615 | - $vars[$paramCount]['name'] = $tokens[$currVar]['content']; |
|
616 | - $vars[$paramCount]['content'] = trim($phpcsFile->getTokensAsString($paramStart, ($i - $paramStart))); |
|
617 | - |
|
618 | - if ($defaultStart !== null) { |
|
619 | - $vars[$paramCount]['default'] = trim( |
|
620 | - $phpcsFile->getTokensAsString( |
|
621 | - $defaultStart, |
|
622 | - ($i - $defaultStart) |
|
623 | - ) |
|
624 | - ); |
|
625 | - } |
|
626 | - |
|
627 | - $vars[$paramCount]['pass_by_reference'] = $passByReference; |
|
628 | - $vars[$paramCount]['variable_length'] = $variableLength; |
|
629 | - $vars[$paramCount]['type_hint'] = $typeHint; |
|
630 | - $vars[$paramCount]['type_hint_token'] = $typeHintToken; |
|
631 | - $vars[$paramCount]['nullable_type'] = $nullableType; |
|
632 | - |
|
633 | - // Reset the vars, as we are about to process the next parameter. |
|
634 | - $defaultStart = null; |
|
635 | - $paramStart = ($i + 1); |
|
636 | - $passByReference = false; |
|
637 | - $variableLength = false; |
|
638 | - $typeHint = ''; |
|
639 | - $typeHintToken = false; |
|
640 | - $nullableType = false; |
|
641 | - |
|
642 | - $paramCount++; |
|
643 | - break; |
|
644 | - case 'T_EQUAL': |
|
645 | - $defaultStart = ($i + 1); |
|
646 | - break; |
|
647 | - }//end switch |
|
648 | - }//end for |
|
649 | - |
|
650 | - return $vars; |
|
651 | - } |
|
33 | + /** |
|
34 | + * Get the PHPCS version number. |
|
35 | + * |
|
36 | + * @return string |
|
37 | + */ |
|
38 | + public static function getVersion() |
|
39 | + { |
|
40 | + if (\defined('\PHP_CodeSniffer\Config::VERSION')) { |
|
41 | + // PHPCS 3.x. |
|
42 | + return \PHP_CodeSniffer\Config::VERSION; |
|
43 | + } else { |
|
44 | + // PHPCS 2.x. |
|
45 | + return \PHP_CodeSniffer::VERSION; |
|
46 | + } |
|
47 | + } |
|
48 | + |
|
49 | + |
|
50 | + /** |
|
51 | + * Pass config data to PHPCS. |
|
52 | + * |
|
53 | + * PHPCS cross-version compatibility helper. |
|
54 | + * |
|
55 | + * @param string $key The name of the config value. |
|
56 | + * @param string|null $value The value to set. If null, the config entry |
|
57 | + * is deleted, reverting it to the default value. |
|
58 | + * @param boolean $temp Set this config data temporarily for this script run. |
|
59 | + * This will not write the config data to the config file. |
|
60 | + * |
|
61 | + * @return void |
|
62 | + */ |
|
63 | + public static function setConfigData($key, $value, $temp = false) |
|
64 | + { |
|
65 | + if (method_exists('\PHP_CodeSniffer\Config', 'setConfigData')) { |
|
66 | + // PHPCS 3.x. |
|
67 | + \PHP_CodeSniffer\Config::setConfigData($key, $value, $temp); |
|
68 | + } else { |
|
69 | + // PHPCS 2.x. |
|
70 | + \PHP_CodeSniffer::setConfigData($key, $value, $temp); |
|
71 | + } |
|
72 | + } |
|
73 | + |
|
74 | + |
|
75 | + /** |
|
76 | + * Get the value of a single PHPCS config key. |
|
77 | + * |
|
78 | + * @param string $key The name of the config value. |
|
79 | + * |
|
80 | + * @return string|null |
|
81 | + */ |
|
82 | + public static function getConfigData($key) |
|
83 | + { |
|
84 | + if (method_exists('\PHP_CodeSniffer\Config', 'getConfigData')) { |
|
85 | + // PHPCS 3.x. |
|
86 | + return \PHP_CodeSniffer\Config::getConfigData($key); |
|
87 | + } else { |
|
88 | + // PHPCS 2.x. |
|
89 | + return \PHP_CodeSniffer::getConfigData($key); |
|
90 | + } |
|
91 | + } |
|
92 | + |
|
93 | + |
|
94 | + /** |
|
95 | + * Get the value of a single PHPCS config key. |
|
96 | + * |
|
97 | + * This config key can be set in the `CodeSniffer.conf` file, on the |
|
98 | + * command-line or in a ruleset. |
|
99 | + * |
|
100 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
101 | + * @param string $key The name of the config value. |
|
102 | + * |
|
103 | + * @return string|null |
|
104 | + */ |
|
105 | + public static function getCommandLineData(File $phpcsFile, $key) |
|
106 | + { |
|
107 | + if (class_exists('\PHP_CodeSniffer\Config')) { |
|
108 | + // PHPCS 3.x. |
|
109 | + $config = $phpcsFile->config; |
|
110 | + if (isset($config->{$key})) { |
|
111 | + return $config->{$key}; |
|
112 | + } |
|
113 | + } else { |
|
114 | + // PHPCS 2.x. |
|
115 | + $config = $phpcsFile->phpcs->cli->getCommandLineValues(); |
|
116 | + if (isset($config[$key])) { |
|
117 | + return $config[$key]; |
|
118 | + } |
|
119 | + } |
|
120 | + |
|
121 | + return null; |
|
122 | + } |
|
123 | + |
|
124 | + |
|
125 | + /** |
|
126 | + * Returns the position of the first non-whitespace token in a statement. |
|
127 | + * |
|
128 | + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
129 | + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1. |
|
130 | + * |
|
131 | + * Once the minimum supported PHPCS version for this standard goes beyond |
|
132 | + * that, this method can be removed and calls to it replaced with |
|
133 | + * `$phpcsFile->findStartOfStatement($start, $ignore)` calls. |
|
134 | + * |
|
135 | + * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e}} |
|
136 | + * |
|
137 | + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
138 | + * @param int $start The position to start searching from in the token stack. |
|
139 | + * @param int|array $ignore Token types that should not be considered stop points. |
|
140 | + * |
|
141 | + * @return int |
|
142 | + */ |
|
143 | + public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null) |
|
144 | + { |
|
145 | + if (version_compare(self::getVersion(), '2.7.1', '>=') === true) { |
|
146 | + return $phpcsFile->findStartOfStatement($start, $ignore); |
|
147 | + } |
|
148 | + |
|
149 | + $tokens = $phpcsFile->getTokens(); |
|
150 | + $endTokens = Tokens::$blockOpeners; |
|
151 | + |
|
152 | + $endTokens[\T_COLON] = true; |
|
153 | + $endTokens[\T_COMMA] = true; |
|
154 | + $endTokens[\T_DOUBLE_ARROW] = true; |
|
155 | + $endTokens[\T_SEMICOLON] = true; |
|
156 | + $endTokens[\T_OPEN_TAG] = true; |
|
157 | + $endTokens[\T_CLOSE_TAG] = true; |
|
158 | + $endTokens[\T_OPEN_SHORT_ARRAY] = true; |
|
159 | + |
|
160 | + if ($ignore !== null) { |
|
161 | + $ignore = (array) $ignore; |
|
162 | + foreach ($ignore as $code) { |
|
163 | + if (isset($endTokens[$code]) === true) { |
|
164 | + unset($endTokens[$code]); |
|
165 | + } |
|
166 | + } |
|
167 | + } |
|
168 | + |
|
169 | + $lastNotEmpty = $start; |
|
170 | + |
|
171 | + for ($i = $start; $i >= 0; $i--) { |
|
172 | + if (isset($endTokens[$tokens[$i]['code']]) === true) { |
|
173 | + // Found the end of the previous statement. |
|
174 | + return $lastNotEmpty; |
|
175 | + } |
|
176 | + |
|
177 | + if (isset($tokens[$i]['scope_opener']) === true |
|
178 | + && $i === $tokens[$i]['scope_closer'] |
|
179 | + ) { |
|
180 | + // Found the end of the previous scope block. |
|
181 | + return $lastNotEmpty; |
|
182 | + } |
|
183 | + |
|
184 | + // Skip nested statements. |
|
185 | + if (isset($tokens[$i]['bracket_opener']) === true |
|
186 | + && $i === $tokens[$i]['bracket_closer'] |
|
187 | + ) { |
|
188 | + $i = $tokens[$i]['bracket_opener']; |
|
189 | + } elseif (isset($tokens[$i]['parenthesis_opener']) === true |
|
190 | + && $i === $tokens[$i]['parenthesis_closer'] |
|
191 | + ) { |
|
192 | + $i = $tokens[$i]['parenthesis_opener']; |
|
193 | + } |
|
194 | + |
|
195 | + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { |
|
196 | + $lastNotEmpty = $i; |
|
197 | + } |
|
198 | + }//end for |
|
199 | + |
|
200 | + return 0; |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * Returns the position of the last non-whitespace token in a statement. |
|
206 | + * |
|
207 | + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
208 | + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0. |
|
209 | + * |
|
210 | + * Once the minimum supported PHPCS version for this standard goes beyond |
|
211 | + * that, this method can be removed and calls to it replaced with |
|
212 | + * `$phpcsFile->findEndOfStatement($start, $ignore)` calls. |
|
213 | + * |
|
214 | + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823}} |
|
215 | + * |
|
216 | + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
217 | + * @param int $start The position to start searching from in the token stack. |
|
218 | + * @param int|array $ignore Token types that should not be considered stop points. |
|
219 | + * |
|
220 | + * @return int |
|
221 | + */ |
|
222 | + public static function findEndOfStatement(File $phpcsFile, $start, $ignore = null) |
|
223 | + { |
|
224 | + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { |
|
225 | + return $phpcsFile->findEndOfStatement($start, $ignore); |
|
226 | + } |
|
227 | + |
|
228 | + $tokens = $phpcsFile->getTokens(); |
|
229 | + $endTokens = array( |
|
230 | + \T_COLON => true, |
|
231 | + \T_COMMA => true, |
|
232 | + \T_DOUBLE_ARROW => true, |
|
233 | + \T_SEMICOLON => true, |
|
234 | + \T_CLOSE_PARENTHESIS => true, |
|
235 | + \T_CLOSE_SQUARE_BRACKET => true, |
|
236 | + \T_CLOSE_CURLY_BRACKET => true, |
|
237 | + \T_CLOSE_SHORT_ARRAY => true, |
|
238 | + \T_OPEN_TAG => true, |
|
239 | + \T_CLOSE_TAG => true, |
|
240 | + ); |
|
241 | + |
|
242 | + if ($ignore !== null) { |
|
243 | + $ignore = (array) $ignore; |
|
244 | + foreach ($ignore as $code) { |
|
245 | + if (isset($endTokens[$code]) === true) { |
|
246 | + unset($endTokens[$code]); |
|
247 | + } |
|
248 | + } |
|
249 | + } |
|
250 | + |
|
251 | + $lastNotEmpty = $start; |
|
252 | + |
|
253 | + for ($i = $start; $i < $phpcsFile->numTokens; $i++) { |
|
254 | + if ($i !== $start && isset($endTokens[$tokens[$i]['code']]) === true) { |
|
255 | + // Found the end of the statement. |
|
256 | + if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS |
|
257 | + || $tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET |
|
258 | + || $tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET |
|
259 | + || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY |
|
260 | + || $tokens[$i]['code'] === \T_OPEN_TAG |
|
261 | + || $tokens[$i]['code'] === \T_CLOSE_TAG |
|
262 | + ) { |
|
263 | + return $lastNotEmpty; |
|
264 | + } |
|
265 | + |
|
266 | + return $i; |
|
267 | + } |
|
268 | + |
|
269 | + // Skip nested statements. |
|
270 | + if (isset($tokens[$i]['scope_closer']) === true |
|
271 | + && ($i === $tokens[$i]['scope_opener'] |
|
272 | + || $i === $tokens[$i]['scope_condition']) |
|
273 | + ) { |
|
274 | + if ($i === $start && isset(Tokens::$scopeOpeners[$tokens[$i]['code']]) === true) { |
|
275 | + return $tokens[$i]['scope_closer']; |
|
276 | + } |
|
277 | + |
|
278 | + $i = $tokens[$i]['scope_closer']; |
|
279 | + } elseif (isset($tokens[$i]['bracket_closer']) === true |
|
280 | + && $i === $tokens[$i]['bracket_opener'] |
|
281 | + ) { |
|
282 | + $i = $tokens[$i]['bracket_closer']; |
|
283 | + } elseif (isset($tokens[$i]['parenthesis_closer']) === true |
|
284 | + && $i === $tokens[$i]['parenthesis_opener'] |
|
285 | + ) { |
|
286 | + $i = $tokens[$i]['parenthesis_closer']; |
|
287 | + } |
|
288 | + |
|
289 | + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { |
|
290 | + $lastNotEmpty = $i; |
|
291 | + } |
|
292 | + }//end for |
|
293 | + |
|
294 | + return ($phpcsFile->numTokens - 1); |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * Returns the name of the class that the specified class extends |
|
300 | + * (works for classes, anonymous classes and interfaces). |
|
301 | + * |
|
302 | + * Returns FALSE on error or if there is no extended class name. |
|
303 | + * |
|
304 | + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
305 | + * class, but with some improvements which have been introduced in |
|
306 | + * PHPCS 2.8.0. |
|
307 | + * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}. |
|
308 | + * |
|
309 | + * Once the minimum supported PHPCS version for this standard goes beyond |
|
310 | + * that, this method can be removed and calls to it replaced with |
|
311 | + * `$phpcsFile->findExtendedClassName($stackPtr)` calls. |
|
312 | + * |
|
313 | + * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6}} |
|
314 | + * |
|
315 | + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
316 | + * @param int $stackPtr The position of the class token in the stack. |
|
317 | + * |
|
318 | + * @return string|false |
|
319 | + */ |
|
320 | + public static function findExtendedClassName(File $phpcsFile, $stackPtr) |
|
321 | + { |
|
322 | + if (version_compare(self::getVersion(), '3.1.0', '>=') === true) { |
|
323 | + return $phpcsFile->findExtendedClassName($stackPtr); |
|
324 | + } |
|
325 | + |
|
326 | + $tokens = $phpcsFile->getTokens(); |
|
327 | + |
|
328 | + // Check for the existence of the token. |
|
329 | + if (isset($tokens[$stackPtr]) === false) { |
|
330 | + return false; |
|
331 | + } |
|
332 | + |
|
333 | + if ($tokens[$stackPtr]['code'] !== \T_CLASS |
|
334 | + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' |
|
335 | + && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' |
|
336 | + ) { |
|
337 | + return false; |
|
338 | + } |
|
339 | + |
|
340 | + if (isset($tokens[$stackPtr]['scope_closer']) === false) { |
|
341 | + return false; |
|
342 | + } |
|
343 | + |
|
344 | + $classCloserIndex = $tokens[$stackPtr]['scope_closer']; |
|
345 | + $extendsIndex = $phpcsFile->findNext(\T_EXTENDS, $stackPtr, $classCloserIndex); |
|
346 | + if ($extendsIndex === false) { |
|
347 | + return false; |
|
348 | + } |
|
349 | + |
|
350 | + $find = array( |
|
351 | + \T_NS_SEPARATOR, |
|
352 | + \T_STRING, |
|
353 | + \T_WHITESPACE, |
|
354 | + ); |
|
355 | + |
|
356 | + $end = $phpcsFile->findNext($find, ($extendsIndex + 1), $classCloserIndex, true); |
|
357 | + $name = $phpcsFile->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); |
|
358 | + $name = trim($name); |
|
359 | + |
|
360 | + if ($name === '') { |
|
361 | + return false; |
|
362 | + } |
|
363 | + |
|
364 | + return $name; |
|
365 | + } |
|
366 | + |
|
367 | + |
|
368 | + /** |
|
369 | + * Returns the name(s) of the interface(s) that the specified class implements. |
|
370 | + * |
|
371 | + * Returns FALSE on error or if there are no implemented interface names. |
|
372 | + * |
|
373 | + * {@internal Duplicate of same method as introduced in PHPCS 2.7. |
|
374 | + * This method also includes an improvement we use which was only introduced |
|
375 | + * in PHPCS 2.8.0, so only defer to upstream for higher versions. |
|
376 | + * Once the minimum supported PHPCS version for this sniff library goes beyond |
|
377 | + * that, this method can be removed and calls to it replaced with |
|
378 | + * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.}} |
|
379 | + * |
|
380 | + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. |
|
381 | + * @param int $stackPtr The position of the class token. |
|
382 | + * |
|
383 | + * @return array|false |
|
384 | + */ |
|
385 | + public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr) |
|
386 | + { |
|
387 | + if (version_compare(self::getVersion(), '2.7.1', '>') === true) { |
|
388 | + return $phpcsFile->findImplementedInterfaceNames($stackPtr); |
|
389 | + } |
|
390 | + |
|
391 | + $tokens = $phpcsFile->getTokens(); |
|
392 | + |
|
393 | + // Check for the existence of the token. |
|
394 | + if (isset($tokens[$stackPtr]) === false) { |
|
395 | + return false; |
|
396 | + } |
|
397 | + |
|
398 | + if ($tokens[$stackPtr]['code'] !== \T_CLASS |
|
399 | + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' |
|
400 | + ) { |
|
401 | + return false; |
|
402 | + } |
|
403 | + |
|
404 | + if (isset($tokens[$stackPtr]['scope_closer']) === false) { |
|
405 | + return false; |
|
406 | + } |
|
407 | + |
|
408 | + $classOpenerIndex = $tokens[$stackPtr]['scope_opener']; |
|
409 | + $implementsIndex = $phpcsFile->findNext(\T_IMPLEMENTS, $stackPtr, $classOpenerIndex); |
|
410 | + if ($implementsIndex === false) { |
|
411 | + return false; |
|
412 | + } |
|
413 | + |
|
414 | + $find = array( |
|
415 | + \T_NS_SEPARATOR, |
|
416 | + \T_STRING, |
|
417 | + \T_WHITESPACE, |
|
418 | + \T_COMMA, |
|
419 | + ); |
|
420 | + |
|
421 | + $end = $phpcsFile->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); |
|
422 | + $name = $phpcsFile->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); |
|
423 | + $name = trim($name); |
|
424 | + |
|
425 | + if ($name === '') { |
|
426 | + return false; |
|
427 | + } else { |
|
428 | + $names = explode(',', $name); |
|
429 | + $names = array_map('trim', $names); |
|
430 | + return $names; |
|
431 | + } |
|
432 | + } |
|
433 | + |
|
434 | + |
|
435 | + /** |
|
436 | + * Returns the method parameters for the specified function token. |
|
437 | + * |
|
438 | + * Each parameter is in the following format: |
|
439 | + * |
|
440 | + * <code> |
|
441 | + * 0 => array( |
|
442 | + * 'name' => '$var', // The variable name. |
|
443 | + * 'token' => integer, // The stack pointer to the variable name. |
|
444 | + * 'content' => string, // The full content of the variable definition. |
|
445 | + * 'pass_by_reference' => boolean, // Is the variable passed by reference? |
|
446 | + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? |
|
447 | + * 'type_hint' => string, // The type hint for the variable. |
|
448 | + * 'type_hint_token' => integer, // The stack pointer to the type hint |
|
449 | + * // or false if there is no type hint. |
|
450 | + * 'nullable_type' => boolean, // Is the variable using a nullable type? |
|
451 | + * ) |
|
452 | + * </code> |
|
453 | + * |
|
454 | + * Parameters with default values have an additional array index of |
|
455 | + * 'default' with the value of the default as a string. |
|
456 | + * |
|
457 | + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` |
|
458 | + * class. |
|
459 | + * |
|
460 | + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9}} |
|
461 | + * |
|
462 | + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. |
|
463 | + * @param int $stackPtr The position in the stack of the |
|
464 | + * function token to acquire the |
|
465 | + * parameters for. |
|
466 | + * |
|
467 | + * @return array|false |
|
468 | + * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of |
|
469 | + * type T_FUNCTION or T_CLOSURE. |
|
470 | + */ |
|
471 | + public static function getMethodParameters(File $phpcsFile, $stackPtr) |
|
472 | + { |
|
473 | + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { |
|
474 | + return $phpcsFile->getMethodParameters($stackPtr); |
|
475 | + } |
|
476 | + |
|
477 | + $tokens = $phpcsFile->getTokens(); |
|
478 | + |
|
479 | + // Check for the existence of the token. |
|
480 | + if (isset($tokens[$stackPtr]) === false) { |
|
481 | + return false; |
|
482 | + } |
|
483 | + |
|
484 | + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION |
|
485 | + && $tokens[$stackPtr]['code'] !== \T_CLOSURE |
|
486 | + ) { |
|
487 | + throw new PHPCS_Exception('$stackPtr must be of type T_FUNCTION or T_CLOSURE'); |
|
488 | + } |
|
489 | + |
|
490 | + $opener = $tokens[$stackPtr]['parenthesis_opener']; |
|
491 | + $closer = $tokens[$stackPtr]['parenthesis_closer']; |
|
492 | + |
|
493 | + $vars = array(); |
|
494 | + $currVar = null; |
|
495 | + $paramStart = ($opener + 1); |
|
496 | + $defaultStart = null; |
|
497 | + $paramCount = 0; |
|
498 | + $passByReference = false; |
|
499 | + $variableLength = false; |
|
500 | + $typeHint = ''; |
|
501 | + $typeHintToken = false; |
|
502 | + $nullableType = false; |
|
503 | + |
|
504 | + for ($i = $paramStart; $i <= $closer; $i++) { |
|
505 | + // Check to see if this token has a parenthesis or bracket opener. If it does |
|
506 | + // it's likely to be an array which might have arguments in it. This |
|
507 | + // could cause problems in our parsing below, so lets just skip to the |
|
508 | + // end of it. |
|
509 | + if (isset($tokens[$i]['parenthesis_opener']) === true) { |
|
510 | + // Don't do this if it's the close parenthesis for the method. |
|
511 | + if ($i !== $tokens[$i]['parenthesis_closer']) { |
|
512 | + $i = ($tokens[$i]['parenthesis_closer'] + 1); |
|
513 | + } |
|
514 | + } |
|
515 | + |
|
516 | + if (isset($tokens[$i]['bracket_opener']) === true) { |
|
517 | + // Don't do this if it's the close parenthesis for the method. |
|
518 | + if ($i !== $tokens[$i]['bracket_closer']) { |
|
519 | + $i = ($tokens[$i]['bracket_closer'] + 1); |
|
520 | + } |
|
521 | + } |
|
522 | + |
|
523 | + switch ($tokens[$i]['type']) { |
|
524 | + case 'T_BITWISE_AND': |
|
525 | + if ($defaultStart === null) { |
|
526 | + $passByReference = true; |
|
527 | + } |
|
528 | + break; |
|
529 | + case 'T_VARIABLE': |
|
530 | + $currVar = $i; |
|
531 | + break; |
|
532 | + case 'T_ELLIPSIS': |
|
533 | + $variableLength = true; |
|
534 | + break; |
|
535 | + case 'T_ARRAY_HINT': // Pre-PHPCS 3.3.0. |
|
536 | + case 'T_CALLABLE': |
|
537 | + if ($typeHintToken === false) { |
|
538 | + $typeHintToken = $i; |
|
539 | + } |
|
540 | + |
|
541 | + $typeHint .= $tokens[$i]['content']; |
|
542 | + break; |
|
543 | + case 'T_SELF': |
|
544 | + case 'T_PARENT': |
|
545 | + case 'T_STATIC': |
|
546 | + // Self and parent are valid, static invalid, but was probably intended as type hint. |
|
547 | + if (isset($defaultStart) === false) { |
|
548 | + if ($typeHintToken === false) { |
|
549 | + $typeHintToken = $i; |
|
550 | + } |
|
551 | + |
|
552 | + $typeHint .= $tokens[$i]['content']; |
|
553 | + } |
|
554 | + break; |
|
555 | + case 'T_STRING': |
|
556 | + // This is a string, so it may be a type hint, but it could |
|
557 | + // also be a constant used as a default value. |
|
558 | + $prevComma = false; |
|
559 | + for ($t = $i; $t >= $opener; $t--) { |
|
560 | + if ($tokens[$t]['code'] === \T_COMMA) { |
|
561 | + $prevComma = $t; |
|
562 | + break; |
|
563 | + } |
|
564 | + } |
|
565 | + |
|
566 | + if ($prevComma !== false) { |
|
567 | + $nextEquals = false; |
|
568 | + for ($t = $prevComma; $t < $i; $t++) { |
|
569 | + if ($tokens[$t]['code'] === \T_EQUAL) { |
|
570 | + $nextEquals = $t; |
|
571 | + break; |
|
572 | + } |
|
573 | + } |
|
574 | + |
|
575 | + if ($nextEquals !== false) { |
|
576 | + break; |
|
577 | + } |
|
578 | + } |
|
579 | + |
|
580 | + if ($defaultStart === null) { |
|
581 | + if ($typeHintToken === false) { |
|
582 | + $typeHintToken = $i; |
|
583 | + } |
|
584 | + |
|
585 | + $typeHint .= $tokens[$i]['content']; |
|
586 | + } |
|
587 | + break; |
|
588 | + case 'T_NS_SEPARATOR': |
|
589 | + // Part of a type hint or default value. |
|
590 | + if ($defaultStart === null) { |
|
591 | + if ($typeHintToken === false) { |
|
592 | + $typeHintToken = $i; |
|
593 | + } |
|
594 | + |
|
595 | + $typeHint .= $tokens[$i]['content']; |
|
596 | + } |
|
597 | + break; |
|
598 | + case 'T_NULLABLE': |
|
599 | + case 'T_INLINE_THEN': // Pre-PHPCS 2.8.0. |
|
600 | + if ($defaultStart === null) { |
|
601 | + $nullableType = true; |
|
602 | + $typeHint .= $tokens[$i]['content']; |
|
603 | + } |
|
604 | + break; |
|
605 | + case 'T_CLOSE_PARENTHESIS': |
|
606 | + case 'T_COMMA': |
|
607 | + // If it's null, then there must be no parameters for this |
|
608 | + // method. |
|
609 | + if ($currVar === null) { |
|
610 | + break; |
|
611 | + } |
|
612 | + |
|
613 | + $vars[$paramCount] = array(); |
|
614 | + $vars[$paramCount]['token'] = $currVar; |
|
615 | + $vars[$paramCount]['name'] = $tokens[$currVar]['content']; |
|
616 | + $vars[$paramCount]['content'] = trim($phpcsFile->getTokensAsString($paramStart, ($i - $paramStart))); |
|
617 | + |
|
618 | + if ($defaultStart !== null) { |
|
619 | + $vars[$paramCount]['default'] = trim( |
|
620 | + $phpcsFile->getTokensAsString( |
|
621 | + $defaultStart, |
|
622 | + ($i - $defaultStart) |
|
623 | + ) |
|
624 | + ); |
|
625 | + } |
|
626 | + |
|
627 | + $vars[$paramCount]['pass_by_reference'] = $passByReference; |
|
628 | + $vars[$paramCount]['variable_length'] = $variableLength; |
|
629 | + $vars[$paramCount]['type_hint'] = $typeHint; |
|
630 | + $vars[$paramCount]['type_hint_token'] = $typeHintToken; |
|
631 | + $vars[$paramCount]['nullable_type'] = $nullableType; |
|
632 | + |
|
633 | + // Reset the vars, as we are about to process the next parameter. |
|
634 | + $defaultStart = null; |
|
635 | + $paramStart = ($i + 1); |
|
636 | + $passByReference = false; |
|
637 | + $variableLength = false; |
|
638 | + $typeHint = ''; |
|
639 | + $typeHintToken = false; |
|
640 | + $nullableType = false; |
|
641 | + |
|
642 | + $paramCount++; |
|
643 | + break; |
|
644 | + case 'T_EQUAL': |
|
645 | + $defaultStart = ($i + 1); |
|
646 | + break; |
|
647 | + }//end switch |
|
648 | + }//end for |
|
649 | + |
|
650 | + return $vars; |
|
651 | + } |
|
652 | 652 | } |
@@ -24,44 +24,44 @@ |
||
24 | 24 | * manner.}} |
25 | 25 | */ |
26 | 26 | if (defined('PHPCOMPATIBILITY_PHPCS_ALIASES_SET') === false) { |
27 | - if (interface_exists('\PHP_CodeSniffer_Sniff') === false) { |
|
28 | - class_alias('PHP_CodeSniffer\Sniffs\Sniff', '\PHP_CodeSniffer_Sniff'); |
|
29 | - } |
|
30 | - if (class_exists('\PHP_CodeSniffer_File') === false) { |
|
31 | - class_alias('PHP_CodeSniffer\Files\File', '\PHP_CodeSniffer_File'); |
|
32 | - } |
|
33 | - if (class_exists('\PHP_CodeSniffer_Tokens') === false) { |
|
34 | - class_alias('PHP_CodeSniffer\Util\Tokens', '\PHP_CodeSniffer_Tokens'); |
|
35 | - } |
|
36 | - if (class_exists('\PHP_CodeSniffer_Exception') === false) { |
|
37 | - class_alias('PHP_CodeSniffer\Exceptions\RuntimeException', '\PHP_CodeSniffer_Exception'); |
|
38 | - } |
|
39 | - if (class_exists('\PHP_CodeSniffer_Standards_AbstractScopeSniff') === false) { |
|
40 | - class_alias('PHP_CodeSniffer\Sniffs\AbstractScopeSniff', '\PHP_CodeSniffer_Standards_AbstractScopeSniff'); |
|
41 | - } |
|
42 | - if (class_exists('\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff') === false) { |
|
43 | - class_alias('PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', '\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff'); |
|
44 | - } |
|
27 | + if (interface_exists('\PHP_CodeSniffer_Sniff') === false) { |
|
28 | + class_alias('PHP_CodeSniffer\Sniffs\Sniff', '\PHP_CodeSniffer_Sniff'); |
|
29 | + } |
|
30 | + if (class_exists('\PHP_CodeSniffer_File') === false) { |
|
31 | + class_alias('PHP_CodeSniffer\Files\File', '\PHP_CodeSniffer_File'); |
|
32 | + } |
|
33 | + if (class_exists('\PHP_CodeSniffer_Tokens') === false) { |
|
34 | + class_alias('PHP_CodeSniffer\Util\Tokens', '\PHP_CodeSniffer_Tokens'); |
|
35 | + } |
|
36 | + if (class_exists('\PHP_CodeSniffer_Exception') === false) { |
|
37 | + class_alias('PHP_CodeSniffer\Exceptions\RuntimeException', '\PHP_CodeSniffer_Exception'); |
|
38 | + } |
|
39 | + if (class_exists('\PHP_CodeSniffer_Standards_AbstractScopeSniff') === false) { |
|
40 | + class_alias('PHP_CodeSniffer\Sniffs\AbstractScopeSniff', '\PHP_CodeSniffer_Standards_AbstractScopeSniff'); |
|
41 | + } |
|
42 | + if (class_exists('\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff') === false) { |
|
43 | + class_alias('PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', '\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff'); |
|
44 | + } |
|
45 | 45 | |
46 | - define('PHPCOMPATIBILITY_PHPCS_ALIASES_SET', true); |
|
46 | + define('PHPCOMPATIBILITY_PHPCS_ALIASES_SET', true); |
|
47 | 47 | |
48 | - /* |
|
48 | + /* |
|
49 | 49 | * Register an autoloader. |
50 | 50 | * |
51 | 51 | * {@internal When `installed_paths` is set via the ruleset, this autoloader |
52 | 52 | * is needed to run the sniffs. |
53 | 53 | * Upstream issue: {@link https://github.com/squizlabs/PHP_CodeSniffer/issues/1591} }} |
54 | 54 | */ |
55 | - spl_autoload_register(function ($class) { |
|
56 | - // Only try & load our own classes. |
|
57 | - if (stripos($class, 'PHPCompatibility') !== 0) { |
|
58 | - return; |
|
59 | - } |
|
55 | + spl_autoload_register(function ($class) { |
|
56 | + // Only try & load our own classes. |
|
57 | + if (stripos($class, 'PHPCompatibility') !== 0) { |
|
58 | + return; |
|
59 | + } |
|
60 | 60 | |
61 | - $file = realpath(__DIR__) . DIRECTORY_SEPARATOR . strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; |
|
61 | + $file = realpath(__DIR__) . DIRECTORY_SEPARATOR . strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; |
|
62 | 62 | |
63 | - if (file_exists($file)) { |
|
64 | - include_once $file; |
|
65 | - } |
|
66 | - }); |
|
63 | + if (file_exists($file)) { |
|
64 | + include_once $file; |
|
65 | + } |
|
66 | + }); |
|
67 | 67 | } |
@@ -6,16 +6,16 @@ discard block |
||
6 | 6 | */ |
7 | 7 | |
8 | 8 | if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { |
9 | - define('PHP_CODESNIFFER_IN_TESTS', true); |
|
9 | + define('PHP_CODESNIFFER_IN_TESTS', true); |
|
10 | 10 | } |
11 | 11 | |
12 | 12 | // The below two defines are needed for PHPCS 3.x. |
13 | 13 | if (defined('PHP_CODESNIFFER_CBF') === false) { |
14 | - define('PHP_CODESNIFFER_CBF', false); |
|
14 | + define('PHP_CODESNIFFER_CBF', false); |
|
15 | 15 | } |
16 | 16 | |
17 | 17 | if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { |
18 | - define('PHP_CODESNIFFER_VERBOSITY', 0); |
|
18 | + define('PHP_CODESNIFFER_VERBOSITY', 0); |
|
19 | 19 | } |
20 | 20 | |
21 | 21 | $ds = DIRECTORY_SEPARATOR; |
@@ -25,34 +25,34 @@ discard block |
||
25 | 25 | |
26 | 26 | // This may be a Composer install. |
27 | 27 | if ($phpcsDir === false && is_dir(__DIR__ . $ds . 'vendor' . $ds . 'squizlabs' . $ds . 'php_codesniffer')) { |
28 | - $vendorDir = __DIR__ . $ds . 'vendor'; |
|
29 | - $phpcsDir = $vendorDir . $ds . 'squizlabs' . $ds . 'php_codesniffer'; |
|
28 | + $vendorDir = __DIR__ . $ds . 'vendor'; |
|
29 | + $phpcsDir = $vendorDir . $ds . 'squizlabs' . $ds . 'php_codesniffer'; |
|
30 | 30 | } elseif ($phpcsDir !== false) { |
31 | - $phpcsDir = realpath($phpcsDir); |
|
31 | + $phpcsDir = realpath($phpcsDir); |
|
32 | 32 | } |
33 | 33 | |
34 | 34 | // Try and load the PHPCS autoloader. |
35 | 35 | if ($phpcsDir !== false && file_exists($phpcsDir . $ds . 'autoload.php')) { |
36 | - // PHPCS 3.x. |
|
37 | - require_once $phpcsDir . $ds . 'autoload.php'; |
|
36 | + // PHPCS 3.x. |
|
37 | + require_once $phpcsDir . $ds . 'autoload.php'; |
|
38 | 38 | |
39 | - /* |
|
39 | + /* |
|
40 | 40 | * Alias the PHPCS 3.x classes to their PHPCS 2.x equivalent if necessary. |
41 | 41 | * Also provide a custom autoloader for our abstract base classes as the PHPCS native autoloader |
42 | 42 | * has trouble with them in combination with the PHPCompatibility custom unit test suite. |
43 | 43 | */ |
44 | - require_once __DIR__ . $ds . 'PHPCSAliases.php'; |
|
44 | + require_once __DIR__ . $ds . 'PHPCSAliases.php'; |
|
45 | 45 | |
46 | 46 | } elseif ($phpcsDir !== false && file_exists($phpcsDir . $ds . 'CodeSniffer.php')) { |
47 | - // PHPCS 2.x. |
|
48 | - require_once $phpcsDir . $ds . 'CodeSniffer.php'; |
|
47 | + // PHPCS 2.x. |
|
48 | + require_once $phpcsDir . $ds . 'CodeSniffer.php'; |
|
49 | 49 | |
50 | - if (isset($vendorDir) && file_exists($vendorDir . $ds . 'autoload.php')) { |
|
51 | - require_once $vendorDir . $ds . 'autoload.php'; |
|
52 | - } |
|
50 | + if (isset($vendorDir) && file_exists($vendorDir . $ds . 'autoload.php')) { |
|
51 | + require_once $vendorDir . $ds . 'autoload.php'; |
|
52 | + } |
|
53 | 53 | |
54 | 54 | } else { |
55 | - echo 'Uh oh... can\'t find PHPCS. |
|
55 | + echo 'Uh oh... can\'t find PHPCS. |
|
56 | 56 | |
57 | 57 | If you use Composer, please run `composer install --prefer-source`. |
58 | 58 | Otherwise, make sure you set a `PHPCS_DIR` environment variable in your phpunit.xml file |
@@ -62,16 +62,16 @@ discard block |
||
62 | 62 | https://is.gd/PHPCompatibilityContrib |
63 | 63 | '; |
64 | 64 | |
65 | - die(1); |
|
65 | + die(1); |
|
66 | 66 | } |
67 | 67 | |
68 | 68 | |
69 | 69 | // PHPUnit cross version compatibility. |
70 | 70 | if (class_exists('PHPUnit\Runner\Version') |
71 | - && version_compare(PHPUnit\Runner\Version::id(), '6.0', '>=') |
|
72 | - && class_exists('PHPUnit_Framework_TestCase') === false |
|
71 | + && version_compare(PHPUnit\Runner\Version::id(), '6.0', '>=') |
|
72 | + && class_exists('PHPUnit_Framework_TestCase') === false |
|
73 | 73 | ) { |
74 | - class_alias('PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase'); |
|
74 | + class_alias('PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase'); |
|
75 | 75 | } |
76 | 76 | |
77 | 77 | require_once __DIR__ . $ds . 'PHPCompatibility' . $ds . 'Tests' . $ds . 'BaseSniffTest.php'; |
@@ -34,445 +34,445 @@ |
||
34 | 34 | class Plugin implements PluginInterface, EventSubscriberInterface |
35 | 35 | { |
36 | 36 | |
37 | - const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; |
|
38 | - |
|
39 | - const MESSAGE_ERROR_WRONG_MAX_DEPTH = |
|
40 | - 'The value of "%s" (in the composer.json "extra".section) must be an integer larger then %d, %s given.'; |
|
41 | - const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; |
|
42 | - const MESSAGE_NOTHING_TO_INSTALL = 'Nothing to install or update'; |
|
43 | - const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; |
|
44 | - |
|
45 | - const PACKAGE_NAME = 'squizlabs/php_codesniffer'; |
|
46 | - const PACKAGE_TYPE = 'phpcodesniffer-standard'; |
|
47 | - |
|
48 | - const PHPCS_CONFIG_KEY = 'installed_paths'; |
|
49 | - |
|
50 | - /** |
|
51 | - * @var Composer |
|
52 | - */ |
|
53 | - private $composer; |
|
54 | - |
|
55 | - /** |
|
56 | - * @var string |
|
57 | - */ |
|
58 | - private $cwd; |
|
59 | - |
|
60 | - /** |
|
61 | - * @var Filesystem |
|
62 | - */ |
|
63 | - private $filesystem; |
|
64 | - |
|
65 | - /** |
|
66 | - * @var array |
|
67 | - */ |
|
68 | - private $installedPaths; |
|
69 | - |
|
70 | - /** |
|
71 | - * @var IOInterface |
|
72 | - */ |
|
73 | - private $io; |
|
74 | - |
|
75 | - /** |
|
76 | - * @var ProcessExecutor |
|
77 | - */ |
|
78 | - private $processExecutor; |
|
79 | - |
|
80 | - /** |
|
81 | - * Triggers the plugin's main functionality. |
|
82 | - * |
|
83 | - * Makes it possible to run the plugin as a custom command. |
|
84 | - * |
|
85 | - * @param Event $event |
|
86 | - * |
|
87 | - * @throws \InvalidArgumentException |
|
88 | - * @throws \RuntimeException |
|
89 | - * @throws LogicException |
|
90 | - * @throws ProcessFailedException |
|
91 | - * @throws RuntimeException |
|
92 | - */ |
|
93 | - public static function run(Event $event) |
|
94 | - { |
|
95 | - $io = $event->getIO(); |
|
96 | - $composer = $event->getComposer(); |
|
97 | - |
|
98 | - $instance = new static(); |
|
99 | - |
|
100 | - $instance->io = $io; |
|
101 | - $instance->composer = $composer; |
|
102 | - $instance->init(); |
|
103 | - $instance->onDependenciesChangedEvent(); |
|
104 | - } |
|
105 | - |
|
106 | - /** |
|
107 | - * {@inheritDoc} |
|
108 | - * |
|
109 | - * @throws \RuntimeException |
|
110 | - * @throws LogicException |
|
111 | - * @throws ProcessFailedException |
|
112 | - * @throws RuntimeException |
|
113 | - */ |
|
114 | - public function activate(Composer $composer, IOInterface $io) |
|
115 | - { |
|
116 | - $this->composer = $composer; |
|
117 | - $this->io = $io; |
|
118 | - |
|
119 | - $this->init(); |
|
120 | - } |
|
121 | - |
|
122 | - /** |
|
123 | - * Prepares the plugin so it's main functionality can be run. |
|
124 | - * |
|
125 | - * @throws \RuntimeException |
|
126 | - * @throws LogicException |
|
127 | - * @throws ProcessFailedException |
|
128 | - * @throws RuntimeException |
|
129 | - */ |
|
130 | - private function init() |
|
131 | - { |
|
132 | - $this->cwd = getcwd(); |
|
133 | - $this->installedPaths = array(); |
|
134 | - |
|
135 | - $this->processExecutor = new ProcessExecutor($this->io); |
|
136 | - $this->filesystem = new Filesystem($this->processExecutor); |
|
137 | - } |
|
138 | - |
|
139 | - /** |
|
140 | - * {@inheritDoc} |
|
141 | - */ |
|
142 | - public static function getSubscribedEvents() |
|
143 | - { |
|
144 | - return array( |
|
145 | - ScriptEvents::POST_INSTALL_CMD => array( |
|
146 | - array('onDependenciesChangedEvent', 0), |
|
147 | - ), |
|
148 | - ScriptEvents::POST_UPDATE_CMD => array( |
|
149 | - array('onDependenciesChangedEvent', 0), |
|
150 | - ), |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - /** |
|
155 | - * Entry point for post install and post update events. |
|
156 | - * |
|
157 | - * @throws \InvalidArgumentException |
|
158 | - * @throws LogicException |
|
159 | - * @throws ProcessFailedException |
|
160 | - * @throws RuntimeException |
|
161 | - */ |
|
162 | - public function onDependenciesChangedEvent() |
|
163 | - { |
|
164 | - $io = $this->io; |
|
165 | - $isVerbose = $io->isVerbose(); |
|
166 | - |
|
167 | - if ($isVerbose) { |
|
168 | - $io->write(sprintf('<info>%s</info>', self::MESSAGE_RUNNING_INSTALLER)); |
|
169 | - } |
|
170 | - |
|
171 | - if ($this->isPHPCodeSnifferInstalled() === true) { |
|
172 | - $this->loadInstalledPaths(); |
|
173 | - $installPathCleaned = $this->cleanInstalledPaths(); |
|
174 | - $installPathUpdated = $this->updateInstalledPaths(); |
|
175 | - |
|
176 | - if ($installPathCleaned === true || $installPathUpdated === true) { |
|
177 | - $this->saveInstalledPaths(); |
|
178 | - } elseif ($isVerbose) { |
|
179 | - $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOTHING_TO_INSTALL)); |
|
180 | - } |
|
181 | - } elseif ($isVerbose) { |
|
182 | - $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOT_INSTALLED)); |
|
183 | - } |
|
184 | - } |
|
185 | - |
|
186 | - /** |
|
187 | - * Load all paths from PHP_CodeSniffer into an array. |
|
188 | - * |
|
189 | - * @throws LogicException |
|
190 | - * @throws ProcessFailedException |
|
191 | - * @throws RuntimeException |
|
192 | - */ |
|
193 | - private function loadInstalledPaths() |
|
194 | - { |
|
195 | - if ($this->isPHPCodeSnifferInstalled() === true) { |
|
196 | - $this->processExecutor->execute( |
|
197 | - sprintf( |
|
198 | - 'phpcs --config-show %s', |
|
199 | - self::PHPCS_CONFIG_KEY |
|
200 | - ), |
|
201 | - $output, |
|
202 | - $this->composer->getConfig()->get('bin-dir') |
|
203 | - ); |
|
204 | - |
|
205 | - $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $output); |
|
206 | - $phpcsInstalledPaths = trim($phpcsInstalledPaths); |
|
207 | - |
|
208 | - if ($phpcsInstalledPaths !== '') { |
|
209 | - $this->installedPaths = explode(',', $phpcsInstalledPaths); |
|
210 | - } |
|
211 | - } |
|
212 | - } |
|
213 | - |
|
214 | - /** |
|
215 | - * Save all coding standard paths back into PHP_CodeSniffer |
|
216 | - * |
|
217 | - * @throws LogicException |
|
218 | - * @throws ProcessFailedException |
|
219 | - * @throws RuntimeException |
|
220 | - */ |
|
221 | - private function saveInstalledPaths() |
|
222 | - { |
|
223 | - // Check if we found installed paths to set. |
|
224 | - if (count($this->installedPaths) !== 0) { |
|
225 | - $paths = implode(',', $this->installedPaths); |
|
226 | - $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); |
|
227 | - $configMessage = sprintf( |
|
228 | - 'PHP CodeSniffer Config <info>%s</info> <comment>set to</comment> <info>%s</info>', |
|
229 | - self::PHPCS_CONFIG_KEY, |
|
230 | - $paths |
|
231 | - ); |
|
232 | - } else { |
|
233 | - // Delete the installed paths if none were found. |
|
234 | - $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); |
|
235 | - $configMessage = sprintf( |
|
236 | - 'PHP CodeSniffer Config <info>%s</info> <comment>delete</comment>', |
|
237 | - self::PHPCS_CONFIG_KEY |
|
238 | - ); |
|
239 | - } |
|
240 | - |
|
241 | - $this->io->write($configMessage); |
|
242 | - |
|
243 | - $this->processExecutor->execute( |
|
244 | - sprintf( |
|
245 | - 'phpcs %s', |
|
246 | - implode(' ', $arguments) |
|
247 | - ), |
|
248 | - $configResult, |
|
249 | - $this->composer->getConfig()->get('bin-dir') |
|
250 | - ); |
|
251 | - |
|
252 | - if ($this->io->isVerbose() && !empty($configResult)) { |
|
253 | - $this->io->write(sprintf('<info>%s</info>', $configResult)); |
|
254 | - } |
|
255 | - } |
|
256 | - |
|
257 | - /** |
|
258 | - * Iterate trough all known paths and check if they are still valid. |
|
259 | - * |
|
260 | - * If path does not exists, is not an directory or isn't readable, the path |
|
261 | - * is removed from the list. |
|
262 | - * |
|
263 | - * @return bool True if changes where made, false otherwise |
|
264 | - */ |
|
265 | - private function cleanInstalledPaths() |
|
266 | - { |
|
267 | - $changes = false; |
|
268 | - foreach ($this->installedPaths as $key => $path) { |
|
269 | - // This might be a relative path as well |
|
270 | - $alternativePath = realpath($this->getPHPCodeSnifferInstallPath() . DIRECTORY_SEPARATOR . $path); |
|
271 | - |
|
272 | - if ((is_dir($path) === false || is_readable($path) === false) && |
|
273 | - (is_dir($alternativePath) === false || is_readable($alternativePath) === false) |
|
274 | - ) { |
|
275 | - unset($this->installedPaths[$key]); |
|
276 | - $changes = true; |
|
277 | - } |
|
278 | - } |
|
279 | - return $changes; |
|
280 | - } |
|
281 | - |
|
282 | - /** |
|
283 | - * Check all installed packages (including the root package) against |
|
284 | - * the installed paths from PHP_CodeSniffer and add the missing ones. |
|
285 | - * |
|
286 | - * @return bool True if changes where made, false otherwise |
|
287 | - * |
|
288 | - * @throws \InvalidArgumentException |
|
289 | - * @throws \RuntimeException |
|
290 | - */ |
|
291 | - private function updateInstalledPaths() |
|
292 | - { |
|
293 | - $changes = false; |
|
294 | - |
|
295 | - $searchPaths = array($this->cwd); |
|
296 | - $codingStandardPackages = $this->getPHPCodingStandardPackages(); |
|
297 | - foreach ($codingStandardPackages as $package) { |
|
298 | - $installPath = $this->composer->getInstallationManager()->getInstallPath($package); |
|
299 | - if ($this->filesystem->isAbsolutePath($installPath) === false) { |
|
300 | - $installPath = $this->filesystem->normalizePath( |
|
301 | - $this->cwd . DIRECTORY_SEPARATOR . $installPath |
|
302 | - ); |
|
303 | - } |
|
304 | - $searchPaths[] = $installPath; |
|
305 | - } |
|
306 | - |
|
307 | - $finder = new Finder(); |
|
308 | - $finder->files() |
|
309 | - ->depth('<= ' . $this->getMaxDepth()) |
|
310 | - ->depth('>= ' . $this->getMinDepth()) |
|
311 | - ->ignoreUnreadableDirs() |
|
312 | - ->ignoreVCS(true) |
|
313 | - ->in($searchPaths) |
|
314 | - ->name('ruleset.xml'); |
|
315 | - |
|
316 | - // Process each found possible ruleset. |
|
317 | - foreach ($finder as $ruleset) { |
|
318 | - $standardsPath = $ruleset->getPath(); |
|
319 | - |
|
320 | - // Pick the directory above the directory containing the standard, unless this is the project root. |
|
321 | - if ($standardsPath !== $this->cwd) { |
|
322 | - $standardsPath = dirname($standardsPath); |
|
323 | - } |
|
324 | - |
|
325 | - // Use relative paths for local project repositories. |
|
326 | - if ($this->isRunningGlobally() === false) { |
|
327 | - $standardsPath = $this->filesystem->findShortestPath( |
|
328 | - $this->getPHPCodeSnifferInstallPath(), |
|
329 | - $standardsPath, |
|
330 | - true |
|
331 | - ); |
|
332 | - } |
|
333 | - |
|
334 | - // De-duplicate and add when directory is not configured. |
|
335 | - if (in_array($standardsPath, $this->installedPaths, true) === false) { |
|
336 | - $this->installedPaths[] = $standardsPath; |
|
337 | - $changes = true; |
|
338 | - } |
|
339 | - } |
|
340 | - |
|
341 | - return $changes; |
|
342 | - } |
|
343 | - |
|
344 | - /** |
|
345 | - * Iterates through Composers' local repository looking for valid Coding |
|
346 | - * Standard packages. |
|
347 | - * |
|
348 | - * If the package is the RootPackage (the one the plugin is installed into), |
|
349 | - * the package is ignored for now since it needs a different install path logic. |
|
350 | - * |
|
351 | - * @return array Composer packages containing coding standard(s) |
|
352 | - */ |
|
353 | - private function getPHPCodingStandardPackages() |
|
354 | - { |
|
355 | - $codingStandardPackages = array_filter( |
|
356 | - $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), |
|
357 | - function (PackageInterface $package) { |
|
358 | - if ($package instanceof AliasPackage) { |
|
359 | - return false; |
|
360 | - } |
|
361 | - return $package->getType() === Plugin::PACKAGE_TYPE; |
|
362 | - } |
|
363 | - ); |
|
364 | - |
|
365 | - if (! $this->composer->getPackage() instanceof RootpackageInterface |
|
366 | - && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE |
|
367 | - ) { |
|
368 | - $codingStandardPackages[] = $this->composer->getPackage(); |
|
369 | - } |
|
370 | - |
|
371 | - return $codingStandardPackages; |
|
372 | - } |
|
373 | - |
|
374 | - /** |
|
375 | - * Searches for the installed PHP_CodeSniffer Composer package |
|
376 | - * |
|
377 | - * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against |
|
378 | - * |
|
379 | - * @return PackageInterface|null |
|
380 | - */ |
|
381 | - private function getPHPCodeSnifferPackage($versionConstraint = null) |
|
382 | - { |
|
383 | - $packages = $this |
|
384 | - ->composer |
|
385 | - ->getRepositoryManager() |
|
386 | - ->getLocalRepository() |
|
387 | - ->findPackages(self::PACKAGE_NAME, $versionConstraint); |
|
388 | - |
|
389 | - return array_shift($packages); |
|
390 | - } |
|
391 | - |
|
392 | - /** |
|
393 | - * Returns the path to the PHP_CodeSniffer package installation location |
|
394 | - * |
|
395 | - * @return string |
|
396 | - */ |
|
397 | - private function getPHPCodeSnifferInstallPath() |
|
398 | - { |
|
399 | - return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); |
|
400 | - } |
|
401 | - |
|
402 | - /** |
|
403 | - * Simple check if PHP_CodeSniffer is installed. |
|
404 | - * |
|
405 | - * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against |
|
406 | - * |
|
407 | - * @return bool Whether PHP_CodeSniffer is installed |
|
408 | - */ |
|
409 | - private function isPHPCodeSnifferInstalled($versionConstraint = null) |
|
410 | - { |
|
411 | - return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); |
|
412 | - } |
|
413 | - |
|
414 | - /** |
|
415 | - * Test if composer is running "global" |
|
416 | - * This check kinda dirty, but it is the "Composer Way" |
|
417 | - * |
|
418 | - * @return bool Whether Composer is running "globally" |
|
419 | - * |
|
420 | - * @throws \RuntimeException |
|
421 | - */ |
|
422 | - private function isRunningGlobally() |
|
423 | - { |
|
424 | - return ($this->composer->getConfig()->get('home') === $this->cwd); |
|
425 | - } |
|
426 | - |
|
427 | - /** |
|
428 | - * Determines the maximum search depth when searching for Coding Standards. |
|
429 | - * |
|
430 | - * @return int |
|
431 | - * |
|
432 | - * @throws \InvalidArgumentException |
|
433 | - */ |
|
434 | - private function getMaxDepth() |
|
435 | - { |
|
436 | - $maxDepth = 3; |
|
437 | - |
|
438 | - $extra = $this->composer->getPackage()->getExtra(); |
|
439 | - |
|
440 | - if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { |
|
441 | - $maxDepth = $extra[self::KEY_MAX_DEPTH]; |
|
442 | - $minDepth = $this->getMinDepth(); |
|
443 | - |
|
444 | - if (is_int($maxDepth) === false /* Must be an integer */ |
|
445 | - || $maxDepth <= $minDepth /* Larger than the minimum */ |
|
446 | - || is_float($maxDepth) === true /* Within the boundaries of integer */ |
|
447 | - ) { |
|
448 | - $message = vsprintf( |
|
449 | - self::MESSAGE_ERROR_WRONG_MAX_DEPTH, |
|
450 | - array( |
|
451 | - 'key' => self::KEY_MAX_DEPTH, |
|
452 | - 'min' => $minDepth, |
|
453 | - 'given' => var_export($maxDepth, true), |
|
454 | - ) |
|
455 | - ); |
|
456 | - |
|
457 | - throw new \InvalidArgumentException($message); |
|
458 | - } |
|
459 | - } |
|
460 | - |
|
461 | - return $maxDepth; |
|
462 | - } |
|
463 | - |
|
464 | - /** |
|
465 | - * Returns the minimal search depth for Coding Standard packages. |
|
466 | - * |
|
467 | - * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. |
|
468 | - * |
|
469 | - * @return int |
|
470 | - */ |
|
471 | - private function getMinDepth() |
|
472 | - { |
|
473 | - if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { |
|
474 | - return 1; |
|
475 | - } |
|
476 | - return 0; |
|
477 | - } |
|
37 | + const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; |
|
38 | + |
|
39 | + const MESSAGE_ERROR_WRONG_MAX_DEPTH = |
|
40 | + 'The value of "%s" (in the composer.json "extra".section) must be an integer larger then %d, %s given.'; |
|
41 | + const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; |
|
42 | + const MESSAGE_NOTHING_TO_INSTALL = 'Nothing to install or update'; |
|
43 | + const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; |
|
44 | + |
|
45 | + const PACKAGE_NAME = 'squizlabs/php_codesniffer'; |
|
46 | + const PACKAGE_TYPE = 'phpcodesniffer-standard'; |
|
47 | + |
|
48 | + const PHPCS_CONFIG_KEY = 'installed_paths'; |
|
49 | + |
|
50 | + /** |
|
51 | + * @var Composer |
|
52 | + */ |
|
53 | + private $composer; |
|
54 | + |
|
55 | + /** |
|
56 | + * @var string |
|
57 | + */ |
|
58 | + private $cwd; |
|
59 | + |
|
60 | + /** |
|
61 | + * @var Filesystem |
|
62 | + */ |
|
63 | + private $filesystem; |
|
64 | + |
|
65 | + /** |
|
66 | + * @var array |
|
67 | + */ |
|
68 | + private $installedPaths; |
|
69 | + |
|
70 | + /** |
|
71 | + * @var IOInterface |
|
72 | + */ |
|
73 | + private $io; |
|
74 | + |
|
75 | + /** |
|
76 | + * @var ProcessExecutor |
|
77 | + */ |
|
78 | + private $processExecutor; |
|
79 | + |
|
80 | + /** |
|
81 | + * Triggers the plugin's main functionality. |
|
82 | + * |
|
83 | + * Makes it possible to run the plugin as a custom command. |
|
84 | + * |
|
85 | + * @param Event $event |
|
86 | + * |
|
87 | + * @throws \InvalidArgumentException |
|
88 | + * @throws \RuntimeException |
|
89 | + * @throws LogicException |
|
90 | + * @throws ProcessFailedException |
|
91 | + * @throws RuntimeException |
|
92 | + */ |
|
93 | + public static function run(Event $event) |
|
94 | + { |
|
95 | + $io = $event->getIO(); |
|
96 | + $composer = $event->getComposer(); |
|
97 | + |
|
98 | + $instance = new static(); |
|
99 | + |
|
100 | + $instance->io = $io; |
|
101 | + $instance->composer = $composer; |
|
102 | + $instance->init(); |
|
103 | + $instance->onDependenciesChangedEvent(); |
|
104 | + } |
|
105 | + |
|
106 | + /** |
|
107 | + * {@inheritDoc} |
|
108 | + * |
|
109 | + * @throws \RuntimeException |
|
110 | + * @throws LogicException |
|
111 | + * @throws ProcessFailedException |
|
112 | + * @throws RuntimeException |
|
113 | + */ |
|
114 | + public function activate(Composer $composer, IOInterface $io) |
|
115 | + { |
|
116 | + $this->composer = $composer; |
|
117 | + $this->io = $io; |
|
118 | + |
|
119 | + $this->init(); |
|
120 | + } |
|
121 | + |
|
122 | + /** |
|
123 | + * Prepares the plugin so it's main functionality can be run. |
|
124 | + * |
|
125 | + * @throws \RuntimeException |
|
126 | + * @throws LogicException |
|
127 | + * @throws ProcessFailedException |
|
128 | + * @throws RuntimeException |
|
129 | + */ |
|
130 | + private function init() |
|
131 | + { |
|
132 | + $this->cwd = getcwd(); |
|
133 | + $this->installedPaths = array(); |
|
134 | + |
|
135 | + $this->processExecutor = new ProcessExecutor($this->io); |
|
136 | + $this->filesystem = new Filesystem($this->processExecutor); |
|
137 | + } |
|
138 | + |
|
139 | + /** |
|
140 | + * {@inheritDoc} |
|
141 | + */ |
|
142 | + public static function getSubscribedEvents() |
|
143 | + { |
|
144 | + return array( |
|
145 | + ScriptEvents::POST_INSTALL_CMD => array( |
|
146 | + array('onDependenciesChangedEvent', 0), |
|
147 | + ), |
|
148 | + ScriptEvents::POST_UPDATE_CMD => array( |
|
149 | + array('onDependenciesChangedEvent', 0), |
|
150 | + ), |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + /** |
|
155 | + * Entry point for post install and post update events. |
|
156 | + * |
|
157 | + * @throws \InvalidArgumentException |
|
158 | + * @throws LogicException |
|
159 | + * @throws ProcessFailedException |
|
160 | + * @throws RuntimeException |
|
161 | + */ |
|
162 | + public function onDependenciesChangedEvent() |
|
163 | + { |
|
164 | + $io = $this->io; |
|
165 | + $isVerbose = $io->isVerbose(); |
|
166 | + |
|
167 | + if ($isVerbose) { |
|
168 | + $io->write(sprintf('<info>%s</info>', self::MESSAGE_RUNNING_INSTALLER)); |
|
169 | + } |
|
170 | + |
|
171 | + if ($this->isPHPCodeSnifferInstalled() === true) { |
|
172 | + $this->loadInstalledPaths(); |
|
173 | + $installPathCleaned = $this->cleanInstalledPaths(); |
|
174 | + $installPathUpdated = $this->updateInstalledPaths(); |
|
175 | + |
|
176 | + if ($installPathCleaned === true || $installPathUpdated === true) { |
|
177 | + $this->saveInstalledPaths(); |
|
178 | + } elseif ($isVerbose) { |
|
179 | + $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOTHING_TO_INSTALL)); |
|
180 | + } |
|
181 | + } elseif ($isVerbose) { |
|
182 | + $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOT_INSTALLED)); |
|
183 | + } |
|
184 | + } |
|
185 | + |
|
186 | + /** |
|
187 | + * Load all paths from PHP_CodeSniffer into an array. |
|
188 | + * |
|
189 | + * @throws LogicException |
|
190 | + * @throws ProcessFailedException |
|
191 | + * @throws RuntimeException |
|
192 | + */ |
|
193 | + private function loadInstalledPaths() |
|
194 | + { |
|
195 | + if ($this->isPHPCodeSnifferInstalled() === true) { |
|
196 | + $this->processExecutor->execute( |
|
197 | + sprintf( |
|
198 | + 'phpcs --config-show %s', |
|
199 | + self::PHPCS_CONFIG_KEY |
|
200 | + ), |
|
201 | + $output, |
|
202 | + $this->composer->getConfig()->get('bin-dir') |
|
203 | + ); |
|
204 | + |
|
205 | + $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $output); |
|
206 | + $phpcsInstalledPaths = trim($phpcsInstalledPaths); |
|
207 | + |
|
208 | + if ($phpcsInstalledPaths !== '') { |
|
209 | + $this->installedPaths = explode(',', $phpcsInstalledPaths); |
|
210 | + } |
|
211 | + } |
|
212 | + } |
|
213 | + |
|
214 | + /** |
|
215 | + * Save all coding standard paths back into PHP_CodeSniffer |
|
216 | + * |
|
217 | + * @throws LogicException |
|
218 | + * @throws ProcessFailedException |
|
219 | + * @throws RuntimeException |
|
220 | + */ |
|
221 | + private function saveInstalledPaths() |
|
222 | + { |
|
223 | + // Check if we found installed paths to set. |
|
224 | + if (count($this->installedPaths) !== 0) { |
|
225 | + $paths = implode(',', $this->installedPaths); |
|
226 | + $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); |
|
227 | + $configMessage = sprintf( |
|
228 | + 'PHP CodeSniffer Config <info>%s</info> <comment>set to</comment> <info>%s</info>', |
|
229 | + self::PHPCS_CONFIG_KEY, |
|
230 | + $paths |
|
231 | + ); |
|
232 | + } else { |
|
233 | + // Delete the installed paths if none were found. |
|
234 | + $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); |
|
235 | + $configMessage = sprintf( |
|
236 | + 'PHP CodeSniffer Config <info>%s</info> <comment>delete</comment>', |
|
237 | + self::PHPCS_CONFIG_KEY |
|
238 | + ); |
|
239 | + } |
|
240 | + |
|
241 | + $this->io->write($configMessage); |
|
242 | + |
|
243 | + $this->processExecutor->execute( |
|
244 | + sprintf( |
|
245 | + 'phpcs %s', |
|
246 | + implode(' ', $arguments) |
|
247 | + ), |
|
248 | + $configResult, |
|
249 | + $this->composer->getConfig()->get('bin-dir') |
|
250 | + ); |
|
251 | + |
|
252 | + if ($this->io->isVerbose() && !empty($configResult)) { |
|
253 | + $this->io->write(sprintf('<info>%s</info>', $configResult)); |
|
254 | + } |
|
255 | + } |
|
256 | + |
|
257 | + /** |
|
258 | + * Iterate trough all known paths and check if they are still valid. |
|
259 | + * |
|
260 | + * If path does not exists, is not an directory or isn't readable, the path |
|
261 | + * is removed from the list. |
|
262 | + * |
|
263 | + * @return bool True if changes where made, false otherwise |
|
264 | + */ |
|
265 | + private function cleanInstalledPaths() |
|
266 | + { |
|
267 | + $changes = false; |
|
268 | + foreach ($this->installedPaths as $key => $path) { |
|
269 | + // This might be a relative path as well |
|
270 | + $alternativePath = realpath($this->getPHPCodeSnifferInstallPath() . DIRECTORY_SEPARATOR . $path); |
|
271 | + |
|
272 | + if ((is_dir($path) === false || is_readable($path) === false) && |
|
273 | + (is_dir($alternativePath) === false || is_readable($alternativePath) === false) |
|
274 | + ) { |
|
275 | + unset($this->installedPaths[$key]); |
|
276 | + $changes = true; |
|
277 | + } |
|
278 | + } |
|
279 | + return $changes; |
|
280 | + } |
|
281 | + |
|
282 | + /** |
|
283 | + * Check all installed packages (including the root package) against |
|
284 | + * the installed paths from PHP_CodeSniffer and add the missing ones. |
|
285 | + * |
|
286 | + * @return bool True if changes where made, false otherwise |
|
287 | + * |
|
288 | + * @throws \InvalidArgumentException |
|
289 | + * @throws \RuntimeException |
|
290 | + */ |
|
291 | + private function updateInstalledPaths() |
|
292 | + { |
|
293 | + $changes = false; |
|
294 | + |
|
295 | + $searchPaths = array($this->cwd); |
|
296 | + $codingStandardPackages = $this->getPHPCodingStandardPackages(); |
|
297 | + foreach ($codingStandardPackages as $package) { |
|
298 | + $installPath = $this->composer->getInstallationManager()->getInstallPath($package); |
|
299 | + if ($this->filesystem->isAbsolutePath($installPath) === false) { |
|
300 | + $installPath = $this->filesystem->normalizePath( |
|
301 | + $this->cwd . DIRECTORY_SEPARATOR . $installPath |
|
302 | + ); |
|
303 | + } |
|
304 | + $searchPaths[] = $installPath; |
|
305 | + } |
|
306 | + |
|
307 | + $finder = new Finder(); |
|
308 | + $finder->files() |
|
309 | + ->depth('<= ' . $this->getMaxDepth()) |
|
310 | + ->depth('>= ' . $this->getMinDepth()) |
|
311 | + ->ignoreUnreadableDirs() |
|
312 | + ->ignoreVCS(true) |
|
313 | + ->in($searchPaths) |
|
314 | + ->name('ruleset.xml'); |
|
315 | + |
|
316 | + // Process each found possible ruleset. |
|
317 | + foreach ($finder as $ruleset) { |
|
318 | + $standardsPath = $ruleset->getPath(); |
|
319 | + |
|
320 | + // Pick the directory above the directory containing the standard, unless this is the project root. |
|
321 | + if ($standardsPath !== $this->cwd) { |
|
322 | + $standardsPath = dirname($standardsPath); |
|
323 | + } |
|
324 | + |
|
325 | + // Use relative paths for local project repositories. |
|
326 | + if ($this->isRunningGlobally() === false) { |
|
327 | + $standardsPath = $this->filesystem->findShortestPath( |
|
328 | + $this->getPHPCodeSnifferInstallPath(), |
|
329 | + $standardsPath, |
|
330 | + true |
|
331 | + ); |
|
332 | + } |
|
333 | + |
|
334 | + // De-duplicate and add when directory is not configured. |
|
335 | + if (in_array($standardsPath, $this->installedPaths, true) === false) { |
|
336 | + $this->installedPaths[] = $standardsPath; |
|
337 | + $changes = true; |
|
338 | + } |
|
339 | + } |
|
340 | + |
|
341 | + return $changes; |
|
342 | + } |
|
343 | + |
|
344 | + /** |
|
345 | + * Iterates through Composers' local repository looking for valid Coding |
|
346 | + * Standard packages. |
|
347 | + * |
|
348 | + * If the package is the RootPackage (the one the plugin is installed into), |
|
349 | + * the package is ignored for now since it needs a different install path logic. |
|
350 | + * |
|
351 | + * @return array Composer packages containing coding standard(s) |
|
352 | + */ |
|
353 | + private function getPHPCodingStandardPackages() |
|
354 | + { |
|
355 | + $codingStandardPackages = array_filter( |
|
356 | + $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), |
|
357 | + function (PackageInterface $package) { |
|
358 | + if ($package instanceof AliasPackage) { |
|
359 | + return false; |
|
360 | + } |
|
361 | + return $package->getType() === Plugin::PACKAGE_TYPE; |
|
362 | + } |
|
363 | + ); |
|
364 | + |
|
365 | + if (! $this->composer->getPackage() instanceof RootpackageInterface |
|
366 | + && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE |
|
367 | + ) { |
|
368 | + $codingStandardPackages[] = $this->composer->getPackage(); |
|
369 | + } |
|
370 | + |
|
371 | + return $codingStandardPackages; |
|
372 | + } |
|
373 | + |
|
374 | + /** |
|
375 | + * Searches for the installed PHP_CodeSniffer Composer package |
|
376 | + * |
|
377 | + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against |
|
378 | + * |
|
379 | + * @return PackageInterface|null |
|
380 | + */ |
|
381 | + private function getPHPCodeSnifferPackage($versionConstraint = null) |
|
382 | + { |
|
383 | + $packages = $this |
|
384 | + ->composer |
|
385 | + ->getRepositoryManager() |
|
386 | + ->getLocalRepository() |
|
387 | + ->findPackages(self::PACKAGE_NAME, $versionConstraint); |
|
388 | + |
|
389 | + return array_shift($packages); |
|
390 | + } |
|
391 | + |
|
392 | + /** |
|
393 | + * Returns the path to the PHP_CodeSniffer package installation location |
|
394 | + * |
|
395 | + * @return string |
|
396 | + */ |
|
397 | + private function getPHPCodeSnifferInstallPath() |
|
398 | + { |
|
399 | + return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); |
|
400 | + } |
|
401 | + |
|
402 | + /** |
|
403 | + * Simple check if PHP_CodeSniffer is installed. |
|
404 | + * |
|
405 | + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against |
|
406 | + * |
|
407 | + * @return bool Whether PHP_CodeSniffer is installed |
|
408 | + */ |
|
409 | + private function isPHPCodeSnifferInstalled($versionConstraint = null) |
|
410 | + { |
|
411 | + return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); |
|
412 | + } |
|
413 | + |
|
414 | + /** |
|
415 | + * Test if composer is running "global" |
|
416 | + * This check kinda dirty, but it is the "Composer Way" |
|
417 | + * |
|
418 | + * @return bool Whether Composer is running "globally" |
|
419 | + * |
|
420 | + * @throws \RuntimeException |
|
421 | + */ |
|
422 | + private function isRunningGlobally() |
|
423 | + { |
|
424 | + return ($this->composer->getConfig()->get('home') === $this->cwd); |
|
425 | + } |
|
426 | + |
|
427 | + /** |
|
428 | + * Determines the maximum search depth when searching for Coding Standards. |
|
429 | + * |
|
430 | + * @return int |
|
431 | + * |
|
432 | + * @throws \InvalidArgumentException |
|
433 | + */ |
|
434 | + private function getMaxDepth() |
|
435 | + { |
|
436 | + $maxDepth = 3; |
|
437 | + |
|
438 | + $extra = $this->composer->getPackage()->getExtra(); |
|
439 | + |
|
440 | + if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { |
|
441 | + $maxDepth = $extra[self::KEY_MAX_DEPTH]; |
|
442 | + $minDepth = $this->getMinDepth(); |
|
443 | + |
|
444 | + if (is_int($maxDepth) === false /* Must be an integer */ |
|
445 | + || $maxDepth <= $minDepth /* Larger than the minimum */ |
|
446 | + || is_float($maxDepth) === true /* Within the boundaries of integer */ |
|
447 | + ) { |
|
448 | + $message = vsprintf( |
|
449 | + self::MESSAGE_ERROR_WRONG_MAX_DEPTH, |
|
450 | + array( |
|
451 | + 'key' => self::KEY_MAX_DEPTH, |
|
452 | + 'min' => $minDepth, |
|
453 | + 'given' => var_export($maxDepth, true), |
|
454 | + ) |
|
455 | + ); |
|
456 | + |
|
457 | + throw new \InvalidArgumentException($message); |
|
458 | + } |
|
459 | + } |
|
460 | + |
|
461 | + return $maxDepth; |
|
462 | + } |
|
463 | + |
|
464 | + /** |
|
465 | + * Returns the minimal search depth for Coding Standard packages. |
|
466 | + * |
|
467 | + * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. |
|
468 | + * |
|
469 | + * @return int |
|
470 | + */ |
|
471 | + private function getMinDepth() |
|
472 | + { |
|
473 | + if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { |
|
474 | + return 1; |
|
475 | + } |
|
476 | + return 0; |
|
477 | + } |
|
478 | 478 | } |
@@ -8,40 +8,40 @@ discard block |
||
8 | 8 | */ |
9 | 9 | |
10 | 10 | if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { |
11 | - define('PHP_CODESNIFFER_IN_TESTS', true); |
|
11 | + define('PHP_CODESNIFFER_IN_TESTS', true); |
|
12 | 12 | } |
13 | 13 | |
14 | 14 | if (defined('PHP_CODESNIFFER_CBF') === false) { |
15 | - define('PHP_CODESNIFFER_CBF', false); |
|
15 | + define('PHP_CODESNIFFER_CBF', false); |
|
16 | 16 | } |
17 | 17 | |
18 | 18 | if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { |
19 | - define('PHP_CODESNIFFER_VERBOSITY', 0); |
|
19 | + define('PHP_CODESNIFFER_VERBOSITY', 0); |
|
20 | 20 | } |
21 | 21 | |
22 | 22 | if (is_file(__DIR__.'/../autoload.php') === true) { |
23 | - include_once __DIR__.'/../autoload.php'; |
|
23 | + include_once __DIR__.'/../autoload.php'; |
|
24 | 24 | } else { |
25 | - include_once 'PHP/CodeSniffer/autoload.php'; |
|
25 | + include_once 'PHP/CodeSniffer/autoload.php'; |
|
26 | 26 | } |
27 | 27 | |
28 | 28 | $tokens = new \PHP_CodeSniffer\Util\Tokens(); |
29 | 29 | |
30 | 30 | // Compatibility for PHPUnit < 6 and PHPUnit 6+. |
31 | 31 | if (class_exists('PHPUnit_Framework_TestSuite') === true && class_exists('PHPUnit\Framework\TestSuite') === false) { |
32 | - class_alias('PHPUnit_Framework_TestSuite', 'PHPUnit'.'\Framework\TestSuite'); |
|
32 | + class_alias('PHPUnit_Framework_TestSuite', 'PHPUnit'.'\Framework\TestSuite'); |
|
33 | 33 | } |
34 | 34 | |
35 | 35 | if (class_exists('PHPUnit_Framework_TestCase') === true && class_exists('PHPUnit\Framework\TestCase') === false) { |
36 | - class_alias('PHPUnit_Framework_TestCase', 'PHPUnit'.'\Framework\TestCase'); |
|
36 | + class_alias('PHPUnit_Framework_TestCase', 'PHPUnit'.'\Framework\TestCase'); |
|
37 | 37 | } |
38 | 38 | |
39 | 39 | if (class_exists('PHPUnit_TextUI_TestRunner') === true && class_exists('PHPUnit\TextUI\TestRunner') === false) { |
40 | - class_alias('PHPUnit_TextUI_TestRunner', 'PHPUnit'.'\TextUI\TestRunner'); |
|
40 | + class_alias('PHPUnit_TextUI_TestRunner', 'PHPUnit'.'\TextUI\TestRunner'); |
|
41 | 41 | } |
42 | 42 | |
43 | 43 | if (class_exists('PHPUnit_Framework_TestResult') === true && class_exists('PHPUnit\Framework\TestResult') === false) { |
44 | - class_alias('PHPUnit_Framework_TestResult', 'PHPUnit'.'\Framework\TestResult'); |
|
44 | + class_alias('PHPUnit_Framework_TestResult', 'PHPUnit'.'\Framework\TestResult'); |
|
45 | 45 | } |
46 | 46 | |
47 | 47 | |
@@ -52,33 +52,33 @@ discard block |
||
52 | 52 | */ |
53 | 53 | function printPHPCodeSnifferTestOutput() |
54 | 54 | { |
55 | - echo PHP_EOL.PHP_EOL; |
|
55 | + echo PHP_EOL.PHP_EOL; |
|
56 | 56 | |
57 | - $output = 'The test files'; |
|
58 | - $data = []; |
|
57 | + $output = 'The test files'; |
|
58 | + $data = []; |
|
59 | 59 | |
60 | - $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); |
|
61 | - if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { |
|
62 | - $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); |
|
63 | - $files = array_unique($files); |
|
64 | - $fileCount = count($files); |
|
60 | + $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); |
|
61 | + if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { |
|
62 | + $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); |
|
63 | + $files = array_unique($files); |
|
64 | + $fileCount = count($files); |
|
65 | 65 | |
66 | - $output = '%d sniff test files'; |
|
67 | - $data[] = $fileCount; |
|
68 | - } |
|
66 | + $output = '%d sniff test files'; |
|
67 | + $data[] = $fileCount; |
|
68 | + } |
|
69 | 69 | |
70 | - $output .= ' generated %d unique error codes'; |
|
71 | - $data[] = $codeCount; |
|
70 | + $output .= ' generated %d unique error codes'; |
|
71 | + $data[] = $codeCount; |
|
72 | 72 | |
73 | - if ($codeCount > 0) { |
|
74 | - $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); |
|
75 | - $percent = round(($fixes / $codeCount * 100), 2); |
|
73 | + if ($codeCount > 0) { |
|
74 | + $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); |
|
75 | + $percent = round(($fixes / $codeCount * 100), 2); |
|
76 | 76 | |
77 | - $output .= '; %d were fixable (%d%%)'; |
|
78 | - $data[] = $fixes; |
|
79 | - $data[] = $percent; |
|
80 | - } |
|
77 | + $output .= '; %d were fixable (%d%%)'; |
|
78 | + $data[] = $fixes; |
|
79 | + $data[] = $percent; |
|
80 | + } |
|
81 | 81 | |
82 | - vprintf($output, $data); |
|
82 | + vprintf($output, $data); |
|
83 | 83 | |
84 | 84 | }//end printPHPCodeSnifferTestOutput() |