1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix #699 - prevent stubs from overriding known functions

This commit is contained in:
Matt Brown 2018-04-27 15:00:22 -04:00
parent 383f706d6b
commit 6b3759a266
4 changed files with 75 additions and 2 deletions

View File

@ -514,6 +514,28 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
$this->file_storage->declaring_constants[$const->name->name] = $this->file_path;
}
}
} elseif ($this->codebase->register_global_functions && $node instanceof PhpParser\Node\Stmt\If_) {
if ($node->cond instanceof PhpParser\Node\Expr\BooleanNot) {
if ($node->cond->expr instanceof PhpParser\Node\Expr\FuncCall
&& $node->cond->expr->name instanceof PhpParser\Node\Name
) {
if ($node->cond->expr->name->parts === ['function_exists']
&& isset($node->cond->expr->args[0])
&& $node->cond->expr->args[0]->value instanceof PhpParser\Node\Scalar\String_
&& function_exists($node->cond->expr->args[0]->value->value)
) {
return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
if ($node->cond->expr->name->parts === ['class_exists']
&& isset($node->cond->expr->args[0])
&& $node->cond->expr->args[0]->value instanceof PhpParser\Node\Scalar\String_
&& class_exists($node->cond->expr->args[0]->value->value, false)
) {
return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
}
}
}
}

View File

@ -894,7 +894,7 @@ class AnnotationTest extends TestCase
$arr["a"]()',
],
'magicMethodAnnotation' => [
'magicMethodValidAnnotations' => [
'<?php
class Parent {
public function __call() {}
@ -915,6 +915,7 @@ class AnnotationTest extends TestCase
$a = $child->getString();
$child->setInteger(4);
/** @psalm-suppress MixedAssignment */
$b = $child->setString(5);
$c = $child->getBool("hello");
$d = $child->getArray();
@ -927,7 +928,6 @@ class AnnotationTest extends TestCase
'$d' => 'array<mixed, string|int>',
'$e' => 'callable():string',
],
'error_levels' => ['MixedAssignment'],
],
];
}

View File

@ -19,6 +19,14 @@ class ConfigTest extends TestCase
public static function setUpBeforeClass()
{
self::$config = new TestConfig();
if (!defined('PSALM_VERSION')) {
define('PSALM_VERSION', '2.0.0');
}
if (!defined('PHP_PARSER_VERSION')) {
define('PHP_PARSER_VERSION', '4.0.0');
}
}
/**
@ -437,6 +445,38 @@ class ConfigTest extends TestCase
$this->analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testPolyfilledFunction()
{
$this->project_checker = $this->getProjectCheckerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'<?xml version="1.0"?>
<psalm>
<projectFiles>
<directory name="src" />
</projectFiles>
<stubs>
<file name="tests/stubs/polyfill.php" />
</stubs>
</psalm>'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'<?php
$a = random_bytes(16);'
);
$this->analyzeFile($file_path, new Context());
}
/**
* @return void
*/

11
tests/stubs/polyfill.php Normal file
View File

@ -0,0 +1,11 @@
<?php
if (!function_exists("random_bytes")) {
/**
* @param int $bytes
* @return void
*/
function random_bytes($bytes)
{
throw new \Exception("bad");
}
}