1
0
Fork 0

feat(completion): complete function and constant aliases

pull/606/head
Declspeck 2018-02-24 15:52:20 +02:00
parent f5b1256cf9
commit 10a4592d9a
No known key found for this signature in database
GPG Key ID: F0417663122A2189
9 changed files with 311 additions and 73 deletions

View File

@ -0,0 +1,13 @@
<?php
namespace Whatever;
use const TestNamespace\InnerNamespace\INNER_CONST;
use const TestNamespace\InnerNamespace\INNER_CONST as ALIASED_CONST;
use const TestNamespace\InnerNamespace\NON_EXISTENT_CONST;
INNER_C;
ALIASED_C;
NON_EXISTENT_C;

View File

@ -0,0 +1,11 @@
<?php
namespace TestNs;
use function TestNamespace\InnerNamespace\inner_function;
use function TestNamespace\InnerNamespace\inner_function2 as second_function;
use function TestNamespace\InnerNamespace\i_dont_exist;
inner_f;
second_f;
i_dont_ex;

View File

@ -108,3 +108,8 @@ namespace TestNamespace\InnerNamespace;
class InnerClass {
}
const INNER_CONST = 333;
function inner_function(InnerClass $i) {}
function inner_function2(InnerClass $i) {}

View File

@ -389,6 +389,8 @@ class CompletionProvider
*
* Yields
* - Aliased classes
* - Aliased functions (when not creating)
* - Aliased constants (when not creating)
* - Completions from current namespace
* - Roamed completions from the global namespace (when not creating and not already in root NS)
* - PHP keywords (when not creating)
@ -403,7 +405,7 @@ class CompletionProvider
bool $requireCanBeInstantiated
): \Generator {
// Aliases
list($namespaceAliases,,) = $importTables;
list($namespaceAliases, $functionAliases, $constAliases) = $importTables;
// use Foo\Bar
yield from $this->getCompletionsForAliases(
$prefix,
@ -411,6 +413,12 @@ class CompletionProvider
$requireCanBeInstantiated,
CompletionItemKind::CLASS_
);
if (!$requireCanBeInstantiated) {
// use function Foo\createBar
yield from $this->getCompletionsForAliases($prefix, $functionAliases, false, CompletionItemKind::FUNCTION);
// use const Foo\BAR_TYPE_COCKTAIL
yield from $this->getCompletionsForAliases($prefix, $constAliases, false, CompletionItemKind::VARIABLE);
}
// Completions from the current namespace
yield from $this->getCompletionsForFqnPrefix(

View File

@ -38,8 +38,12 @@ class DefinitionCollectorTest extends TestCase
'TestNamespace\\Example->__destruct()',
'TestNamespace\\InnerNamespace',
'TestNamespace\\InnerNamespace\\InnerClass',
'TestNamespace\\InnerNamespace\\INNER_CONST',
'TestNamespace\\InnerNamespace\\inner_function()',
'TestNamespace\\InnerNamespace\\inner_function2()',
], array_keys($defNodes));
// @codingStandardsIgnoreStart
$this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\\TEST_CONST']);
$this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\TestClass']);
$this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\\TestClass::TEST_CLASS_CONST']);
@ -56,6 +60,10 @@ class DefinitionCollectorTest extends TestCase
$this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__construct()']);
$this->assertInstanceOf(Node\MethodDeclaration::class, $defNodes['TestNamespace\\Example->__destruct()']);
$this->assertInstanceOf(Node\Statement\ClassDeclaration::class, $defNodes['TestNamespace\\InnerNamespace\\InnerClass']);
$this->assertInstanceOf(Node\ConstElement::class, $defNodes['TestNamespace\InnerNamespace\INNER_CONST']);
$this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\InnerNamespace\inner_function()']);
$this->assertInstanceOf(Node\Statement\FunctionDeclaration::class, $defNodes['TestNamespace\InnerNamespace\inner_function2()']);
// @codingStandardsIgnoreEnd
}
public function testDoesNotCollectReferences()

View File

