mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Read more from config and fix switch snafu
This commit is contained in:
parent
4edd11cd44
commit
46005ddd29
7
src/CodeInspector/CodeException.php
Normal file
7
src/CodeInspector/CodeException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace CodeInspector;
|
||||
|
||||
class CodeException extends \Exception {
|
||||
|
||||
}
|
@ -11,49 +11,66 @@ class Config
|
||||
{
|
||||
protected static $_config;
|
||||
|
||||
public $stopOnError = true;
|
||||
public $useDocblockReturnType = false;
|
||||
public $stop_on_error = true;
|
||||
public $use_docblock_return_type = false;
|
||||
|
||||
protected $errorHandlers;
|
||||
protected $inspect_files;
|
||||
|
||||
protected $inspectFiles;
|
||||
protected $base_dir;
|
||||
|
||||
protected $fileExtensions = ['php'];
|
||||
protected $file_extensions = ['php'];
|
||||
|
||||
protected $issue_handlers = [];
|
||||
|
||||
protected $mock_classes = [];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
self::$_config = $this;
|
||||
}
|
||||
|
||||
public static function loadFromXML($file_contents)
|
||||
public static function loadFromXML($file_name)
|
||||
{
|
||||
$config = new self();
|
||||
|
||||
$file_contents = file_get_contents($file_name);
|
||||
|
||||
$config->base_dir = dirname($file_name) . '/';
|
||||
|
||||
$config_xml = new SimpleXMLElement($file_contents);
|
||||
|
||||
if (isset($config_xml['stopOnError'])) {
|
||||
$config->stopOnError = (bool) $config_xml['stopOnError'];
|
||||
$config->stop_on_error = (bool) $config_xml['stopOnError'];
|
||||
}
|
||||
|
||||
if (isset($config_xml['useDocblockReturnType'])) {
|
||||
$config->stopOnError = (bool) $config_xml['useDocblockReturnType'];
|
||||
$config->use_docblock_return_type = (bool) $config_xml['useDocblockReturnType'];
|
||||
}
|
||||
|
||||
if (isset($config_xml->inspectFiles)) {
|
||||
$config->inspectFiles = new FileFilter($config_xml->inspectFiles);
|
||||
$config->inspect_files = FileFilter::loadFromXML($config_xml->inspectFiles, true);
|
||||
}
|
||||
|
||||
if (isset($config_xml->fileExtensions)) {
|
||||
$config->fileExtensions = [];
|
||||
if ($config_xml->fileExtensions->extension instanceof SimpleXMLElement) {
|
||||
$config->fileExtensions[] = preg_replace('/^.?/', '', $config_xml->fileExtensions->extension);
|
||||
}
|
||||
else {
|
||||
$config->file_extensions = [];
|
||||
|
||||
foreach ($config_xml->fileExtensions->extension as $extension) {
|
||||
$config->fileExtensions[] = preg_replace('/^.?/', '', $extension);
|
||||
$config->file_extensions[] = preg_replace('/^\.?/', '', $extension['name']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config_xml->mockClasses) && isset($config_xml->mockClasses->class)) {
|
||||
foreach ($config_xml->mockClasses->class as $mock_class) {
|
||||
$config->mock_classes[] = $mock_class['name'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config_xml->issueHandler)) {
|
||||
foreach ($config_xml->issueHandler->children() as $key => $issue_handler) {
|
||||
if (isset($issue_handler->excludeFiles)) {
|
||||
$config->issue_handlers[$key] = FileFilter::loadFromXML($issue_handler->excludeFiles, false);
|
||||
}
|
||||
}
|
||||
$config->inspectFiles = new FileFilter($config_xml->inspectFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +88,14 @@ class Config
|
||||
|
||||
public function excludeIssueInFile($issue_type, $file_name)
|
||||
{
|
||||
$issue_type = array_pop(explode('\\', $issue_type));
|
||||
$file_name = preg_replace('/^' . preg_quote($this->base_dir, '/') . '/', '', $file_name);
|
||||
|
||||
if (!isset($this->issue_handlers[$issue_type])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !$this->issue_handlers[$issue_type]->allows($file_name);
|
||||
}
|
||||
|
||||
public function doesInheritVariables($file_name)
|
||||
@ -81,16 +105,16 @@ class Config
|
||||
|
||||
public function getFilesToCheck()
|
||||
{
|
||||
$files = $this->inspectFiles->getIncludeFiles();
|
||||
$files = $this->inspect_files->getIncludeFiles();
|
||||
|
||||
foreach ($this->inspectFiles->getIncludeFolders() as $folder) {
|
||||
foreach ($this->inspect_files->getIncludeDirs() as $dir) {
|
||||
/** @var RecursiveDirectoryIterator */
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder));
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->base_dir . '/' . $dir));
|
||||
$iterator->rewind();
|
||||
|
||||
while ($iterator->valid()) {
|
||||
if (!$iterator->isDot()) {
|
||||
if (in_array($iterator->getExtension(), $this->extensions)) {
|
||||
if (in_array($iterator->getExtension(), $this->file_extensions)) {
|
||||
$files[] = $iterator->getRealPath();
|
||||
}
|
||||
}
|
||||
@ -101,4 +125,9 @@ class Config
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
public function getMockClasses()
|
||||
{
|
||||
return $this->mock_classes;
|
||||
}
|
||||
}
|
||||
|
@ -39,50 +39,30 @@ class FileFilter
|
||||
$filter->inclusive = true;
|
||||
|
||||
if ($e->directory) {
|
||||
if ($e->directory instanceof \SimpleXMLElement) {
|
||||
$filter->include_dirs[] = self::slashify($e->directory['name']);
|
||||
}
|
||||
else {
|
||||
foreach ($e->directory as $directory) {
|
||||
$filter->include_dirs[] = self::slashify($directory['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($e->file) {
|
||||
if ($e->file instanceof \SimpleXMLElement) {
|
||||
$filter->include_files[] = $e->file['name'];
|
||||
}
|
||||
else {
|
||||
foreach ($e->file as $file) {
|
||||
$filter->include_files[] = $file['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($e->directory) {
|
||||
if ($e->directory instanceof \SimpleXMLElement) {
|
||||
$filter->exclude_dirs[] = self::slashify($e->directory['name']);
|
||||
}
|
||||
else {
|
||||
foreach ($e->directory as $directory) {
|
||||
$filter->exclude_dirs[] = self::slashify($directory['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($e->file) {
|
||||
if ($e->file instanceof \SimpleXMLElement) {
|
||||
$filter->exclude_files[] = $e->file['name'];
|
||||
}
|
||||
else {
|
||||
foreach ($e->file as $file) {
|
||||
$filter->exclude_files[] = $file['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
@ -96,7 +76,7 @@ class FileFilter
|
||||
{
|
||||
if ($this->inclusive) {
|
||||
foreach ($this->include_dirs as $include_dir) {
|
||||
if (strpos($file_name, $include_dir) !== false) {
|
||||
if (strpos($file_name, $include_dir) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -110,7 +90,7 @@ class FileFilter
|
||||
|
||||
// exclusive
|
||||
foreach ($this->exclude_dirs as $exclude_dir) {
|
||||
if (strpos($file_name, $exclude_dir) !== false) {
|
||||
if (strpos($file_name, $exclude_dir) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -121,4 +101,24 @@ class FileFilter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getIncludeDirs()
|
||||
{
|
||||
return $this->include_dirs;
|
||||
}
|
||||
|
||||
public function getExcludeDirs()
|
||||
{
|
||||
return $this->exclude_dirs;
|
||||
}
|
||||
|
||||
public function getIncludeFiles()
|
||||
{
|
||||
return $this->include_files;
|
||||
}
|
||||
|
||||
public function getExcludeFiles()
|
||||
{
|
||||
return $this->exclude_files;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ class ExceptionHandler
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
|
||||
if ($config->stopOnError) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
if ($config->excludeIssueInFile(get_class($e), $e->getFileName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($config->stop_on_error) {
|
||||
throw new CodeException($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
namespace CodeInspector\Issue;
|
||||
|
||||
class PossiblyUndefinedVariableError extends CodeError
|
||||
class PossiblyUndefinedVariableNotice extends CodeIssue
|
||||
{
|
||||
}
|
||||
|
@ -13,26 +13,29 @@ class ScopeChecker
|
||||
* @param bool $check_continue - also looks for a continue
|
||||
* @return bool
|
||||
*/
|
||||
public static function doesLeaveBlock(array $stmts, $check_continue = true)
|
||||
public static function doesLeaveBlock(array $stmts, $check_continue = true, $check_break = true)
|
||||
{
|
||||
for ($i = count($stmts) - 1; $i >= 0; $i--) {
|
||||
$stmt = $stmts[$i];
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Return_ ||
|
||||
$stmt instanceof PhpParser\Node\Stmt\Throw_ ||
|
||||
($check_continue && ($stmt instanceof PhpParser\Node\Stmt\Continue_ || $stmt instanceof PhpParser\Node\Stmt\Break_))) {
|
||||
($check_continue && $stmt instanceof PhpParser\Node\Stmt\Continue_) ||
|
||||
($check_break && $stmt instanceof PhpParser\Node\Stmt\Break_)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\If_) {
|
||||
if ($stmt->else && self::doesLeaveBlock($stmt->stmts, $check_continue) && self::doesLeaveBlock($stmt->else->stmts, $check_continue)) {
|
||||
if ($stmt->else && self::doesLeaveBlock($stmt->stmts, $check_continue, $check_break) &&
|
||||
self::doesLeaveBlock($stmt->else->stmts, $check_continue, $check_break)) {
|
||||
|
||||
if (empty($stmt->elseifs)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($stmt->elseifs as $elseif) {
|
||||
if (!self::doesLeaveBlock($elseif->stmts, $check_continue)) {
|
||||
if (!self::doesLeaveBlock($elseif->stmts, $check_continue, $check_break)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class StatementsChecker
|
||||
$this->_checkThrow($stmt, $vars_in_scope, $vars_possibly_in_scope);
|
||||
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Switch_) {
|
||||
$this->_checkSwitch($stmt, $vars_in_scope, $vars_possibly_in_scope);
|
||||
$this->_checkSwitch($stmt, $vars_in_scope, $vars_possibly_in_scope, $for_vars_possibly_in_scope);
|
||||
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Break_) {
|
||||
// do nothing
|
||||
@ -252,7 +252,7 @@ class StatementsChecker
|
||||
$post_type_assertions = [];
|
||||
|
||||
if (count($stmt->stmts)) {
|
||||
$has_leaving_statments = ScopeChecker::doesLeaveBlock($stmt->stmts, true);
|
||||
$has_leaving_statments = ScopeChecker::doesLeaveBlock($stmt->stmts, true, true);
|
||||
|
||||
if (!$has_leaving_statments) {
|
||||
$new_vars = array_diff_key($if_vars, $vars_in_scope);
|
||||
@ -278,7 +278,7 @@ class StatementsChecker
|
||||
$post_type_assertions = $negated_types;
|
||||
}
|
||||
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($stmt->stmts, false);
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($stmt->stmts, false, false);
|
||||
|
||||
if (!$has_ending_statments) {
|
||||
$vars = array_diff_key($if_vars_possibly_in_scope, $vars_possibly_in_scope);
|
||||
@ -327,7 +327,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
if (count($elseif->stmts)) {
|
||||
$has_leaving_statements = ScopeChecker::doesLeaveBlock($elseif->stmts, true);
|
||||
$has_leaving_statements = ScopeChecker::doesLeaveBlock($elseif->stmts, true, true);
|
||||
|
||||
if (!$has_leaving_statements) {
|
||||
$elseif_redefined_vars = [];
|
||||
@ -384,7 +384,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
// has a return/throw at end
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($elseif->stmts, false);
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($elseif->stmts, false, false);
|
||||
|
||||
if (!$has_ending_statments) {
|
||||
$vars = array_diff_key($elseif_vars_possibly_in_scope, $vars_possibly_in_scope);
|
||||
@ -421,7 +421,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
if (count($stmt->else->stmts)) {
|
||||
$has_leaving_statements = ScopeChecker::doesLeaveBlock($stmt->else->stmts, true);
|
||||
$has_leaving_statements = ScopeChecker::doesLeaveBlock($stmt->else->stmts, true, true);
|
||||
|
||||
// if it doesn't end in a return
|
||||
if (!$has_leaving_statements) {
|
||||
@ -470,7 +470,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
// has a return/throw at end
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($stmt->else->stmts, false);
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($stmt->else->stmts, false, false);
|
||||
|
||||
if (!$has_ending_statments) {
|
||||
$vars = array_diff_key($else_vars_possibly_in_scope, $vars_possibly_in_scope);
|
||||
@ -502,7 +502,7 @@ class StatementsChecker
|
||||
* let's get the type assertions from the condition if it's a terminator
|
||||
* so that we can negate them going forward
|
||||
*/
|
||||
if (ScopeChecker::doesLeaveBlock($stmt->stmts, false) && $negated_if_types) {
|
||||
if (ScopeChecker::doesLeaveBlock($stmt->stmts, false, false) && $negated_if_types) {
|
||||
$vars_in_scope_reconciled = TypeChecker::reconcileTypes($negated_if_types, $vars_in_scope, true, $this->_file_name, $stmt->getLine());
|
||||
|
||||
if ($vars_in_scope_reconciled === false) {
|
||||
@ -620,7 +620,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @return false|null
|
||||
*/
|
||||
protected function _checkExpression(PhpParser\Node\Expr $stmt, array &$vars_in_scope, array &$vars_possibly_in_scope = [])
|
||||
{
|
||||
@ -921,7 +921,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @return false|null
|
||||
*/
|
||||
protected function _checkVariable(PhpParser\Node\Expr\Variable $stmt, array &$vars_in_scope, array &$vars_possibly_in_scope, $method_id = null, $argument_offset = -1)
|
||||
{
|
||||
@ -1159,7 +1159,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
foreach ($stmt->cond as $condition) {
|
||||
if ($this->_checkCondition($init, $for_vars, $vars_possibly_in_scope) === false) {
|
||||
if ($this->_checkCondition($condition, $for_vars, $vars_possibly_in_scope) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2019,7 +2019,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @return null|false
|
||||
*/
|
||||
protected function _checkStaticPropertyFetch(PhpParser\Node\Expr\StaticPropertyFetch $stmt, array &$vars_in_scope, array &$vars_possibly_in_scope)
|
||||
{
|
||||
@ -2144,7 +2144,7 @@ class StatementsChecker
|
||||
return $this->_checkExpression($stmt->expr, $vars_in_scope, $vars_possibly_in_scope);
|
||||
}
|
||||
|
||||
protected function _checkSwitch(PhpParser\Node\Stmt\Switch_ $stmt, array &$vars_in_scope, array &$vars_possibly_in_scope)
|
||||
protected function _checkSwitch(PhpParser\Node\Stmt\Switch_ $stmt, array &$vars_in_scope, array &$vars_possibly_in_scope, array &$for_vars_possibly_in_scope)
|
||||
{
|
||||
$type_candidate_var = null;
|
||||
|
||||
@ -2196,7 +2196,19 @@ class StatementsChecker
|
||||
|
||||
$last_stmt = $case->stmts[count($case->stmts) - 1];
|
||||
|
||||
if (!($last_stmt instanceof PhpParser\Node\Stmt\Return_)) {
|
||||
// has a return/throw at end
|
||||
$has_ending_statments = ScopeChecker::doesLeaveBlock($case->stmts, false, false);
|
||||
|
||||
if (!$has_ending_statments) {
|
||||
$vars = array_diff_key($case_vars_possibly_in_scope, $vars_possibly_in_scope);
|
||||
|
||||
$has_leaving_statements = ScopeChecker::doesLeaveBlock($case->stmts, true, false);
|
||||
|
||||
// if we're leaving this block, add vars to outer for loop scope
|
||||
if ($has_leaving_statements) {
|
||||
$for_vars_possibly_in_scope = array_merge($vars, $for_vars_possibly_in_scope);
|
||||
}
|
||||
else {
|
||||
$case_redefined_vars = [];
|
||||
|
||||
foreach ($old_case_vars as $case_var => $type) {
|
||||
@ -2237,13 +2249,15 @@ class StatementsChecker
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_candidate_var && ($last_stmt instanceof PhpParser\Node\Stmt\Break_ || $last_stmt instanceof PhpParser\Node\Stmt\Return_)) {
|
||||
$case_types = [];
|
||||
}
|
||||
|
||||
// only update vars if there is a default
|
||||
if ($case->cond === null && !($last_stmt instanceof PhpParser\Node\Stmt\Return_)) {
|
||||
// if that default has a throw/return/continue, that should be handled above
|
||||
if ($case->cond === null) {
|
||||
if ($new_vars_in_scope) {
|
||||
$vars_in_scope = array_merge($vars_in_scope, $new_vars_in_scope);
|
||||
}
|
||||
@ -2436,7 +2450,7 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @return false|null
|
||||
*/
|
||||
public function _checkFunctionExists($method_id, $stmt)
|
||||
{
|
||||
@ -2789,7 +2803,7 @@ class StatementsChecker
|
||||
|
||||
public static function isMock($absolute_class)
|
||||
{
|
||||
return in_array($absolute_class, self::$_mock_interfaces);
|
||||
return in_array($absolute_class, Config::getInstance()->getMockClasses());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodCall()
|
||||
{
|
||||
@ -123,7 +123,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodCallWithThis()
|
||||
{
|
||||
@ -201,7 +201,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithWrongIfGuard()
|
||||
{
|
||||
@ -272,7 +272,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithWrongBooleanIfGuard()
|
||||
{
|
||||
@ -397,7 +397,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithWrongIfGuardBefore()
|
||||
{
|
||||
@ -450,7 +450,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithWrongBooleanIfGuardBefore()
|
||||
{
|
||||
@ -503,7 +503,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithGuardedNestedIncompleteRedefinition()
|
||||
{
|
||||
@ -668,7 +668,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testNullableMethodWithGuardedNestedRedefinitionWithUselessElseReturn()
|
||||
{
|
||||
@ -887,7 +887,7 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException CodeInspector\Exception\CodeException
|
||||
* @expectedException CodeInspector\CodeException
|
||||
*/
|
||||
public function testVariableReassignmentInIfWithOutsideCall()
|
||||
{
|
||||
@ -1004,4 +1004,30 @@ class TypeTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertSame('mixed', $return_stmt->returnType);
|
||||
}
|
||||
|
||||
public function testSwitchVariableWithContinue()
|
||||
{
|
||||
$stmts = self::$_parser->parse('<?php
|
||||
class B {
|
||||
public function bar() {
|
||||
foreach ([\'a\', \'b\', \'c\'] as $letter) {
|
||||
switch ($letter) {
|
||||
case \'a\':
|
||||
$foo = 1;
|
||||
break;
|
||||
case \'b\':
|
||||
$foo = 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
$moo = $foo;
|
||||
}
|
||||
}
|
||||
}');
|
||||
|
||||
$file_checker = new \CodeInspector\FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user