From 51d6128cde1a62276cb36b833357e3bc7f193e0e Mon Sep 17 00:00:00 2001 From: Fuyao Zhao Date: Thu, 15 Jun 2017 05:28:49 +0800 Subject: [PATCH] Try to lookup base class member while resolveExpressionNodeToType --- src/DefinitionResolver.php | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/DefinitionResolver.php b/src/DefinitionResolver.php index 32defab..c717220 100644 --- a/src/DefinitionResolver.php +++ b/src/DefinitionResolver.php @@ -656,13 +656,31 @@ class DefinitionResolver } else { $classFqn = substr((string)$t->getFqsen(), 1); } - $fqn = $classFqn . '->' . $expr->memberName->getText($expr->getFileContents()); - if ($expr->parent instanceof Node\Expression\CallExpression) { - $fqn .= '()'; + + $memberSuffix = '->' . $expr->memberName->getText($expr->getFileContents()); + if ($expr instanceof Node\Expression\CallExpression) { + $memberSuffix .= '()'; } - $def = $this->index->getDefinition($fqn); - if ($def !== null) { - return $def->type; + + // Find the right class that implements the member + $implementorFqns = [$classFqn]; + while ($implementorFqn = array_shift($implementorFqns)) { + // If the member FQN exists, return it + if ($def = $this->index->getDefinition($implementorFqn . $memberSuffix)) { + return $def->type; + } + // Get Definition of implementor class + $implementorDef = $this->index->getDefinition($implementorFqn); + // If it doesn't exist, return the initial guess + if ($implementorDef === null) { + break; + } + // Repeat for parent class + if ($implementorDef->extends) { + foreach ($implementorDef->extends as $extends) { + $implementorFqns[] = $extends; + } + } } } }