Last active
February 17, 2016 18:44
-
-
Save gsherwood/8275236 to your computer and use it in GitHub Desktop.
Possible fix for bug #20151 : Problem handling "if(): ... else: ... endif;" syntax
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ git diff | |
diff --git a/CodeSniffer/File.php b/CodeSniffer/File.php | |
index f45e307..e629fed 100644 | |
--- a/CodeSniffer/File.php | |
+++ b/CodeSniffer/File.php | |
@@ -1446,7 +1446,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$i]['type']; | |
$content = str_replace($eolChar, '\n', $tokens[$i]['content']); | |
- echo "\tStart scope map at $i: $type => $content".PHP_EOL; | |
+ echo "\tStart scope map at $i:$type => $content".PHP_EOL; | |
} | |
$i = self::_recurseScopeMap( | |
@@ -1531,12 +1531,63 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", $depth); | |
- echo "=> Found semicolon before scope opener for $stackPtr ($type), bailing".PHP_EOL; | |
+ echo "=> Found semicolon before scope opener for $stackPtr:$type, bailing".PHP_EOL; | |
} | |
return $i; | |
} | |
+ if (in_array($tokenType, $tokenizer->scopeOpeners[$currType]['end']) === true | |
+ && $opener !== null | |
+ ) { | |
+ if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) { | |
+ // The last opening bracket must have been for a string | |
+ // offset or alike, so let's ignore it. | |
+ if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
+ echo str_repeat("\t", $depth); | |
+ echo '* finished ignoring curly brace *'.PHP_EOL; | |
+ } | |
+ | |
+ $ignore--; | |
+ continue; | |
+ } else if ($tokens[$opener]['code'] === T_OPEN_CURLY_BRACKET | |
+ && $tokenType !== T_CLOSE_CURLY_BRACKET | |
+ ) { | |
+ // The opener is a curly bracket so the closer must be a curly bracket as well. | |
+ // We ignore this closer to handle cases such as T_ELSE or T_ELSEIF being considered | |
+ // a closer of T_IF when it should not. | |
+ if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
+ $type = $tokens[$stackPtr]['type']; | |
+ echo str_repeat("\t", $depth); | |
+ echo "=> Ignoring non-culry scope closer for $stackPtr:$type".PHP_EOL; | |
+ } | |
+ } else { | |
+ if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
+ $type = $tokens[$stackPtr]['type']; | |
+ $closerType = $tokens[$i]['type']; | |
+ echo str_repeat("\t", $depth); | |
+ echo "=> Found scope closer ($i:$closerType) for $stackPtr:$type".PHP_EOL; | |
+ } | |
+ | |
+ foreach (array($stackPtr, $opener, $i) as $token) { | |
+ $tokens[$token]['scope_condition'] = $stackPtr; | |
+ $tokens[$token]['scope_opener'] = $opener; | |
+ $tokens[$token]['scope_closer'] = $i; | |
+ } | |
+ | |
+ if ($tokenizer->scopeOpeners[$tokens[$stackPtr]['code']]['shared'] === true) { | |
+ // As we are going back to where we started originally, restore | |
+ // the ignore value back to its original value. | |
+ $ignore = $originalIgnore; | |
+ return $opener; | |
+ } else if (isset($tokenizer->scopeOpeners[$tokenType]) === true) { | |
+ return ($i - 1); | |
+ } else { | |
+ return $i; | |
+ } | |
+ }//end if | |
+ }//end if | |
+ | |
// Is this an opening condition ? | |
if (isset($tokenizer->scopeOpeners[$tokenType]) === true) { | |
if ($opener === null) { | |
@@ -1545,7 +1596,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", $depth); | |
- echo "=> Couldn't find scope opener for $stackPtr ($type), bailing".PHP_EOL; | |
+ echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; | |
} | |
return $stackPtr; | |
@@ -1647,45 +1698,11 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", $depth); | |
- echo "=> Found scope opener for $stackPtr ($type)".PHP_EOL; | |
+ echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; | |
} | |
$opener = $i; | |
} | |
- } else if (in_array($tokenType, $tokenizer->scopeOpeners[$currType]['end']) === true | |
- && $opener !== null | |
- ) { | |
- if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) { | |
- // The last opening bracket must have been for a string | |
- // offset or alike, so let's ignore it. | |
- if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
- echo str_repeat("\t", $depth); | |
- echo '* finished ignoring curly brace *'.PHP_EOL; | |
- } | |
- | |
- $ignore--; | |
- } else { | |
- if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
- $type = $tokens[$stackPtr]['type']; | |
- echo str_repeat("\t", $depth); | |
- echo "=> Found scope closer for $stackPtr ($type)".PHP_EOL; | |
- } | |
- | |
- foreach (array($stackPtr, $opener, $i) as $token) { | |
- $tokens[$token]['scope_condition'] = $stackPtr; | |
- $tokens[$token]['scope_opener'] = $opener; | |
- $tokens[$token]['scope_closer'] = $i; | |
- } | |
- | |
- if ($tokenizer->scopeOpeners[$tokens[$stackPtr]['code']]['shared'] === true) { | |
- // As we are going back to where we started originally, restore | |
- // the ignore value back to its original value. | |
- $ignore = $originalIgnore; | |
- return $opener; | |
- } else { | |
- return $i; | |
- } | |
- }//end if | |
} else if ($tokenType === T_OPEN_PARENTHESIS) { | |
if (isset($tokens[$i]['parenthesis_owner']) === true) { | |
$owner = $tokens[$i]['parenthesis_owner']; | |
@@ -1736,13 +1753,13 @@ class PHP_CodeSniffer_File | |
$type = $tokens[$stackPtr]['type']; | |
$lines = ($tokens[$i]['line'] - $startLine); | |
echo str_repeat("\t", $depth); | |
- echo "=> Still looking for $stackPtr ($type) scope opener after $lines lines".PHP_EOL; | |
+ echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL; | |
} | |
} else { | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", $depth); | |
- echo "=> Couldn't find scope opener for $stackPtr ($type), bailing".PHP_EOL; | |
+ echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; | |
} | |
return $stackPtr; | |
@@ -1769,7 +1786,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", $depth); | |
- echo "=> Found (unexpected) scope closer for $stackPtr ($type)".PHP_EOL; | |
+ echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL; | |
} | |
foreach (array($stackPtr, $opener) as $token) { | |
@@ -1844,7 +1861,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "=> Found scope opener for $stackPtr ($type)".PHP_EOL; | |
+ echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; | |
} | |
$stackPtr = $tokens[$i]['scope_condition']; | |
@@ -1874,7 +1891,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$badToken]['type']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* shared closer, cleaning up $badToken ($type) *".PHP_EOL; | |
+ echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL; | |
} | |
for ($x = $tokens[$i]['scope_condition']; $x <= $i; $x++) { | |
@@ -1900,7 +1917,7 @@ class PHP_CodeSniffer_File | |
$newLevel = $tokens[$x]['level']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* cleaned $x ($type) *".PHP_EOL; | |
+ echo "* cleaned $x:$type *".PHP_EOL; | |
echo str_repeat("\t", ($level + 2)); | |
echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; | |
echo str_repeat("\t", ($level + 2)); | |
@@ -1912,7 +1929,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$badToken]['type']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* token $badToken ($type) removed from conditions array *".PHP_EOL; | |
+ echo "* token $badToken:$type removed from conditions array *".PHP_EOL; | |
} | |
unset ($openers[$lastOpener]); | |
@@ -1935,14 +1952,14 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$stackPtr]['type']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* token $stackPtr ($type) added to conditions array *".PHP_EOL; | |
+ echo "* token $stackPtr:$type added to conditions array *".PHP_EOL; | |
} | |
$lastOpener = $tokens[$i]['scope_opener']; | |
if ($lastOpener !== null) { | |
$openers[$lastOpener] = $lastOpener; | |
} | |
- } else if ($tokens[$i]['scope_closer'] === $i) { | |
+ } else if ($lastOpener !== null && $tokens[$lastOpener]['scope_closer'] === $i) { | |
foreach (array_reverse($openers) as $opener) { | |
if ($tokens[$opener]['scope_closer'] === $i) { | |
$oldOpener = array_pop($openers); | |
@@ -1956,7 +1973,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = $tokens[$oldOpener]['type']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "=> Found scope closer for $oldOpener ($type)".PHP_EOL; | |
+ echo "=> Found scope closer for $oldOpener:$type".PHP_EOL; | |
} | |
$oldCondition = array_pop($conditions); | |
@@ -1977,7 +1994,7 @@ class PHP_CodeSniffer_File | |
if (PHP_CODESNIFFER_VERBOSITY > 1) { | |
$type = token_name($oldCondition); | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* scope closer was bad, cleaning up $badToken ($type) *".PHP_EOL; | |
+ echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL; | |
} | |
for ($x = ($oldOpener + 1); $x <= $i; $x++) { | |
@@ -2003,7 +2020,7 @@ class PHP_CodeSniffer_File | |
$newLevel = $tokens[$x]['level']; | |
echo str_repeat("\t", ($level + 1)); | |
- echo "* cleaned $x ($type) *".PHP_EOL; | |
+ echo "* cleaned $x:$type *".PHP_EOL; | |
echo str_repeat("\t", ($level + 2)); | |
echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; | |
echo str_repeat("\t", ($level + 2)); | |
diff --git a/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.inc b/CodeSniffer/Standards/Generic/Tests | |
index bc0d4b6..918c2db 100644 | |
--- a/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.inc | |
+++ b/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.inc | |
@@ -39,4 +39,12 @@ foreach ($array as $element) : | |
echo 'hello'; | |
endforeach; | |
+if ($foo) : | |
+ echo 'true'; | |
+elseif ($something) : | |
+ echo 'foo'; | |
+else: | |
+ echo 'false'; | |
+endif; | |
+ | |
?> | |
diff --git a/CodeSniffer/Tokenizers/PHP.php b/CodeSniffer/Tokenizers/PHP.php | |
index a9da6de..6c92029 100644 | |
--- a/CodeSniffer/Tokenizers/PHP.php | |
+++ b/CodeSniffer/Tokenizers/PHP.php | |
@@ -45,10 +45,15 @@ class PHP_CodeSniffer_Tokenizers_PHP | |
'end' => array( | |
T_CLOSE_CURLY_BRACKET, | |
T_ENDIF, | |
+ T_ELSE, | |
+ T_ELSEIF, | |
), | |
'strict' => false, | |
'shared' => false, | |
- 'with' => array(), | |
+ 'with' => array( | |
+ T_ELSE, | |
+ T_ELSEIF, | |
+ ), | |
), | |
T_TRY => array( | |
'start' => array(T_OPEN_CURLY_BRACKET), | |
@@ -72,18 +77,38 @@ class PHP_CodeSniffer_Tokenizers_PHP | |
'with' => array(), | |
), | |
T_ELSE => array( | |
- 'start' => array(T_OPEN_CURLY_BRACKET), | |
- 'end' => array(T_CLOSE_CURLY_BRACKET), | |
+ 'start' => array( | |
+ T_OPEN_CURLY_BRACKET, | |
+ T_COLON, | |
+ ), | |
+ 'end' => array( | |
+ T_CLOSE_CURLY_BRACKET, | |
+ T_ENDIF, | |
+ ), | |
'strict' => false, | |
'shared' => false, | |
- 'with' => array(), | |
+ 'with' => array( | |
+ T_IF, | |
+ T_ELSEIF, | |
+ ), | |
), | |
T_ELSEIF => array( | |
- 'start' => array(T_OPEN_CURLY_BRACKET), | |
- 'end' => array(T_CLOSE_CURLY_BRACKET), | |
+ 'start' => array( | |
+ T_OPEN_CURLY_BRACKET, | |
+ T_COLON, | |
+ ), | |
+ 'end' => array( | |
+ T_CLOSE_CURLY_BRACKET, | |
+ T_ENDIF, | |
+ T_ELSE, | |
+ T_ELSEIF, | |
+ ), | |
'strict' => false, | |
'shared' => false, | |
- 'with' => array(), | |
+ 'with' => array( | |
+ T_IF, | |
+ T_ELSE, | |
+ ), | |
), | |
T_FOR => array( | |
'start' => array( |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, is this update usable from somewhere? Hitting false error "Expected 1 space after ELSE keyword; 0 found".