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(); 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 * Returns the assignment or parameter node where a variable was defined
* *
@ -1110,7 +1124,14 @@ class DefinitionResolver
&& $returnTags[0]->getType() !== null && $returnTags[0]->getType() !== null
) { ) {
// Use @return tag // 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)) { if ($node->returnType !== null && !($node->returnType instanceof PhpParser\MissingToken)) {
// Use PHP7 return type hint // Use PHP7 return type hint
@ -1118,10 +1139,9 @@ class DefinitionResolver
// Resolve a string like "bool" to a type object // Resolve a string like "bool" to a type object
return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents())); return $this->typeResolver->resolve($node->returnType->getText($node->getFileContents()));
} elseif ($node->returnType->getResolvedName() === 'self') { } elseif ($node->returnType->getResolvedName() === 'self') {
$classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class); $selfType = $this->getContainingClassType($node);
if ($classNode) { if ($selfType !== null) {
$classFqn = (string)$classNode->getNamespacedName(); return $selfType;
return new Types\Object_(new Fqsen('\\' . $classFqn));
} }
} }
return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName()));

View File

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

View File

@ -49,6 +49,31 @@
"documentation": null, "documentation": null,
"parameters": [] "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": []
}
} }
} }
} }