From d315822bfa68a0fd35ae6c61bbe08ebab8572761 Mon Sep 17 00:00:00 2001 From: Philip Hofstetter Date: Tue, 25 Feb 2020 13:40:46 +0100 Subject: [PATCH] make skipping of checks after invalid includes configurable as suggested in the PR it's best to make the setting configurable. In order not to break existing installations, we default to keeping the old behaviour, but in a later version of psalm, we might change the default. --- config.xsd | 1 + docs/running_psalm/configuration.md | 11 ++++++++++ src/Psalm/Config.php | 6 ++++++ .../Statements/Expression/IncludeAnalyzer.php | 11 ++++++++++ tests/IncludeTest.php | 21 +++++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/config.xsd b/config.xsd index 2668b8252..3083e5931 100644 --- a/config.xsd +++ b/config.xsd @@ -68,6 +68,7 @@ + diff --git a/docs/running_psalm/configuration.md b/docs/running_psalm/configuration.md index 4288cc77c..9fae1d4de 100644 --- a/docs/running_psalm/configuration.md +++ b/docs/running_psalm/configuration.md @@ -275,6 +275,17 @@ Set the php version psalm should assume when checking and/or fixing the project. This can be overridden on the command-line using the `--php-version=` flag which takes the highest precedence over both the `phpVersion` setting and the version derived from `composer.json`. +#### skipChecksOnUnresolvableIncludes +```xml + +``` + +When `true`, Psalm will skip checking classes, variables and functions after it comes across an `include` or `require` it cannot resolve. This allows code to reference functions and classes unknown to Psalm. + +For backwards compatibility, this defaults to `true`, but if you do not rely on dynamically generated includes to cause classes otherwise unknown to psalm to come into existence, it's recommended you set this to `false` in order to reliably detect errors that would be fatal to PHP at runtime. + ### Running Psalm #### autoloader diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 2e3a8f3d4..7ac577b48 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -291,6 +291,11 @@ class Config */ public $use_phpdoc_property_without_magic_or_parent = false; + /** + * @var bool + */ + public $skip_checks_on_unresolvable_includes = true; + /** * @var bool */ @@ -765,6 +770,7 @@ class Config 'ensureArrayStringOffsetsExist' => 'ensure_array_string_offsets_exist', 'ensureArrayIntOffsetsExist' => 'ensure_array_int_offsets_exist', 'reportMixedIssues' => 'show_mixed_issues', + 'skipChecksOnUnresolvableIncludes' => 'skip_checks_on_unresolvable_includes' ]; foreach ($booleanAttributes as $xmlName => $internalName) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php index 0a452364a..f08f69079 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php @@ -160,6 +160,11 @@ class IncludeAnalyzer $global_context ); } catch (\Psalm\Exception\UnpreparedAnalysisException $e) { + if ($config->skip_checks_on_unresolvable_includes) { + $context->check_classes = false; + $context->check_variables = false; + $context->check_functions = false; + } } foreach ($include_file_analyzer->getRequiredFilePaths() as $required_file_path) { @@ -200,6 +205,12 @@ class IncludeAnalyzer } } + if ($config->skip_checks_on_unresolvable_includes) { + $context->check_classes = false; + $context->check_variables = false; + $context->check_functions = false; + } + return null; } diff --git a/tests/IncludeTest.php b/tests/IncludeTest.php index 3c7a0d3c9..d63a99639 100644 --- a/tests/IncludeTest.php +++ b/tests/IncludeTest.php @@ -37,6 +37,7 @@ class IncludeTest extends TestCase } $config = $codebase->config; + $config->skip_checks_on_unresolvable_includes = true; foreach ($error_levels as $error_level) { $config->setCustomErrorLevel($error_level, \Psalm\Config::REPORT_SUPPRESS); @@ -83,6 +84,7 @@ class IncludeTest extends TestCase } $config = $codebase->config; + $config->skip_checks_on_unresolvable_includes = false; $this->expectException(\Psalm\Exception\CodeException::class); $this->expectExceptionMessageRegExp('/\b' . preg_quote($error_message, '/') . '\b/'); @@ -569,6 +571,25 @@ class IncludeTest extends TestCase getcwd() . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'b' . DIRECTORY_SEPARATOR . 'c' . DIRECTORY_SEPARATOR . 'd' . DIRECTORY_SEPARATOR . 'script.php', ], ], + 'undefinedMethodAfterInvalidRequire' => [ + 'files' => [ + getcwd() . DIRECTORY_SEPARATOR . 'file2.php' => ' ' [ + getcwd() . DIRECTORY_SEPARATOR . 'file2.php', + ], + ], + ]; }