Skip to content
Permalink
Browse files

Add better return type provider for PDO statement

Fixes #2529
  • Loading branch information
muglug committed Dec 30, 2019
1 parent 4444104 commit 53a2f77d00a1c774d65bcfd4cfaa2a2b61280a8d
@@ -37,6 +37,7 @@ public function __construct()

$this->registerClass(ReturnTypeProvider\DomNodeAppendChild::class);
$this->registerClass(ReturnTypeProvider\SimpleXmlElementAsXml::class);
$this->registerClass(ReturnTypeProvider\PdoStatementReturnTypeProvider::class);
}

/**
@@ -0,0 +1,46 @@
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;

use PhpParser;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\StatementsSource;
use Psalm\Type;

class PdoStatementReturnTypeProvider implements \Psalm\Plugin\Hook\MethodReturnTypeProviderInterface
{
public static function getClassLikeNames() : array
{
return ['PDOStatement'];
}

/**
* @param array<PhpParser\Node\Arg> $call_args
*
* @return ?Type\Union
*/
public static function getMethodReturnType(
StatementsSource $source,
string $fq_classlike_name,
string $method_name_lowercase,
array $call_args,
Context $context,
CodeLocation $code_location,
array $template_type_parameters = null,
string $called_fq_classlike_name = null,
string $called_method_name_lowercase = null
) {
if ($method_name_lowercase === 'fetch'
&& \class_exists('PDO')
&& isset($call_args[0])
&& ($first_arg_type = $source->getNodeTypeProvider()->getType($call_args[0]->value))
&& $first_arg_type->isSingleIntLiteral()
) {
$value = $first_arg_type->getSingleIntLiteral()->value;

if ($value === \PDO::FETCH_ASSOC) {
return Type::getArray();
}
}
}
}
@@ -426,6 +426,13 @@ function foo(string $foo): string {
return $foo;
}'
],
'pdoStatementFetchAssoc' => [
'<?php
$p = new \PDO("sqlite:::memory:");
$sth = $p->prepare("SELECT 1");
$sth->execute();
while (($row = $sth->fetch(\PDO::FETCH_ASSOC)) !== false) {}'
],
];
}

0 comments on commit 53a2f77

Please sign in to comment.
You can’t perform that action at this time.