1
0
Fork 0

fix(DefinitionResolver): resolve self correctly for docblock @return self (#576)

pull/588/head v5.3.4
Phil Nelson 2018-01-09 20:38:18 +11:00 committed by Felix Becker
parent c48ee55808
commit 6894d85aaf
3 changed files with 53 additions and 5 deletions

View File

@ -526,6 +526,20 @@ class DefinitionResolver
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
*
@ -1110,7 +1124,14 @@ class DefinitionResolver
&& $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
@ -1118,10 +1139,9 @@ class DefinitionResolver
// 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()));

View File

@ -4,4 +4,7 @@ class FooClass {
public function foo(): FooClass {
return $this;
}
/** @return self */
public function bar() { }
}

View File

@ -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": []
}
}
}
}