Properly filter completion on empty property
parent
51de0b5dfc
commit
d66cc763bc
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
|
||||
$obj = new TestClass;
|
||||
$obj->t
|
||||
$obj->
|
||||
|
|
|
@ -56,14 +56,38 @@ class CompletionProvider
|
|||
|| $node instanceof Node\Expr\StaticPropertyFetch
|
||||
|| $node instanceof Node\Expr\ClassConstFetch
|
||||
) {
|
||||
/** The FQN to be completed */
|
||||
$prefix = $this->definitionResolver->resolveReferenceNodeToFqn($node) ?? '';
|
||||
$prefixLen = strlen($prefix);
|
||||
$nodeToResolve = $node;
|
||||
if (!is_string($node->name)) {
|
||||
// If the name is an Error node, just filter by the class
|
||||
if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) {
|
||||
$nodeToResolve = $node->var;
|
||||
} else {
|
||||
$nodeToResolve = $node->class;
|
||||
}
|
||||
}
|
||||
$prefixes = DefinitionResolver::getFqnsFromType(
|
||||
$this->definitionResolver->resolveExpressionNodeToType($nodeToResolve)
|
||||
);
|
||||
if (!is_string($node->name)) {
|
||||
// If we are just filtering by the class, add the appropiate operator to the prefix
|
||||
// to filter the type of symbol
|
||||
foreach ($prefixes as &$prefix) {
|
||||
if ($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\PropertyFetch) {
|
||||
$prefix .= '->';
|
||||
} else if ($node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\ClassConstFetch) {
|
||||
$prefix .= '::';
|
||||
} else if ($node instanceof Node\Expr\StaticPropertyFetch) {
|
||||
$prefix .= '::$';
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($this->project->getDefinitions() as $fqn => $def) {
|
||||
if (substr($fqn, 0, $prefixLen) === $prefix && !$def->isGlobal) {
|
||||
foreach ($prefixes as $prefix) {
|
||||
if (substr($fqn, 0, strlen($prefix)) === $prefix && !$def->isGlobal) {
|
||||
$items[] = CompletionItem::fromDefinition($def);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
// A ConstFetch means any static reference, like a class, interface, etc.
|
||||
($node instanceof Node\Name && $node->getAttribute('parentNode') instanceof Node\Expr\ConstFetch)
|
||||
|
|
|
@ -146,6 +146,31 @@ class DefinitionResolver
|
|||
return $this->project->getDefinition($fqn, $globalFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all possible FQNs in a type
|
||||
*
|
||||
* @param Type $type
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getFqnsFromType(Type $type): array
|
||||
{
|
||||
$fqns = [];
|
||||
if ($type instanceof Types\Object_) {
|
||||
$fqsen = $type->getFqsen();
|
||||
if ($fqsen !== null) {
|
||||
$fqns[] = substr((string)$fqsen, 1);
|
||||
}
|
||||
}
|
||||
if ($type instanceof Types\Compound) {
|
||||
for ($i = 0; $t = $type->get($i); $i++) {
|
||||
foreach (self::getFqnsFromType($type) as $fqn) {
|
||||
$fqns[] = $fqn;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fqns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given any node, returns the FQN of the symbol that is referenced
|
||||
* Returns null if the FQN could not be resolved or the reference node references a variable
|
||||
|
|
|
@ -30,13 +30,37 @@ class CompletionTest extends TestCase
|
|||
$this->textDocument = new Server\TextDocument($this->project, $client);
|
||||
}
|
||||
|
||||
public function testForPropertiesAndMethods()
|
||||
public function testPropertyAndMethodWithPrefix()
|
||||
{
|
||||
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/property_with_prefix.php');
|
||||
$this->project->openDocument($completionUri, file_get_contents($completionUri));
|
||||
$items = $this->textDocument->completion(
|
||||
new TextDocumentIdentifier($completionUri),
|
||||
new Position(3, 7)
|
||||
)->wait();
|
||||
$this->assertEquals([
|
||||
new CompletionItem(
|
||||
'testProperty',
|
||||
CompletionItemKind::PROPERTY,
|
||||
'\TestClass', // Type of the property
|
||||
'Reprehenderit magna velit mollit ipsum do.'
|
||||
),
|
||||
new CompletionItem(
|
||||
'testMethod',
|
||||
CompletionItemKind::METHOD,
|
||||
'\TestClass', // Return type of the method
|
||||
'Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.'
|
||||
)
|
||||
], $items);
|
||||
}
|
||||
|
||||
public function testPropertyAndMethodWithoutPrefix()
|
||||
{
|
||||
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/property.php');
|
||||
$this->project->openDocument($completionUri, file_get_contents($completionUri));
|
||||
$items = $this->textDocument->completion(
|
||||
new TextDocumentIdentifier($completionUri),
|
||||
new Position(3, 7)
|
||||
new Position(3, 6)
|
||||
)->wait();
|
||||
$this->assertEquals([
|
||||
new CompletionItem(
|
||||
|
|
Loading…
Reference in New Issue