1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Add support for $a::class

This commit is contained in:
Matthew Brown 2019-01-05 15:12:42 -05:00
parent f5378bdca8
commit 8024b4e275
2 changed files with 209 additions and 137 deletions

View File

@ -90,9 +90,9 @@ class ConstFetchAnalyzer
) {
$codebase = $statements_analyzer->getCodebase();
if (($context->check_consts
|| ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class'))
&& $stmt->class instanceof PhpParser\Node\Name
if ($stmt->class instanceof PhpParser\Node\Name) {
if ($context->check_consts
|| ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class')
) {
$first_part_lc = strtolower($stmt->class->parts[0]);
@ -258,6 +258,16 @@ class ConstFetchAnalyzer
return null;
}
} elseif ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class') {
ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context);
$lhs_type = $stmt->class->inferredType;
$stmt->inferredType = new Type\Union([
new Type\Atomic\TClassString('object', $lhs_type)
]);
return;
}
$stmt->inferredType = Type::getMixed();

View File

@ -311,6 +311,47 @@ class ClassStringTest extends TestCase
foo(AChild::class);',
],
'returnClassConstantClassStringParameterized' => [
'<?php
class A {}
/**
* @return class-string<A> $s
*/
function foo(A $a) : string {
return $a::class;
}',
],
'returnGetClassClassStringParameterized' => [
'<?php
class A {}
/**
* @return class-string<A> $s
*/
function foo(A $a) : string {
return get_class($a);
}',
],
'createClassOfTypeFromString' => [
'<?php
class A {}
/**
* @return class-string<A> $s
*/
function foo(string $s) : string {
if (!class_exists($s)) {
throw new \UnexpectedValueException("bad");
}
if (!is_a($s, A::class, true)) {
throw new \UnexpectedValueException("bad");
}
return $s;
}',
],
];
}
@ -428,6 +469,27 @@ class ClassStringTest extends TestCase
foo(AChild::class);',
'error_message' => 'InvalidArgument',
],
'createClassOfWrongTypeFromString' => [
'<?php
class A {}
class B {}
/**
* @return class-string<A> $s
*/
function foo(string $s) : string {
if (!class_exists($s)) {
throw new \UnexpectedValueException("bad");
}
if (!is_a($s, B::class, true)) {
throw new \UnexpectedValueException("bad");
}
return $s;
}',
'error_message' => 'InvalidReturnStatement',
],
];
}
}