moved ancestor generator to Definition
parent
9fb18413f5
commit
56d95102d8
|
@ -201,7 +201,7 @@ class CompletionProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
// Include parent classes
|
// Include parent classes
|
||||||
$prefixes = $this->expandParentFqns($prefixes);
|
$prefixes = iterator_to_array($this->expandParentFqns($prefixes), false);
|
||||||
|
|
||||||
// Add the object access operator to only get members
|
// Add the object access operator to only get members
|
||||||
foreach ($prefixes as &$prefix) {
|
foreach ($prefixes as &$prefix) {
|
||||||
|
@ -237,7 +237,7 @@ class CompletionProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add parent classes
|
// Add parent classes
|
||||||
$prefixes = $this->expandParentFqns($prefixes);
|
$prefixes = iterator_to_array($this->expandParentFqns($prefixes), false);
|
||||||
|
|
||||||
// Append :: operator to only get static members
|
// Append :: operator to only get static members
|
||||||
foreach ($prefixes as &$prefix) {
|
foreach ($prefixes as &$prefix) {
|
||||||
|
@ -382,19 +382,16 @@ class CompletionProvider
|
||||||
* @param string[] $fqns
|
* @param string[] $fqns
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
private function expandParentFqns(array $fqns): array
|
private function expandParentFqns(array $fqns)
|
||||||
{
|
{
|
||||||
$expanded = $fqns;
|
|
||||||
foreach ($fqns as $fqn) {
|
foreach ($fqns as $fqn) {
|
||||||
|
yield $fqn;
|
||||||
$def = $this->index->getDefinition($fqn);
|
$def = $this->index->getDefinition($fqn);
|
||||||
if ($def) {
|
if ($def !== null) {
|
||||||
foreach ($this->expandParentFqns($def->extends ?? []) as $parent) {
|
yield from $def->getAncestorFQNs($this->index);
|
||||||
$expanded[] = $parent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will walk the AST upwards until a function-like node is met
|
* Will walk the AST upwards until a function-like node is met
|
||||||
|
|
|
@ -3,6 +3,7 @@ declare(strict_types = 1);
|
||||||
|
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
|
use LanguageServer\Index\ReadableIndex;
|
||||||
use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver};
|
use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver};
|
||||||
use LanguageServer\Protocol\SymbolInformation;
|
use LanguageServer\Protocol\SymbolInformation;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
@ -95,4 +96,42 @@ class Definition
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $documentation;
|
public $documentation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the definitons of all ancestor classes
|
||||||
|
*
|
||||||
|
* @return Definition[]
|
||||||
|
*/
|
||||||
|
public function getAncestorDefinitions(ReadableIndex $index, bool $includeSelf = false)
|
||||||
|
{
|
||||||
|
if ($includeSelf) {
|
||||||
|
yield $this;
|
||||||
|
}
|
||||||
|
if (is_array($this->extends)) {
|
||||||
|
// iterating once, storing the references and iterating again
|
||||||
|
// guarantees that closest definitions are returned first
|
||||||
|
$definitions = [];
|
||||||
|
foreach ($this->extends as $fqn) {
|
||||||
|
$def = $index->getDefinition($fqn);
|
||||||
|
if ($def !== null) {
|
||||||
|
yield $def;
|
||||||
|
$definitions[] = $def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($definitions as $def) {
|
||||||
|
yield from $def->getAncestorDefinitions($index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the FQNs of all parent classes
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getAncestorFQNs(ReadableIndex $index, bool $includeSelf = false)
|
||||||
|
{
|
||||||
|
foreach ($this->getAncestorDefinitions($index, $includeSelf) as $def) {
|
||||||
|
yield $def->fqn;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -670,19 +670,11 @@ class DefinitionResolver
|
||||||
if ($expr->parent instanceof Node\Expression\CallExpression) {
|
if ($expr->parent instanceof Node\Expression\CallExpression) {
|
||||||
$add .= '()';
|
$add .= '()';
|
||||||
}
|
}
|
||||||
$lookupDefinition = function (string $base, string $add) use (&$lookupDefinition) {
|
$classDef = $this->index->getDefinition($classFqn);
|
||||||
$def = $this->index->getDefinition($base . $add);
|
if ($classDef !== null) {
|
||||||
|
foreach ($classDef->getAncestorFQNs($this->index, true) as $fqn) {
|
||||||
|
$def = $this->index->getDefinition($fqn . $add);
|
||||||
if ($def !== null) {
|
if ($def !== null) {
|
||||||
yield $def;
|
|
||||||
}
|
|
||||||
$baseDef = $this->index->getDefinition($base);
|
|
||||||
if ($baseDef !== null && is_array($baseDef->extends)) {
|
|
||||||
foreach ($baseDef->extends as $name) {
|
|
||||||
yield from $lookupDefinition($name, $add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
foreach ($lookupDefinition($classFqn, $add) as $def) {
|
|
||||||
if ($def->type instanceof Types\This) {
|
if ($def->type instanceof Types\This) {
|
||||||
return new Types\Object_(new Fqsen('\\' . $classFqn));
|
return new Types\Object_(new Fqsen('\\' . $classFqn));
|
||||||
}
|
}
|
||||||
|
@ -690,6 +682,8 @@ class DefinitionResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SCOPED PROPERTY ACCESS EXPRESSION
|
// SCOPED PROPERTY ACCESS EXPRESSION
|
||||||
if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) {
|
if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) {
|
||||||
|
|
Loading…
Reference in New Issue