@ -110,6 +110,9 @@ abstract class ServerTestCase extends TestCase
'TestNamespace\\Example::__destruct' => new Location($symbolsUri, new Range(new Position(103, 4), new Position(103, 35))),
'TestNamespace\\InnerNamespace' => new Location($symbolsUri, new Range(new Position(106, 0), new Position(106, 39))),
'TestNamespace\\InnerNamespace\\InnerClass' => new Location($symbolsUri, new Range(new Position(108, 0), new Position(109, 1))),
'TestNamespace\\InnerNamespace\\INNER_CONST' => new Location($symbolsUri, new Range(new Position(111, 6), new Position(111, 23))),
'TestNamespace\\InnerNamespace\\inner_function()' => new Location($symbolsUri, new Range(new Position(113, 0), new Position(113, 41))),
'TestNamespace\\InnerNamespace\\inner_function2()' => new Location($symbolsUri, new Range(new Position(114, 0), new Position(114, 42))),
];
$this->referenceLocations = [

View File

@ -315,7 +315,16 @@ class CompletionTest extends TestCase
null,
null,
'AliasNamespace\\InnerClass'
)
),
new CompletionItem(
'INNER_CONST',
CompletionItemKind::VARIABLE,
'int',
null,
null,
null,
'AliasNamespace\\INNER_CONST'
),
], true),
$items
);
@ -343,6 +352,180 @@ class CompletionTest extends TestCase
null,
'AliasNamespace\InnerClass'
),
new CompletionItem(
'INNER_CONST',
CompletionItemKind::VARIABLE,
'int',
null,
null,
null,
'AliasNamespace\INNER_CONST'
),
new CompletionItem(
'inner_function',
CompletionItemKind::FUNCTION,
'mixed',
null,
null,
null,
'AliasNamespace\inner_function'
),
new CompletionItem(
'inner_function2',
CompletionItemKind::FUNCTION,
'mixed',
null,
null,
null,
'AliasNamespace\inner_function2'
),
], true),
$items
);
}
/**
* Tests completion with `use function ..inner_function`.
*/
public function testUseFunction()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_function.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 7)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'inner_function',
CompletionItemKind::FUNCTION,
'TestNamespace\InnerNamespace'
),
], true),
$items
);
}
/**
* Tests completion with `use function .. as second_function;`.
*/
public function testUseFunctionAs()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_function.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(9, 8)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'second_function',
CompletionItemKind::FUNCTION,
'TestNamespace\InnerNamespace'
),
], true),
$items
);
}
/**
* Tests completion with `use function .. as second_function;`.
*/
public function testUseFunctionNotExists()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_function.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(10, 9)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'i_dont_exist',
CompletionItemKind::FUNCTION,
'TestNamespace\InnerNamespace',
''
),
], true),
$items
);
}
/**
* Tests completion with `use const ..INNER_CONST`
*/
public function testUseConst()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_const.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 7)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'INNER_CONST',
CompletionItemKind::VARIABLE,
'int',
null,
null,
null,
'INNER_CONST'
),
], true),
$items
);
}
/**
* Tests completion with `use const .. as ALIASED_CONST;`.
*/
public function testUseConsttAs()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_const.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(10, 9)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'INNER_CONST',
CompletionItemKind::VARIABLE,
'int',
null,
null,
null,
'ALIASED_CONST'
),
], true),
$items
);
}
/**
* Tests completion with `use const NON_EXISTENT_CONST`
*/
public function testUseConsttNonExistent()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_const.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(12, 14)
)->wait();
$this->assertEquals(
new CompletionList([
new CompletionItem(
'NON_EXISTENT_CONST',
CompletionItemKind::VARIABLE,
'TestNamespace\InnerNamespace'
),
], true),
$items
);

View File

@ -35,6 +35,9 @@ class DocumentSymbolTest extends ServerTestCase
new SymbolInformation('__destruct', SymbolKind::CONSTRUCTOR, $this->getDefinitionLocation('TestNamespace\\Example::__destruct'), 'TestNamespace\\Example'),
new SymbolInformation('TestNamespace\\InnerNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('TestNamespace\\InnerNamespace'), 'TestNamespace'),
new SymbolInformation('InnerClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\InnerClass'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('INNER_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\INNER_CONST'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('inner_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\inner_function()'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('inner_function2', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\inner_function2()'),'TestNamespace\\InnerNamespace'),
], $result);
// @codingStandardsIgnoreEnd
}

View File

@ -48,6 +48,10 @@ class SymbolTest extends ServerTestCase
new SymbolInformation('__destruct', SymbolKind::CONSTRUCTOR, $this->getDefinitionLocation('TestNamespace\\Example::__destruct'), 'TestNamespace\\Example'),
new SymbolInformation('TestNamespace\\InnerNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('TestNamespace\\InnerNamespace'), 'TestNamespace'),
new SymbolInformation('InnerClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\InnerClass'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('INNER_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\INNER_CONST'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('inner_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\inner_function()'), 'TestNamespace\\InnerNamespace'),
new SymbolInformation('inner_function2', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\inner_function2()'), 'TestNamespace\InnerNamespace'),
new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\whatever()'), 'TestNamespace'),
// Global
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TEST_CONST'), ''),