function File::findStartOfStatement
Returns the position of the first non-whitespace token in a statement.
Parameters
int $start The position to start searching from in the token stack.:
int|string|array $ignore Token types that should not be considered stop points.:
Return value
int
File
-
vendor/
squizlabs/ php_codesniffer/ src/ Files/ File.php, line 2410
Class
Namespace
PHP_CodeSniffer\FilesCode
public function findStartOfStatement($start, $ignore = null) {
$startTokens = Tokens::$blockOpeners;
$startTokens[T_OPEN_SHORT_ARRAY] = true;
$startTokens[T_OPEN_TAG] = true;
$startTokens[T_OPEN_TAG_WITH_ECHO] = true;
$endTokens = [
T_CLOSE_TAG => true,
T_COLON => true,
T_COMMA => true,
T_DOUBLE_ARROW => true,
T_MATCH_ARROW => true,
T_SEMICOLON => true,
];
if ($ignore !== null) {
$ignore = (array) $ignore;
foreach ($ignore as $code) {
if (isset($startTokens[$code]) === true) {
unset($startTokens[$code]);
}
if (isset($endTokens[$code]) === true) {
unset($endTokens[$code]);
}
}
}
// If the start token is inside the case part of a match expression,
// find the start of the condition. If it's in the statement part, find
// the token that comes after the match arrow.
if (empty($this->tokens[$start]['conditions']) === false) {
$conditions = $this->tokens[$start]['conditions'];
$lastConditionOwner = end($conditions);
$matchExpression = key($conditions);
if ($lastConditionOwner === T_MATCH && (empty($this->tokens[$matchExpression]['nested_parenthesis']) === true && empty($this->tokens[$start]['nested_parenthesis']) === true || empty($this->tokens[$matchExpression]['nested_parenthesis']) === false && empty($this->tokens[$start]['nested_parenthesis']) === false && $this->tokens[$matchExpression]['nested_parenthesis'] === $this->tokens[$start]['nested_parenthesis'])) {
// Walk back to the previous match arrow (if it exists).
$lastComma = null;
$inNestedExpression = false;
for ($prevMatch = $start; $prevMatch > $this->tokens[$matchExpression]['scope_opener']; $prevMatch--) {
if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_MATCH_ARROW) {
break;
}
if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_COMMA) {
$lastComma = $prevMatch;
continue;
}
// Skip nested statements.
if (isset($this->tokens[$prevMatch]['bracket_opener']) === true && $prevMatch === $this->tokens[$prevMatch]['bracket_closer']) {
$prevMatch = $this->tokens[$prevMatch]['bracket_opener'];
continue;
}
if (isset($this->tokens[$prevMatch]['parenthesis_opener']) === true && $prevMatch === $this->tokens[$prevMatch]['parenthesis_closer']) {
$prevMatch = $this->tokens[$prevMatch]['parenthesis_opener'];
continue;
}
// Stop if we're _within_ a nested short array statement, which may contain comma's too.
// No need to deal with parentheses, those are handled above via the `nested_parenthesis` checks.
if (isset($this->tokens[$prevMatch]['bracket_opener']) === true && $this->tokens[$prevMatch]['bracket_closer'] > $start) {
$inNestedExpression = true;
break;
}
}
//end for
if ($inNestedExpression === false) {
// $prevMatch will now either be the scope opener or a match arrow.
// If it is the scope opener, go the first non-empty token after. $start will have been part of the first condition.
if ($prevMatch <= $this->tokens[$matchExpression]['scope_opener']) {
// We're before the arrow in the first case.
$next = $this->findNext(Tokens::$emptyTokens, $this->tokens[$matchExpression]['scope_opener'] + 1, null, true);
if ($next === false) {
// Shouldn't be possible.
return $start;
}
return $next;
}
// Okay, so we found a match arrow.
// If $start was part of the "next" condition, the last comma will be set.
// Otherwise, $start must have been part of a return expression.
if (isset($lastComma) === true && $lastComma > $prevMatch) {
$prevMatch = $lastComma;
}
// In both cases, go to the first non-empty token after.
$next = $this->findNext(Tokens::$emptyTokens, $prevMatch + 1, null, true);
if ($next === false) {
// Shouldn't be possible.
return $start;
}
return $next;
}
//end if
}
//end if
}
//end if
$lastNotEmpty = $start;
// If we are starting at a token that ends a scope block, skip to
// the start and continue from there.
// If we are starting at a token that ends a statement, skip this
// token so we find the true start of the statement.
while (isset($endTokens[$this->tokens[$start]['code']]) === true || isset($this->tokens[$start]['scope_condition']) === true && $start === $this->tokens[$start]['scope_closer']) {
if (isset($this->tokens[$start]['scope_condition']) === true) {
$start = $this->tokens[$start]['scope_condition'];
}
else {
$start--;
}
}
for ($i = $start; $i >= 0; $i--) {
if (isset($startTokens[$this->tokens[$i]['code']]) === true || isset($endTokens[$this->tokens[$i]['code']]) === true) {
// Found the end of the previous statement.
return $lastNotEmpty;
}
if (isset($this->tokens[$i]['scope_opener']) === true && $i === $this->tokens[$i]['scope_closer'] && $this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS && $this->tokens[$i]['code'] !== T_END_NOWDOC && $this->tokens[$i]['code'] !== T_END_HEREDOC && $this->tokens[$i]['code'] !== T_BREAK && $this->tokens[$i]['code'] !== T_RETURN && $this->tokens[$i]['code'] !== T_CONTINUE && $this->tokens[$i]['code'] !== T_THROW && $this->tokens[$i]['code'] !== T_EXIT) {
// Found the end of the previous scope block.
return $lastNotEmpty;
}
// Skip nested statements.
if (isset($this->tokens[$i]['bracket_opener']) === true && $i === $this->tokens[$i]['bracket_closer']) {
$i = $this->tokens[$i]['bracket_opener'];
}
else {
if (isset($this->tokens[$i]['parenthesis_opener']) === true && $i === $this->tokens[$i]['parenthesis_closer']) {
$i = $this->tokens[$i]['parenthesis_opener'];
}
else {
if ($this->tokens[$i]['code'] === T_CLOSE_USE_GROUP) {
$start = $this->findPrevious(T_OPEN_USE_GROUP, $i - 1);
if ($start !== false) {
$i = $start;
}
}
}
}
//end if
if (isset(Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) {
$lastNotEmpty = $i;
}
}
//end for
return 0;
}