Skip to content

Commit

Permalink
Fix Return type Covariance Inverse Order
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Sep 15, 2019
1 parent f855daa commit f2a699f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,30 +114,31 @@ public function refactor(Node $node): ?Node

$inferredReturnNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($inferedType);

// nothing to change in PHP code - @todo add @var annotation fallback?
if ($inferredReturnNode === null) {
return null;
}

// already overridden by previous populateChild() method run
if ($node->returnType && $node->returnType->getAttribute(self::DO_NOT_CHANGE)) {
return null;
}

$shouldPopulateChildren = false;
// should be previous overridden?
if ($node->returnType !== null && $inferredReturnNode !== null) {
if ($node->returnType !== null) {
$isSubtype = $this->isSubtypeOf($inferredReturnNode, $node->returnType);

// @see https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters
if ($this->isAtLeastPhpVersion('7.4') && $isSubtype) {
$shouldPopulateChildren = true;
$node->returnType = $inferredReturnNode;
} elseif ($isSubtype === false) { // type override
$shouldPopulateChildren = true;
$node->returnType = $inferredReturnNode;
}
} elseif ($inferredReturnNode !== null) {
$shouldPopulateChildren = true;
} else {
$node->returnType = $inferredReturnNode;
}

if ($shouldPopulateChildren && $node instanceof ClassMethod) {
if ($node instanceof ClassMethod) {
$this->populateChildren($node, $inferedType);
}

Expand All @@ -160,6 +161,9 @@ private function populateChildren(ClassMethod $classMethod, Type $returnType): v
}

$childrenClassLikes = $this->parsedNodesByType->findChildrenOfClass($className);
if ($childrenClassLikes === []) {
return;
}

// update their methods as well
foreach ($childrenClassLikes as $childClassLike) {
Expand All @@ -184,11 +188,6 @@ private function addReturnTypeToChildMethod(
return;
}

// already has a type
if ($currentClassMethod->returnType !== null) {
return;
}

$resolvedChildTypeNode = $this->resolveChildTypeNode($returnType);
if ($resolvedChildTypeNode === null) {
return;
Expand Down
11 changes: 6 additions & 5 deletions src/NodeContainer/ParsedNodesByType.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,17 +165,18 @@ public function findClassesAndInterfacesByType(string $type): array
public function findChildrenOfClass(string $class): array
{
$childrenClasses = [];

foreach ($this->classes as $classNode) {
$className = $classNode->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return [];
$currentClassName = $classNode->getAttribute(AttributeKey::CLASS_NAME);
if ($currentClassName === null) {
continue;
}

if (! is_a($className, $class, true)) {
if (! is_a($currentClassName, $class, true)) {
continue;
}

if ($className === $class) {
if ($currentClassName === $class) {
continue;
}

Expand Down

0 comments on commit f2a699f

Please sign in to comment.