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

View File

@ -19,6 +19,14 @@ class ConfigTest extends TestCase
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
self::$config = new TestConfig(); 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()); $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 * @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");
}
}