Skip to content

Commit

Permalink
Remove mixin_fqcln hack
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed May 10, 2020
1 parent 3e16aec commit 28349c6
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -488,11 +488,49 @@ public static function analyzeInstance(
$class_exists = true;
}

$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
$property_id = $fq_class_name . '::$' . $prop_name;

$naive_property_exists = $codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations ? new CodeLocation($statements_analyzer->getSource(), $stmt) : null
);

// add method before changing fq_class_name
$get_method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__get');

if (!$naive_property_exists
&& $class_storage->mixin instanceof Type\Atomic\TNamedObject
) {
$new_property_id = $class_storage->mixin->value . '::$' . $prop_name;
$new_class_storage = $codebase->classlike_storage_provider->get($class_storage->mixin->value);

if ($codebase->properties->propertyExists(
$new_property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations ? new CodeLocation($statements_analyzer->getSource(), $stmt) : null
)
|| isset($new_class_storage->pseudo_property_get_types['$' . $prop_name])
) {
$fq_class_name = $class_storage->mixin->value;
$lhs_type_part = clone $class_storage->mixin;
$class_storage = $new_class_storage;

if (!isset($new_class_storage->pseudo_property_get_types['$' . $prop_name])) {
$naive_property_exists = true;
}

$property_id = $new_property_id;
}
}

if ($codebase->methods->methodExists($get_method_id)
&& (!$codebase->properties->propertyExists($property_id, true, $statements_analyzer, $context)
&& (!$naive_property_exists
|| ($stmt_var_id !== '$this'
&& $fq_class_name !== $context->self
&& ClassLikeAnalyzer::checkPropertyVisibility(
Expand All @@ -507,8 +545,6 @@ public static function analyzeInstance(
) {
$has_magic_getter = true;

$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);

if (isset($class_storage->pseudo_property_get_types['$' . $prop_name])) {
$stmt_type = clone $class_storage->pseudo_property_get_types['$' . $prop_name];

Expand Down Expand Up @@ -580,7 +616,9 @@ public static function analyzeInstance(
continue;
}

if (!$class_exists) {
if ($interface_exists) {
$property_id = $lhs_type_part->value . '::$' . $prop_name;

if (IssueBuffer::accepts(
new UndefinedMagicPropertyFetch(
'Magic instance property ' . $property_id . ' is not defined',
Expand All @@ -591,11 +629,9 @@ public static function analyzeInstance(
)) {
// fall through
}
}
}

if (!$class_exists) {
continue;
continue;
}
}

if ($codebase->store_node_types
Expand All @@ -609,17 +645,9 @@ public static function analyzeInstance(
);
}

$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
$config = $statements_analyzer->getProjectAnalyzer()->getConfig();

if (!$codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations ? new CodeLocation($statements_analyzer->getSource(), $stmt) : null
)
) {
if (!$naive_property_exists) {
if ($config->use_phpdoc_property_without_magic_or_parent
&& isset($class_storage->pseudo_property_get_types['$' . $prop_name])
) {
Expand Down
37 changes: 4 additions & 33 deletions src/Psalm/Internal/Codebase/Populator.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,6 @@ private function populateClassLikeStorage(ClassLikeStorage $storage, array $depe

$this->populateDataFromImplementedInterfaces($storage, $storage_provider, $dependent_classlikes);

if ($storage->mixin_fqcln) {
$this->populateDataFromMixin($storage, $storage_provider, $dependent_classlikes, $storage->mixin_fqcln);
}

if ($storage->location) {
$file_path = $storage->location->file_path;

Expand Down Expand Up @@ -446,35 +442,6 @@ private function populateDataFromTraits(
}
}

/**
* @return void
*/
private function populateDataFromMixin(
ClassLikeStorage $storage,
ClassLikeStorageProvider $storage_provider,
array $dependent_classlikes,
string $mixin_fqcln
) {
try {
$mixin_fqcln = strtolower(
$this->classlikes->getUnAliasedName(
$mixin_fqcln
)
);
$mixin_storage = $storage_provider->get($mixin_fqcln);
} catch (\InvalidArgumentException $e) {
return;
}

$this->populateClassLikeStorage($mixin_storage, $dependent_classlikes);

$this->inheritMethodsFromParent($storage, $mixin_storage, true);
$this->inheritPropertiesFromParent($storage, $mixin_storage, true);

$storage->pseudo_property_get_types += $mixin_storage->pseudo_property_get_types;
$storage->pseudo_property_set_types += $mixin_storage->pseudo_property_set_types;
}

private static function extendType(
Type\Union $type,
ClassLikeStorage $storage
Expand Down Expand Up @@ -612,6 +579,10 @@ private function populateDataFromParentClass(
$storage->protected_class_constants
);

if ($parent_storage->mixin && !$storage->mixin) {
$storage->mixin = $parent_storage->mixin;
}

foreach ($parent_storage->public_class_constant_nodes as $name => $_) {
$storage->public_class_constants[$name] = Type::getMixed();
}
Expand Down
17 changes: 3 additions & 14 deletions src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -1270,20 +1270,9 @@ function (array $l, array $r) : int {
if ($mixin_type->isSingle()) {
$mixin_type = \array_values($mixin_type->getAtomicTypes())[0];

if ($mixin_type instanceof Type\Atomic\TNamedObject) {
if ($mixin_type instanceof Type\Atomic\TGenericObject) {
$storage->mixin = $mixin_type;
} else {
$storage->mixin_fqcln = $mixin_type->value;

$this->file_storage->referenced_classlikes[strtolower($storage->mixin_fqcln)]
= $storage->mixin_fqcln;

// if there's a mixin, assume it's the reason for the __call
$storage->sealed_properties = true;
$storage->sealed_methods = true;
}
} elseif ($mixin_type instanceof Type\Atomic\TTemplateParam) {
if ($mixin_type instanceof Type\Atomic\TNamedObject
|| $mixin_type instanceof Type\Atomic\TTemplateParam
) {
$storage->mixin = $mixin_type;
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/Psalm/Storage/ClassLikeStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ class ClassLikeStorage
*/
public $psalm_internal = null;

/**
* @var null|string
*/
public $mixin_fqcln = null;

/**
* @var null|Type\Atomic\TTemplateParam|Type\Atomic\TNamedObject
*/
Expand Down
12 changes: 6 additions & 6 deletions tests/MixinAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,18 @@ function getDog(): Dog {
/**
* @property string $foo
*/
class A {
class A {}
/**
* @mixin A
*/
class B {
/** @return mixed */
public function __get(string $s) {
return 5;
}
}
/**
* @mixin A
*/
class B {}
function toArray(B $b) : string {
return $b->foo;
}'
Expand Down

0 comments on commit 28349c6

Please sign in to comment.