Skip to content

Commit f5b1256

Browse files
committed
feat(completion): complete class aliases when the target does not exist
1 parent 0bc5b81 commit f5b1256

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

fixtures/completion/used_class.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Whatever;
44

5-
use TestNamespace\{TestClass, TestInterface};
5+
use TestNamespace\{TestClass, TestInterface, IDontExist};
66

7-
TestC
7+
TestC;
8+
9+
IDont;
810

911
class OtherClass {}

src/CompletionProvider.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ private function getUnqualifiedCompletions(
408408
yield from $this->getCompletionsForAliases(
409409
$prefix,
410410
$namespaceAliases,
411-
$requireCanBeInstantiated
411+
$requireCanBeInstantiated,
412+
CompletionItemKind::CLASS_
412413
);
413414

414415
// Completions from the current namespace
@@ -471,13 +472,15 @@ private function getCompletionsForFqnPrefix(
471472
*
472473
* @param string $prefix Non-qualified name being completed for
473474
* @param QualifiedName[] $aliases Array of alias FQNs indexed by the alias.
475+
* @param int $defaultSymbolKind The SymbolKind:: constant to use when the definition for the alias is not found.
474476
* @return \Generator|CompletionItem[]
475477
* Yields CompletionItems.
476478
*/
477479
private function getCompletionsForAliases(
478480
string $prefix,
479481
array $aliases,
480-
bool $requireCanBeInstantiated
482+
bool $requireCanBeInstantiated,
483+
int $defaultCompletionItemKind
481484
): \Generator {
482485
foreach ($aliases as $alias => $aliasFqn) {
483486
if (!nameStartsWith($alias, $prefix)) {
@@ -491,6 +494,11 @@ private function getCompletionsForAliases(
491494
$completionItem = CompletionItem::fromDefinition($definition);
492495
$completionItem->insertText = $alias;
493496
yield (string)$aliasFqn => $completionItem;
497+
} else {
498+
// Use clause referred to a symbol which was not indexed.
499+
$completionItem = new CompletionItem($alias, $defaultCompletionItemKind);
500+
$completionItem->detail = nameGetParent((string)$aliasFqn);
501+
yield (string)$aliasFqn => $completionItem;
494502
}
495503
}
496504
}

tests/Server/TextDocument/CompletionTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,29 @@ public function testUsedClass()
271271
$this->assertCompletionsListDoesNotContainLabel('TestInterface', $items);
272272
}
273273

274+
/**
275+
* Tests completion at `IDontE|` with `use TestNamespace\IDontExist`
276+
*/
277+
public function testUsedClassNonExistent()
278+
{
279+
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_class.php');
280+
$this->loader->open($completionUri, file_get_contents($completionUri));
281+
$items = $this->textDocument->completion(
282+
new TextDocumentIdentifier($completionUri),
283+
new Position(8, 5)
284+
)->wait();
285+
$this->assertEquals(new CompletionList([
286+
new CompletionItem(
287+
'IDontExist',
288+
CompletionItemKind::CLASS_,
289+
'TestNamespace'
290+
)
291+
], true), $items);
292+
293+
$this->assertCompletionsListDoesNotContainLabel('OtherClass', $items);
294+
$this->assertCompletionsListDoesNotContainLabel('TestInterface', $items);
295+
}
296+
274297
/**
275298
* Tests completion at `AliasNamespace\I|` with `use TestNamespace\InnerNamespace as AliasNamespace`
276299
*/

0 commit comments

Comments
 (0)