GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 699b70...879176 )
by Chris
13:23
created

SwitchDeclarationSniff::process()   F

Complexity

Conditions 33
Paths > 20000

Size

Total Lines 157
Code Lines 98

Duplication

Lines 157
Ratio 100 %

Importance

Changes 0
Metric Value
cc 33
eloc 98
nc 26042
nop 2
dl 157
loc 157
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <[email protected]>
10
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12
 * @link      http://pear.php.net/package/PHP_CodeSniffer
13
 */
14
15
namespace PSR2R\Sniffs\ControlStructures;
16
17
use PHP_CodeSniffer_File;
18
use PHP_CodeSniffer_Sniff;
19
20
/**
21
 * PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff.
22
 *
23
 * Ensures all switch statements are defined correctly.
24
 *
25
 * @author Greg Sherwood <[email protected]>
26
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
27
 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
28
 * @version Release: @package_version@
29
 * @link http://pear.php.net/package/PHP_CodeSniffer
30
 */
31 View Code Duplication
class SwitchDeclarationSniff implements PHP_CodeSniffer_Sniff {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

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

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

Loading history...
32
33
	/**
34
	 * The number of spaces code should be indented.
35
	 *
36
	 * @var int
37
	 */
38
	public $indent = 4;
39
40
41
	/**
42
	 * @inheritDoc
43
	 */
44
	public function register() {
45
		return [T_SWITCH];
46
47
	}
48
49
50
	/**
51
	 * @inheritDoc
52
	 */
53
	public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) {
54
		$tokens = $phpcsFile->getTokens();
55
56
		// TODO: Auto-detect spaces vs tabs, maybe using a trait method indent($index, $this->indent)
57
		$this->indent = 1;
58
59
		// We can't process SWITCH statements unless we know where they start and end.
60
		if (isset($tokens[$stackPtr]['scope_opener']) === false
61
			|| isset($tokens[$stackPtr]['scope_closer']) === false
62
		) {
63
			return;
64
		}
65
66
		$switch = $tokens[$stackPtr];
67
		$nextCase = $stackPtr;
68
		$caseAlignment = ($switch['column'] + $this->indent);
69
		$caseCount = 0;
70
		$foundDefault = false;
0 ignored issues
show
Unused Code introduced by
$foundDefault is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
71
72
		while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $switch['scope_closer'])) !== false) {
73
			if ($tokens[$nextCase]['code'] === T_DEFAULT) {
74
				$type = 'default';
75
				$foundDefault = true;
0 ignored issues
show
Unused Code introduced by
$foundDefault is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
76
			} else {
77
				$type = 'case';
78
				$caseCount++;
79
			}
80
81
			if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) {
82
				$expected = strtolower($tokens[$nextCase]['content']);
83
				$error = strtoupper($type) . ' keyword must be lowercase; expected "%s" but found "%s"';
84
				$data = [
85
							 $expected,
86
							 $tokens[$nextCase]['content'],
87
							];
88
89
				$fix = $phpcsFile->addFixableError($error, $nextCase, $type . 'NotLower', $data);
90
				if ($fix === true) {
91
					$phpcsFile->fixer->replaceToken($nextCase, $expected);
92
				}
93
			}
94
95
			if ($type === 'case'
96
				&& ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE
97
				|| $tokens[($nextCase + 1)]['content'] !== ' ')
98
			) {
99
				$error = 'CASE keyword must be followed by a single space';
100
				$fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase');
101
				if ($fix === true) {
102
					if ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE) {
103
						$phpcsFile->fixer->addContent($nextCase, ' ');
104
					} else {
105
						$phpcsFile->fixer->replaceToken(($nextCase + 1), ' ');
106
					}
107
				}
108
			}
109
110
			$opener = $tokens[$nextCase]['scope_opener'];
111
			if ($tokens[$opener]['code'] === T_COLON) {
112
				if ($tokens[($opener - 1)]['code'] === T_WHITESPACE) {
113
					$error = 'There must be no space before the colon in a ' . strtoupper($type) . ' statement';
114
					$fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon' . strtoupper($type));
115
					if ($fix === true) {
116
						$phpcsFile->fixer->replaceToken(($opener - 1), '');
117
					}
118
				}
119
120
				$next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true);
121
				if ($tokens[$next]['line'] === $tokens[$opener]['line']
122
					&& $tokens[$next]['code'] === T_COMMENT
123
				) {
124
					// Skip comments on the same line.
125
					$next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
126
				}
