Skip to content
Permalink
Browse files

Add better handling for non-edge-case function calls

  • Loading branch information...
muglug committed Apr 11, 2019
1 parent cadee4d commit be5a262deb619acc0d64f3826fb73d48fb383ce8
@@ -204,30 +204,18 @@ private static function writeToFile(
) {
$baselineDoc = new \DOMDocument('1.0', 'UTF-8');
$filesNode = $baselineDoc->createElement('files');
if (!$filesNode) {
return;
}
foreach ($groupedIssues as $file => $issueTypes) {
$fileNode = $baselineDoc->createElement('file');
if (!$fileNode) {
continue;
}
$fileNode->setAttribute('src', $file);
foreach ($issueTypes as $issueType => $existingIssueType) {
$issueNode = $baselineDoc->createElement($issueType);
if (!$issueNode) {
continue;
}
$issueNode->setAttribute('occurrences', (string)$existingIssueType['o']);
foreach ($existingIssueType['s'] as $selection) {
$codeNode = $baselineDoc->createElement('code');
if (!$codeNode) {
continue;
}
$codeNode->textContent = $selection;
$issueNode->appendChild($codeNode);
@@ -203,6 +203,13 @@ public static function analyzeInstance(
continue;
}
if ($lhs_type_part instanceof Type\Atomic\TFalse
&& $lhs_type->ignore_falsable_issues
&& count($lhs_type->getTypes()) > 1
) {
continue;
}
if (!$lhs_type_part instanceof TObject && !$lhs_type_part instanceof TNamedObject) {
$invalid_assignment_types[] = (string)$lhs_type_part;
@@ -977,9 +977,10 @@ function (PhpParser\Node\Arg $arg) {
}
} else {
$return_type_candidate = CallMap::getReturnTypeFromCallMap($call_map_id);
if ($return_type_candidate->isFalsable()) {
$return_type_candidate->ignore_falsable_issues = true;
}
}
if ($return_type_candidate->isFalsable()) {
$return_type_candidate->ignore_falsable_issues = true;
}
$return_type_candidate = ExpressionAnalyzer::fleshOutType(
@@ -1593,12 +1593,26 @@ protected static function analyzeClone(
}
if (isset($stmt->expr->inferredType)) {
foreach ($stmt->expr->inferredType->getTypes() as $clone_type_part) {
$clone_type = $stmt->expr->inferredType;
foreach ($clone_type->getTypes() as $clone_type_part) {
if (!$clone_type_part instanceof TNamedObject
&& !$clone_type_part instanceof TObject
&& !$clone_type_part instanceof TMixed
&& !$clone_type_part instanceof TTemplateParam
) {
if ($clone_type_part instanceof Type\Atomic\TFalse
&& $clone_type->ignore_falsable_issues
) {
continue;
}
if ($clone_type_part instanceof Type\Atomic\TNull
&& $clone_type->ignore_nullable_issues
) {
continue;
}
if (IssueBuffer::accepts(
new InvalidClone(
'Cannot clone ' . $clone_type_part,
@@ -1190,7 +1190,7 @@
'connection_aborted' => ['int'],
'connection_status' => ['int'],
'connection_timeout' => ['int'],
'constant' => ['mixed|null', 'const_name'=>'string'],
'constant' => ['mixed', 'const_name'=>'string'],
'convert_cyr_string' => ['string', 'str'=>'string', 'from'=>'string', 'to'=>'string'],
'convert_uudecode' => ['string', 'data'=>'string'],
'convert_uuencode' => ['string', 'data'=>'string'],
@@ -3623,7 +3623,7 @@
'get_magic_quotes_gpc' => ['int|false'],
'get_magic_quotes_runtime' => ['int|false'],
'get_meta_tags' => ['array', 'filename'=>'string', 'use_include_path='=>'bool'],
'get_object_vars' => ['string[]|null', 'obj'=>'object'],
'get_object_vars' => ['array<string, mixed>|null', 'obj'=>'object'],
'get_parent_class' => ['class-string|false', 'object='=>'mixed'],
'get_required_files' => ['string[]'],
'get_resource_type' => ['string', 'res'=>'resource'],
@@ -46,6 +46,9 @@ public function __construct()
$this->registerClass(ReturnTypeProvider\StrReplaceReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\VersionCompareReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\MktimeReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\GetObjectVarsReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\GetClassMethodsReturnTypeProvider::class);
$this->registerClass(ReturnTypeProvider\FirstArgStringReturnTypeProvider::class);
}
/**
@@ -0,0 +1,44 @@
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;
use PhpParser;
use Psalm\Context;
use Psalm\CodeLocation;
use Psalm\Type;
use Psalm\StatementsSource;
class FirstArgStringReturnTypeProvider implements \Psalm\Plugin\Hook\FunctionReturnTypeProviderInterface
{
public static function getFunctionIds() : array
{
return [
'crypt',
'date'
];
}
/**
* @param array<PhpParser\Node\Arg> $call_args
*/
public static function getFunctionReturnType(
StatementsSource $statements_source,
string $function_id,
array $call_args,
Context $context,
CodeLocation $code_location
) {
$return_type = Type::getString();
if (isset($call_args[0]->value->inferredType)
&& $call_args[0]->value->inferredType->isString()
) {
return $return_type;
}
$return_type->addType(new Type\Atomic\TNull);
$return_type->ignore_nullable_issues = true;
return $return_type;
}
}
@@ -0,0 +1,36 @@
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;
use PhpParser;
use Psalm\Context;
use Psalm\CodeLocation;
use Psalm\Type;
use Psalm\StatementsSource;
class GetClassMethodsReturnTypeProvider implements \Psalm\Plugin\Hook\FunctionReturnTypeProviderInterface
{
public static function getFunctionIds() : array
{
return [
'get_class_methods'
];
}
/**
* @param array<PhpParser\Node\Arg> $call_args
*/
public static function getFunctionReturnType(
StatementsSource $statements_source,
string $function_id,
array $call_args,
Context $context,
CodeLocation $code_location
) {
if (isset($call_args[0]->value->inferredType)
&& ($call_args[0]->value->inferredType->hasObjectType() || $call_args[0]->value->inferredType->hasString())
) {
return Type::parseString('array<string>');
}
}
}
@@ -0,0 +1,36 @@
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;
use PhpParser;
use Psalm\Context;
use Psalm\CodeLocation;
use Psalm\Type;
use Psalm\StatementsSource;
class GetObjectVarsReturnTypeProvider implements \Psalm\Plugin\Hook\FunctionReturnTypeProviderInterface
{
public static function getFunctionIds() : array
{
return [
'get_object_vars'
];
}
/**
* @param array<PhpParser\Node\Arg> $call_args
*/
public static function getFunctionReturnType(
StatementsSource $statements_source,
string $function_id,
array $call_args,
Context $context,
CodeLocation $code_location
) {
if (isset($call_args[0]->value->inferredType)
&& $call_args[0]->value->inferredType->isObjectType()
) {
return Type::parseString('array<string, mixed>');
}
}
}
@@ -530,6 +530,20 @@ public function hasObjectType()
return false;
}
/**
* @return bool
*/
public function isObjectType()
{
foreach ($this->types as $type) {
if (!$type->isObjectType()) {
return false;
}
}
return true;
}
/**
* @return bool
*/

0 comments on commit be5a262

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