1
0
Fork 0

Completion for inherited this

pull/247/head
Ivan Bozhanov 2017-01-20 21:25:23 +02:00
parent f6ccdd4911
commit 2f50f4a430
2 changed files with 39 additions and 9 deletions

View File

@ -130,6 +130,10 @@ class CompletionProvider
$list = new CompletionList; $list = new CompletionList;
$list->isIncomplete = true; $list->isIncomplete = true;
//echo get_class($node->var);
//var_dump((string)$node->var->name);
//die();
// A non-free node means we do NOT suggest global symbols // A non-free node means we do NOT suggest global symbols
if ( if (
$node instanceof Node\Expr\MethodCall $node instanceof Node\Expr\MethodCall
@ -141,7 +145,7 @@ class CompletionProvider
// If the name is an Error node, just filter by the class // If the name is an Error node, just filter by the class
if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) { if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) {
// For instances, resolve the variable type // For instances, resolve the variable type
$prefixes = DefinitionResolver::getFqnsFromType( $prefixes = DefinitionResolver::getFqnsFromType(
$this->definitionResolver->resolveExpressionNodeToType($node->var) $this->definitionResolver->resolveExpressionNodeToType($node->var)
); );
} else { } else {

View File

@ -423,7 +423,7 @@ class DefinitionResolver
if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') { if ($expr instanceof Node\Expr\Variable && $expr->name === 'this') {
$classNode = getClosestNode($expr, Node\Stmt\Class_::class); $classNode = getClosestNode($expr, Node\Stmt\Class_::class);
if ($classNode) { if ($classNode) {
return self::resolveClassNameToType($classNode->namespacedName); return self::resolveClassNameToType($classNode->namespacedName);
} }
return new Types\This; return new Types\This;
} }
@ -479,13 +479,19 @@ class DefinitionResolver
} else { } else {
$classFqn = substr((string)$t->getFqsen(), 1); $classFqn = substr((string)$t->getFqsen(), 1);
} }
$fqn = $classFqn . '->' . $expr->name; $extended = $this->expandParentFqns([$classFqn]);
if ($expr instanceof Node\Expr\MethodCall) { foreach ($extended as $f) {
$fqn .= '()'; $fqn = $f . '->' . $expr->name;
} if ($expr instanceof Node\Expr\MethodCall) {
$def = $this->index->getDefinition($fqn); $fqn .= '()';
if ($def !== null) { }
return $def->type; $def = $this->index->getDefinition($fqn);
if ($def !== null) {
if ($def->type instanceof Types\This || $def->type instanceof Types\Self_) {
return $this->resolveExpressionNodeToType($expr->var);
}
return $def->type;
}
} }
} }
} }
@ -651,6 +657,26 @@ class DefinitionResolver
return new Types\Mixed; return new Types\Mixed;
} }
/**
* Adds the FQNs of all parent classes to an array of FQNs of classes
*
* @param string[] $fqns
* @return string[]
*/
private function expandParentFqns(array $fqns): array
{
$expanded = $fqns;
foreach ($fqns as $fqn) {
$def = $this->index->getDefinition($fqn);
if ($def) {
foreach ($this->expandParentFqns($def->extends) as $parent) {
$expanded[] = $parent;
}
}
}
return $expanded;
}
/** /**
* Takes any class name node (from a static method call, or new node) and returns a Type object * Takes any class name node (from a static method call, or new node) and returns a Type object
* Resolves keywords like self, static and parent * Resolves keywords like self, static and parent