127
128
				if ($tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) {
129
					$error = 'The ' . strtoupper($type) . ' body must start on the line following the statement';
130
					$fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon' . strtoupper($type));
131
					if ($fix === true) {
132
						if ($tokens[$next]['line'] === $tokens[$opener]['line']) {
133
							$padding = str_repeat(' ', ($caseAlignment + $this->indent - 1));
134
							$phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar . $padding);
0 ignored issues
show
Security Bug introduced by
It seems like $next can also be of type false; however, PHP_CodeSniffer_Fixer::addContentBefore() does only seem to accept integer, did you maybe forget to handle an error condition?
Loading history...
135
						} else {
136
							$phpcsFile->fixer->beginChangeset();
137
							for ($i = ($opener + 1); $i < $next; $i++) {
138
								if ($tokens[$i]['line'] === $tokens[$next]['line']) {
139
									break;
140
								}
141
142
								$phpcsFile->fixer->replaceToken($i, '');
143
							}
144
145
							$phpcsFile->fixer->addNewLineBefore($i);
146
							$phpcsFile->fixer->endChangeset();
147
						}
148
					}
149
				}
150
			} else {
151
				$error = strtoupper($type) . ' statements must be defined using a colon';
152
				$phpcsFile->addError($error, $nextCase, 'WrongOpener' . $type);
153
			}
154
155
			$nextCloser = $tokens[$nextCase]['scope_closer'];
156
			if ($tokens[$nextCloser]['scope_condition'] === $nextCase) {
157
				// Only need to check some things once, even if the
158
				// closer is shared between multiple case statements, or even
159
				// the default case.
160
				$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCloser - 1), $nextCase, true);
161
				if ($tokens[$prev]['line'] === $tokens[$nextCloser]['line']) {
162
					$error = 'Terminating statement must be on a line by itself';
163
					$fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakNotNewLine');
164
					if ($fix === true) {
165
						$phpcsFile->fixer->addNewLine($prev);
0 ignored issues
show
Bug introduced by
It seems like $prev defined by $phpcsFile->findPrevious...r - 1, $nextCase, true) on line 160 can also be of type boolean; however, PHP_CodeSniffer_Fixer::addNewline() does only seem to accept integer, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
166
						$phpcsFile->fixer->replaceToken($nextCloser, trim($tokens[$nextCloser]['content']));
167
					}
168
				} else {
169
					$diff = ($caseAlignment + $this->indent - $tokens[$nextCloser]['column']);
170
					if ($diff !== 0) {
171
						$error = 'Terminating statement must be indented to the same level as the CASE body';
172
						$fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakIndent');
173
						if ($fix === true) {
174
							if ($diff > 0) {
175
								$phpcsFile->fixer->addContentBefore($nextCloser, str_repeat(' ', $diff));
176
							} else {
177
								$phpcsFile->fixer->substrToken(($nextCloser - 1), 0, $diff);
178
							}
179
						}
180
					}
181
				}
182
			}
183
184
			// We only want cases from here on in.
185
			if ($type !== 'case') {
186
				continue;
187
			}
188
189
			$nextCode = $phpcsFile->findNext(T_WHITESPACE,
190
				($tokens[$nextCase]['scope_opener'] + 1),
191
				$nextCloser,
192
				true);
193
194
			if ($tokens[$nextCode]['code'] !== T_CASE && $tokens[$nextCode]['code'] !== T_DEFAULT) {
195
				// This case statement has content. If the next case or default comes
196
				// before the closer, it means we dont have a terminating statement
197
				// and instead need a comment.
198
				$nextCode = $this->findNextCase($phpcsFile, ($tokens[$nextCase]['scope_opener'] + 1), $nextCloser);
199
				if ($nextCode !== false) {
200
					$prevCode = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCode - 1), $nextCase, true);
201
					if ($tokens[$prevCode]['code'] !== T_COMMENT) {
202
						$error = 'There must be a comment when fall-through is intentional in a non-empty case body';
203
						$phpcsFile->addError($error, $nextCase, 'TerminatingComment');
204
					}
205
				}
206
			}
207
		}
208
209
	}
210
211
212
	/**
213
	 * Find the next CASE or DEFAULT statement from a point in the file.
214
	 *
215
	 * Note that nested switches are ignored.
216
	 *
217
	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
218
	 * @param int $stackPtr The position to start looking at.
219
	 * @param int $end The position to stop looking at.
220
	 *
221
	 * @return int | bool
222
	 */
223
	protected function findNextCase(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $end) {
224
		$tokens = $phpcsFile->getTokens();
225
		while (($stackPtr = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], $stackPtr, $end)) !== false) {
226
			// Skip nested SWITCH statements; they are handled on their own.
227
			if ($tokens[$stackPtr]['code'] === T_SWITCH) {
228
				$stackPtr = $tokens[$stackPtr]['scope_closer'];
229
				continue;
230
			}
231
232
			break;
233
		}
234
235
		return $stackPtr;
236
237
	}
238
239
}
240