Skip to content

Commit

Permalink
fix(DefinitionResolver): resolve self correctly for docblock @return
Browse files Browse the repository at this point in the history
…self (#576)
  • Loading branch information
phil-nelson authored and felixfbecker committed Jan 9, 2018
1 parent c48ee55 commit 6894d85
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
30 changes: 25 additions & 5 deletions src/DefinitionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,20 @@ private static function getContainingClassFqn(Node $node)
return (string)$classNode->getNamespacedName();
}

/**
* Returns the type of the class a node is contained in
* Returns null if the class is anonymous or the node is not contained in a class
*
* @param Node $node The node used to find the containing class
*
* @return Types\Object_|null
*/
private function getContainingClassType(Node $node)
{
$classFqn = $this->getContainingClassFqn($node);
return $classFqn ? new Types\Object_(new Fqsen('\\' . $classFqn)) : null;
}

/**
* Returns the assignment or parameter node where a variable was defined
*
Expand Down Expand Up @@ -1110,18 +1124,24 @@ public function getTypeFromNode($node)
&& $returnTags[0]->getType() !== null
) {
// Use @return tag
return $returnTags[0]->getType();
$returnType = $returnTags[0]->getType();
if ($returnType instanceof Types\Self_) {
$selfType = $this->getContainingClassType($node);
if ($selfType) {
return $selfType;
}
}
return $returnType;
}
if ($node->returnType !== null && !($node->returnType instanceof PhpParser\MissingToken)) {
// Use PHP7 return type hint
if ($node->returnType instanceof PhpParser\Token) {
// Resolve a string like "bool" to a type object
return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents()));
} elseif ($node->returnType->getResolvedName() === 'self') {
$classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
if ($classNode) {
$classFqn = (string)$classNode->getNamespacedName();
return new Types\Object_(new Fqsen('\\' . $classFqn));
$selfType = $this->getContainingClassType($node);
if ($selfType !== null) {
return $selfType;
}
}
return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName()));
Expand Down
3 changes: 3 additions & 0 deletions tests/Validation/cases/methodReturnType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ class FooClass {
public function foo(): FooClass {
return $this;
}

/** @return self */
public function bar() { }
}
25 changes: 25 additions & 0 deletions tests/Validation/cases/methodReturnType.php.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,31 @@
"documentation": null,
"parameters": []
}
},
"FooClass->bar()": {
"fqn": "FooClass->bar()",
"extends": [],
"isMember": true,
"roamed": false,
"isStatic": false,
"canBeInstantiated": false,
"symbolInformation": {
"name": "bar",
"kind": 6,
"location": {
"uri": "./methodReturnType.php"
},
"containerName": "FooClass"
},
"type__tostring": "\\FooClass",
"type": {},
"declarationLine": "public function bar() { }",
"documentation": "",
"signatureInformation": {
"label": "()",
"documentation": "",
"parameters": []
}
}
}
}

1 comment on commit 6894d85

@jens1o
Copy link
Contributor

@jens1o jens1o commented on 6894d85 Jan 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a cache buster(cache version increase) not necessary?

Please sign in to comment.