Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php error_reporting(E_ALL);
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt;
require __DIR__ . '/../vendor/autoload.php';
$lexer = new PhpParser\Lexer\Emulative([
'usedAttributes' => [
'comments', 'startLine', 'endLine',
'startFilePos', 'endFilePos',
]
]);
$parser = new PhpParser\Parser\Php7($lexer);
$visitor = new class extends PhpParser\NodeVisitorAbstract {
public $path = null;
public $code = null;
public function enterNode(PhpParser\Node $node) {
if (!$node instanceof Expr\MethodCall) {
return;
}
if (!$node->isMagic()) {
return;
}
$magicMethods = [
'__call' => [
1 => 'string',
2 => 'array',
0 => 'mixed',
],
'__callstatic' => [
1 => 'string',
2 => 'array',
0 => 'mixed',
],
'__clone' => [
0 => 'void'
],
'__debugInfo' => [
0 => 'array'
],
'__get' => [
1 => 'string',
0 => 'mixed',
],
'__isset' => [
1 => 'string',
0 => 'bool',
],
'__set' => [
1 => 'string',
2 => 'mixed',
0 => 'void',
],
'__serialize' => [
0 => 'array'
],
'__sleep' => [
0 => 'array'
],
'__set_state' => [
1 => 'array',
0 => 'mixed',
],
'__unserialize' => [
1 => 'array',
0 => 'void',
],
'__unset' => [
1 => 'string',
0 => 'void',
],
'__wakeup' => [
0 => 'void'
],
];
if (!isset($magicMethods[$node->name->toLowerString()])) {
return;
}
$argument = 0;
foreach ($node->getParams() as $param) {
$argument++;
if (!$param->type instanceof Node\Identifier) {
continue;
}
if ($magicMethods[$node->name->toLowerString()][$argument] === $param->type->toLowerString()) {
continue;
}
echo sprintf(
'wrong native type of argument %d of %s(): %s' ,
$argument,
$node->name->toLowerString(),
$param->type->toLowerString()
) . PHP_EOL;
$showPath = true;
}
if ($node->getReturnType() instanceof Node\Identifier) {
if ($magicMethods[$node->name->toLowerString()][0] !== $node->getReturnType()->toLowerString()) {
echo sprintf('wrong native return type of %s(): %s', $node->name->toLowerString(), $node->getReturnType()->toLowerString()) . PHP_EOL;
$showPath = true;
}
}
if ($showPath ?? false) {
echo $this->path . ":" . $node->getStartLine() . PHP_EOL . PHP_EOL;
}
}
};
$traverser = new PhpParser\NodeTraverser;
$traverser->addVisitor($visitor);
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(__DIR__ . '/sources'),
RecursiveIteratorIterator::LEAVES_ONLY
);
$i = 0;
foreach ($it as $f) {
$path = $f->getPathName();
if (!preg_match('/\.php$/', $path)) {
continue;
}
$code = file_get_contents($path);
try {
$stmts = $parser->parse($code);
} catch (PhpParser\Error $e) {
// echo $path . PHP_EOL;
// echo "Parse error: " . $e->getMessage() . PHP_EOL;
continue;
}
$visitor->path = $path;
$visitor->code = $code;
$traverser->traverse($stmts);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment