From 63da051e72554d41a123b7cb667601ab1f696dd1 Mon Sep 17 00:00:00 2001 From: Phil Nelson Date: Sat, 23 Dec 2017 13:02:37 +1100 Subject: [PATCH] fix(DefinitionResolver): fix methods with self return type (#550) --- src/DefinitionResolver.php | 8 +++++- .../WithReturnTypehints.php.expected.json | 2 +- .../cases/staticMethodReturnType.php | 2 ++ .../staticMethodReturnType.php.expected.json | 25 +++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index f36588d..905f9d6 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -729,7 +729,7 @@ class DefinitionResolver foreach ($classDef->getAncestorDefinitions($this->index, true) as $fqn => $def) { $def = $this->index->getDefinition($fqn . $add); if ($def !== null) { - if ($def->type instanceof Types\This) { + if ($def->type instanceof Types\This || $def->type instanceof Types\Self_) { return new Types\Object_(new Fqsen('\\' . $classFqn)); } return $def->type; @@ -1090,6 +1090,12 @@ class DefinitionResolver 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)); + } } return new Types\Object_(new Fqsen('\\' . (string)$node->returnType->getResolvedName())); } diff --git a/tests/Validation/cases/WithReturnTypehints.php.expected.json b/tests/Validation/cases/WithReturnTypehints.php.expected.json index a037d6c..2eb8218 100644 --- a/tests/Validation/cases/WithReturnTypehints.php.expected.json +++ b/tests/Validation/cases/WithReturnTypehints.php.expected.json @@ -71,7 +71,7 @@ }, "containerName": "Fixtures\\Prophecy\\WithReturnTypehints" }, - "type__tostring": "\\self", + "type__tostring": "\\Fixtures\\Prophecy\\WithReturnTypehints", "type": {}, "declarationLine": "public function getSelf(): self {", "documentation": null, diff --git a/tests/Validation/cases/staticMethodReturnType.php b/tests/Validation/cases/staticMethodReturnType.php index 325738a..0ce2654 100644 --- a/tests/Validation/cases/staticMethodReturnType.php +++ b/tests/Validation/cases/staticMethodReturnType.php @@ -5,5 +5,7 @@ class FooClass { return new FooClass(); } + public static function staticSelf(): self { } + public function bar() { } } diff --git a/tests/Validation/cases/staticMethodReturnType.php.expected.json b/tests/Validation/cases/staticMethodReturnType.php.expected.json index 8de5673..041042a 100644 --- a/tests/Validation/cases/staticMethodReturnType.php.expected.json +++ b/tests/Validation/cases/staticMethodReturnType.php.expected.json @@ -50,6 +50,31 @@ "parameters": [] } }, + "FooClass::staticSelf()": { + "fqn": "FooClass::staticSelf()", + "extends": [], + "isMember": true, + "roamed": false, + "isStatic": true, + "canBeInstantiated": false, + "symbolInformation": { + "name": "staticSelf", + "kind": 6, + "location": { + "uri": "./staticMethodReturnType.php" + }, + "containerName": "FooClass" + }, + "type__tostring": "\\FooClass", + "type": {}, + "declarationLine": "public static function staticSelf(): self { }", + "documentation": null, + "signatureInformation": { + "label": "()", + "documentation": null, + "parameters": [] + } + }, "FooClass->bar()": { "fqn": "FooClass->bar()", "extends": [],