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( $file_manipulations[] = new \Psalm\FileManipulation(
(int) $use->getAttribute('startFilePos'), (int) $use->getAttribute('startFilePos'),
(int) $use->getAttribute('endFilePos') + 1, (int) $use->getAttribute('endFilePos') + 1,
$new_fq_class_name $new_fq_class_name . ($use->alias ? ' as ' . $use_alias : '')
); );
FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); FileManipulationBuffer::add($this->getFilePath(), $file_manipulations);

View File

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

View File

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

View File

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

View File

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

View File

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