Skip to content

Commit

Permalink
Allow omitting argument offsets for map-type overrides in phpstorm.meta
Browse files Browse the repository at this point in the history
Fixes #8758
  • Loading branch information
weirdan committed Nov 27, 2022
1 parent 94dac9f commit de96494
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 6 deletions.
26 changes: 20 additions & 6 deletions src/Psalm/Internal/Scanner/PhpStormMetaScanner.php
Expand Up @@ -89,15 +89,22 @@ public static function handleOverride(array $args, Codebase $codebase): void
if ($identifier instanceof PhpParser\Node\Expr\StaticCall
&& $identifier->class instanceof PhpParser\Node\Name\FullyQualified
&& $identifier->name instanceof PhpParser\Node\Identifier
&& $identifier->getArgs()
&& $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
&& (
$identifier->getArgs() === []
|| $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
)
) {
$meta_fq_classlike_name = implode('\\', $identifier->class->parts);

$meta_method_name = strtolower($identifier->name->name);

if ($map) {
$offset = $identifier->getArgs()[0]->value->value;
$offset = 0;
if ($identifier->getArgs()
&& $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
) {
$offset = $identifier->getArgs()[0]->value->value;
}

$codebase->methods->return_type_provider->registerClosure(
$meta_fq_classlike_name,
Expand Down Expand Up @@ -248,13 +255,20 @@ static function (

if ($identifier instanceof PhpParser\Node\Expr\FuncCall
&& $identifier->name instanceof PhpParser\Node\Name\FullyQualified
&& $identifier->getArgs()
&& $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
&& (
$identifier->getArgs() === []
|| $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
)
) {
$function_id = strtolower(implode('\\', $identifier->name->parts));

if ($map) {
$offset = $identifier->getArgs()[0]->value->value;
$offset = 0;
if ($identifier->getArgs()
&& $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber
) {
$offset = $identifier->getArgs()[0]->value->value;
}

$codebase->functions->return_type_provider->registerClosure(
$function_id,
Expand Down
74 changes: 74 additions & 0 deletions tests/StubTest.php
Expand Up @@ -22,6 +22,9 @@
use function getcwd;
use function implode;
use function reset;
use function strlen;
use function strpos;
use function substr;

use const DIRECTORY_SEPARATOR;

Expand Down Expand Up @@ -321,6 +324,12 @@ class MyClass {
*/
public function create(string $s) {}
/**
* @return mixed
* @psalm-suppress InvalidReturnType
*/
public function create2(string $s) {}
/**
* @param mixed $s
* @return mixed
Expand All @@ -342,6 +351,12 @@ public function bar(array $a) {}
*/
function create(string $s) {}
/**
* @return mixed
* @psalm-suppress InvalidReturnType
*/
function create2(string $s) {}
/**
* @param mixed $s
* @return mixed
Expand All @@ -358,11 +373,19 @@ function bar(array $a) {}
$a1 = (new \Ns\MyClass)->creAte("object");
$a2 = (new \Ns\MyClass)->creaTe("exception");
$y1 = (new \Ns\MyClass)->creAte2("object");
$y2 = (new \Ns\MyClass)->creaTe2("exception");
$b1 = \Create("object");
$b2 = \cReate("exception");
$e2 = \creAte(\LogicException::class);
$z1 = \Create2("object");
$z2 = \cReate2("exception");
$x2 = \creAte2(\LogicException::class);
$c1 = (new \Ns\MyClass)->foo(5);
$c2 = (new \Ns\MyClass)->bar(["hello"]);
Expand All @@ -373,6 +396,57 @@ function bar(array $a) {}

$context = new Context();
$this->analyzeFile($file_path, $context);

$this->assertContextVars(
[
'$a1===' => 'stdClass',
'$a2===' => 'Exception',

'$y1===' => 'stdClass',
'$y2===' => 'Exception',

'$b1===' => 'stdClass',
'$b2===' => 'Exception',

'$e2===' => 'LogicException',

'$z1===' => 'stdClass',
'$z2===' => 'Exception',

'$x2===' => 'LogicException',

'$c1===' => "5",
'$c2===' => "'hello'",

'$d1===' => "5",
'$d2===' => "'hello'"
],
$context
);
}

/** @param array<string, string> $assertions */
private function assertContextVars(array $assertions, Context $context): void
{
$actual_vars = [];
foreach ($assertions as $var => $_) {
$exact = false;

if ($var && strpos($var, '===') === strlen($var) - 3) {
$var = substr($var, 0, -3);
$exact = true;
}

if (isset($context->vars_in_scope[$var])) {
$value = $context->vars_in_scope[$var]->getId($exact);
if ($exact) {
$actual_vars[$var . '==='] = $value;
} else {
$actual_vars[$var] = $value;
}
}
}
$this->assertSame($assertions, $actual_vars);
}

public function testNamespacedStubClass(): void
Expand Down
13 changes: 13 additions & 0 deletions tests/fixtures/stubs/phpstorm.meta.php
@@ -1,6 +1,7 @@
<?php
namespace PHPSTORM_META {

// tests with argument offset (0)
override(\Ns\MyClass::crEate(0), map([
'' => '@',
'exception' => \Exception::class,
Expand All @@ -12,6 +13,18 @@
'object' => \stdClass::class,
]));

// tests without argument offset (0 by default)
override(\Ns\MyClass::crEate2(), map([
'' => '@',
'exception' => \Exception::class,
'object' => \stdClass::class,
]));
override(\create2(), map([
'' => '@',
'exception' => \Exception::class,
'object' => \stdClass::class,
]));

override(\Ns\MyClass::foO(0), type(0));
override(\Ns\MyClass::Bar(0), elementType(0));
override(\foo(0), type(0));
Expand Down

0 comments on commit de96494

Please sign in to comment.