Skip to content

Instantly share code, notes, and snippets.

@gsherwood
Last active February 17, 2016 18:44
Show Gist options
  • Save gsherwood/8275236 to your computer and use it in GitHub Desktop.
Save gsherwood/8275236 to your computer and use it in GitHub Desktop.
Possible fix for bug #20151 : Problem handling "if(): ... else: ... endif;" syntax
$ 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(
@u01jmg3
Copy link

u01jmg3 commented Feb 17, 2016

Hi, is this update usable from somewhere? Hitting false error "Expected 1 space after ELSE keyword; 0 found".

if(CONSTANT === true):
    $x = '1';
else:
    $x = '2';
endif;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment