1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Fix handling of class const types

This commit is contained in:
Matthew Brown 2019-06-06 18:46:40 -04:00
parent 36ac342496
commit 20c66f693e
6 changed files with 102 additions and 21 deletions

View File

@ -78,7 +78,7 @@ trait CanAlias
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $use->getAttribute('startFilePos'),
(int) $use->getAttribute('endFilePos') + 1,
$new_fq_class_name
$new_fq_class_name . ($use->alias ? ' as ' . $use_alias : '')
);
FileManipulationBuffer::add($this->getFilePath(), $file_manipulations);

View File

@ -435,7 +435,8 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
$storage->return_type,
$context->self,
$context->self,
$this->getParentFQCLN()
$this->getParentFQCLN(),
false
);
$codebase->classlikes->handleDocblockTypeInMigration(
@ -458,7 +459,8 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
$function_param->type,
$context->self,
$context->self,
$this->getParentFQCLN()
$this->getParentFQCLN(),
false
);
$codebase->classlikes->handleDocblockTypeInMigration(

View File

@ -1001,7 +1001,8 @@ class ExpressionAnalyzer
Type\Union $return_type,
?string $self_class,
$static_class_type,
?string $parent_class
?string $parent_class,
bool $evaluate = true
) {
$return_type = clone $return_type;
@ -1013,7 +1014,8 @@ class ExpressionAnalyzer
$return_type_part,
$self_class,
$static_class_type,
$parent_class
$parent_class,
$evaluate
);
if (is_array($parts)) {
@ -1048,7 +1050,8 @@ class ExpressionAnalyzer
Type\Atomic &$return_type,
?string $self_class,
$static_class_type,
?string $parent_class
?string $parent_class,
bool $evaluate = true
) {
if ($return_type instanceof TNamedObject
|| $return_type instanceof TTemplateParam
@ -1062,7 +1065,8 @@ class ExpressionAnalyzer
$extra_type,
$self_class,
$static_class_type,
$parent_class
$parent_class,
$evaluate
);
if ($extra_type instanceof TNamedObject && $extra_type->extra_types) {
@ -1121,7 +1125,7 @@ class ExpressionAnalyzer
$return_type->fq_classlike_name = $self_class;
}
if ($codebase->classOrInterfaceExists($return_type->fq_classlike_name)) {
if ($evaluate && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) {
if (strtolower($return_type->const_name) === 'class') {
return new Type\Atomic\TLiteralClassString($return_type->fq_classlike_name);
}
@ -1152,7 +1156,7 @@ class ExpressionAnalyzer
$return_type->fq_classlike_name = $self_class;
}
if ($codebase->classOrInterfaceExists($return_type->fq_classlike_name)) {
if ($evaluate && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) {
$class_constants = $codebase->classlikes->getConstantsForClass(
$return_type->fq_classlike_name,
\ReflectionProperty::IS_PRIVATE

View File

@ -1036,11 +1036,20 @@ class ClassLikes
$uses_flipped = $source->getAliasedClassesFlipped();
$uses_flipped_replaceable = $source->getAliasedClassesFlippedReplaceable();
if (isset($uses_flipped_replaceable[strtolower($fq_class_name)])) {
unset($uses_flipped_replaceable[strtolower($fq_class_name)]);
$new_class_name_parts = explode('\\', $new_fq_class_name);
$class_name = end($new_class_name_parts);
$uses_flipped[strtolower($new_fq_class_name)] = $class_name;
$old_fq_class_name = strtolower($fq_class_name);
if (isset($uses_flipped_replaceable[$old_fq_class_name])) {
$alias = $uses_flipped_replaceable[$old_fq_class_name];
unset($uses_flipped_replaceable[$old_fq_class_name]);
$old_class_name_parts = explode('\\', $old_fq_class_name);
$old_class_name = end($old_class_name_parts);
if (strtolower($old_class_name) === strtolower($alias)) {
$new_class_name_parts = explode('\\', $new_fq_class_name);
$new_class_name = end($new_class_name_parts);
$uses_flipped[strtolower($new_fq_class_name)] = $new_class_name;
} else {
$uses_flipped[strtolower($new_fq_class_name)] = $alias;
}
}
$file_manipulations[] = new \Psalm\FileManipulation(
@ -1138,10 +1147,17 @@ class ClassLikes
$uses_flipped_replaceable = $source->getAliasedClassesFlippedReplaceable();
if (isset($uses_flipped_replaceable[$old_fq_class_name])) {
$alias = $uses_flipped_replaceable[$old_fq_class_name];
unset($uses_flipped_replaceable[$old_fq_class_name]);
$new_class_name_parts = explode('\\', $new_fq_class_name);
$class_name = end($new_class_name_parts);
$uses_flipped[strtolower($new_fq_class_name)] = $class_name;
$old_class_name_parts = explode('\\', $old_fq_class_name);
$old_class_name = end($old_class_name_parts);
if (strtolower($old_class_name) === strtolower($alias)) {
$new_class_name_parts = explode('\\', $new_fq_class_name);
$new_class_name = end($new_class_name_parts);
$uses_flipped[strtolower($new_fq_class_name)] = $new_class_name;
} else {
$uses_flipped[strtolower($new_fq_class_name)] = $alias;
}
}
$file_manipulations[] = new \Psalm\FileManipulation(

View File

@ -812,7 +812,7 @@ abstract class Atomic
}
if ($this instanceof TScalarClassConstant) {
if (strtolower($old) === $new) {
if (strtolower($this->fq_classlike_name) === $old) {
$this->fq_classlike_name = $new;
}
}

View File

@ -366,17 +366,19 @@ class ClassMoveTest extends \Psalm\Tests\TestCase
'A' => 'Foo\Bar\Baz\B',
]
],
'moveClassDeeperIntoNamespaceAdjustUse' => [
'moveClassDeeperIntoNamespaceAdjustUseWithoutAlias' => [
'<?php
namespace Foo {
use Bar\Bat;
echo Bat::FOO;
echo Bat::FAR;
/**
* @param Bat $b
* @param Bat::FOO|Bat::FAR $c
*/
function doSomething(Bat $b) : void {}
function doSomething(Bat $b, int $c) : void {}
class A {
/** @var ?Bat */
@ -386,6 +388,7 @@ class ClassMoveTest extends \Psalm\Tests\TestCase
namespace Bar {
class Bat {
const FOO = 5;
const FAR = 7;
}
}',
'<?php
@ -393,11 +396,13 @@ class ClassMoveTest extends \Psalm\Tests\TestCase
use Bar\Baz\Bahh;
echo Bahh::FOO;
echo Bahh::FAR;
/**
* @param Bahh $b
* @param Bahh::FOO|Bahh::FAR $c
*/
function doSomething(Bahh $b) : void {}
function doSomething(Bahh $b, int $c) : void {}
class A {
/** @var null|Bahh */
@ -407,6 +412,60 @@ class ClassMoveTest extends \Psalm\Tests\TestCase
namespace Bar\Baz {
class Bahh {
const FOO = 5;
const FAR = 7;
}
}',
[
'Bar\Bat' => 'Bar\Baz\Bahh',
]
],
'moveClassDeeperIntoNamespaceAdjustUseWithAlias' => [
'<?php
namespace Foo {
use Bar\Bat as Kappa;
echo Kappa::FOO;
echo Kappa::FAR;
/**
* @param Kappa $b
* @param Kappa::FOO|Kappa::FAR $c
*/
function doSomething(Kappa $b, int $c) : void {}
class A {
/** @var ?Kappa */
public $x = null;
}
}
namespace Bar {
class Bat {
const FOO = 5;
const FAR = 7;
}
}',
'<?php
namespace Foo {
use Bar\Baz\Bahh as Kappa;
echo Kappa::FOO;
echo Kappa::FAR;
/**
* @param Kappa $b
* @param Kappa::FOO|Kappa::FAR $c
*/
function doSomething(Kappa $b, int $c) : void {}
class A {
/** @var null|Kappa */
public $x = null;
}
}
namespace Bar\Baz {
class Bahh {
const FOO = 5;
const FAR = 7;
}
}',
[