mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Skip conditional includes when registering autoload files (#4967)
This should allow analysis of forward-compatible polyfills used in codebases targeting older PHP versions. The following previously problematic polyfills should now emit no parse errors: * `symfony/polyfill-ctype` * `symfony/polyfill-intl-grapheme` * `symfony/polyfill-intl-normalizer` * `symfony/polyfill-mbstring` The pattern that is now works as intended looks like this: ```php if (\PHP_VERSION_ID >= 80000) { require __DIR__ . '/bootstrap80.php'; return; } ``` Previously Psalm would scan the required file even when codebase targeted older PHP versions, and would emit parse errors when that file contained PHP 8 syntax. Fixes #4961 and #4965
This commit is contained in:
parent
d9999b575d
commit
9ce329c866
@ -6,6 +6,10 @@ use function function_exists;
|
||||
use function implode;
|
||||
use function interface_exists;
|
||||
use PhpParser;
|
||||
use PhpParser\ConstExprEvaluationException;
|
||||
use PhpParser\ConstExprEvaluator;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use Psalm\Aliases;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
|
||||
@ -236,6 +240,39 @@ class ExpressionResolver
|
||||
return $enter_conditional_left !== false || $enter_conditional_right !== false;
|
||||
}
|
||||
|
||||
if ($codebase->register_autoload_files) {
|
||||
if ((
|
||||
$expr instanceof PhpParser\Node\Expr\BinaryOp\GreaterOrEqual
|
||||
|| $expr instanceof PhpParser\Node\Expr\BinaryOp\Greater
|
||||
|| $expr instanceof PhpParser\Node\Expr\BinaryOp\SmallerOrEqual
|
||||
|| $expr instanceof PhpParser\Node\Expr\BinaryOp\Smaller
|
||||
) && (
|
||||
(
|
||||
$expr->left instanceof PhpParser\Node\Expr\ConstFetch
|
||||
&& $expr->left->name->parts === ['PHP_VERSION_ID']
|
||||
&& $expr->right instanceof PhpParser\Node\Scalar\LNumber
|
||||
) || (
|
||||
$expr->right instanceof PhpParser\Node\Expr\ConstFetch
|
||||
&& $expr->right->name->parts === ['PHP_VERSION_ID']
|
||||
&& $expr->left instanceof PhpParser\Node\Scalar\LNumber
|
||||
)
|
||||
)
|
||||
) {
|
||||
$php_version_id = $codebase->php_major_version * 10000 + $codebase->php_minor_version * 100;
|
||||
$evaluator = new ConstExprEvaluator(function (Expr $expr) use ($php_version_id) {
|
||||
if ($expr instanceof ConstFetch && $expr->name->parts === ['PHP_VERSION_ID']) {
|
||||
return $php_version_id;
|
||||
}
|
||||
throw new ConstExprEvaluationException('unexpected');
|
||||
});
|
||||
try {
|
||||
return (bool) $evaluator->evaluateSilently($expr);
|
||||
} catch (ConstExprEvaluationException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$expr instanceof PhpParser\Node\Expr\FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class ExpressionScanner
|
||||
?FunctionLikeStorage $functionlike_storage,
|
||||
?int $skip_if_descendants
|
||||
) : void {
|
||||
if ($node instanceof PhpParser\Node\Expr\Include_) {
|
||||
if ($node instanceof PhpParser\Node\Expr\Include_ && !$skip_if_descendants) {
|
||||
self::visitInclude(
|
||||
$codebase,
|
||||
$file_storage,
|
||||
|
Loading…
Reference in New Issue
Block a user