parent
06747bb734
commit
b1a1875070
|
@ -0,0 +1 @@
|
||||||
|
<
|
|
@ -10,7 +10,9 @@ use LanguageServer\Protocol\{
|
||||||
Position,
|
Position,
|
||||||
CompletionList,
|
CompletionList,
|
||||||
CompletionItem,
|
CompletionItem,
|
||||||
CompletionItemKind
|
CompletionItemKind,
|
||||||
|
CompletionContext,
|
||||||
|
CompletionTriggerKind
|
||||||
};
|
};
|
||||||
use Microsoft\PhpParser;
|
use Microsoft\PhpParser;
|
||||||
use Microsoft\PhpParser\Node;
|
use Microsoft\PhpParser\Node;
|
||||||
|
@ -122,9 +124,10 @@ class CompletionProvider
|
||||||
*
|
*
|
||||||
* @param PhpDocument $doc The opened document
|
* @param PhpDocument $doc The opened document
|
||||||
* @param Position $pos The cursor position
|
* @param Position $pos The cursor position
|
||||||
|
* @param CompletionContext $context The completion context
|
||||||
* @return CompletionList
|
* @return CompletionList
|
||||||
*/
|
*/
|
||||||
public function provideCompletion(PhpDocument $doc, Position $pos): CompletionList
|
public function provideCompletion(PhpDocument $doc, Position $pos, CompletionContext $context = null): CompletionList
|
||||||
{
|
{
|
||||||
// This can be made much more performant if the tree follows specific invariants.
|
// This can be made much more performant if the tree follows specific invariants.
|
||||||
$node = $doc->getNodeAtPosition($pos);
|
$node = $doc->getNodeAtPosition($pos);
|
||||||
|
@ -152,7 +155,21 @@ class CompletionProvider
|
||||||
|
|
||||||
// Inspect the type of expression under the cursor
|
// Inspect the type of expression under the cursor
|
||||||
|
|
||||||
if ($node === null || $node instanceof Node\Statement\InlineHtml || $pos == new Position(0, 0)) {
|
$content = $doc->getContent();
|
||||||
|
$offset = $pos->toOffset($content);
|
||||||
|
if (
|
||||||
|
$node === null
|
||||||
|
|| (
|
||||||
|
$node instanceof Node\Statement\InlineHtml
|
||||||
|
&& (
|
||||||
|
$context === null
|
||||||
|
// Make sure to not suggest on the > trigger character in HTML
|
||||||
|
|| $context->triggerKind === CompletionTriggerKind::INVOKED
|
||||||
|
|| $context->triggerCharacter === '<'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|| $pos == new Position(0, 0)
|
||||||
|
) {
|
||||||
// HTML, beginning of file
|
// HTML, beginning of file
|
||||||
|
|
||||||
// Inside HTML and at the beginning of the file, propose <?php
|
// Inside HTML and at the beginning of the file, propose <?php
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LanguageServer\Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains additional information about the context in which a completion request is triggered.
|
||||||
|
*/
|
||||||
|
class CompletionContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How the completion was triggered.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $triggerKind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trigger character (a single character) that has trigger code complete.
|
||||||
|
* Is null if `triggerKind !== CompletionTriggerKind::TRIGGER_CHARACTER`
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $triggerCharacter;
|
||||||
|
|
||||||
|
public function __construct(int $triggerKind, string $triggerCharacter = null)
|
||||||
|
{
|
||||||
|
$this->triggerKind = $triggerKind;
|
||||||
|
$this->triggerCharacter = $triggerCharacter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LanguageServer\Protocol;
|
||||||
|
|
||||||
|
class CompletionTriggerKind
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Completion was triggered by invoking it manuall or using API.
|
||||||
|
*/
|
||||||
|
const INVOKED = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completion was triggered by a trigger character.
|
||||||
|
*/
|
||||||
|
const TRIGGER_CHARACTER = 2;
|
||||||
|
}
|
|
@ -20,7 +20,8 @@ use LanguageServer\Protocol\{
|
||||||
SymbolLocationInformation,
|
SymbolLocationInformation,
|
||||||
TextDocumentIdentifier,
|
TextDocumentIdentifier,
|
||||||
TextDocumentItem,
|
TextDocumentItem,
|
||||||
VersionedTextDocumentIdentifier
|
VersionedTextDocumentIdentifier,
|
||||||
|
CompletionContext
|
||||||
};
|
};
|
||||||
use Microsoft\PhpParser;
|
use Microsoft\PhpParser;
|
||||||
use Microsoft\PhpParser\Node;
|
use Microsoft\PhpParser\Node;
|
||||||
|
@ -335,13 +336,14 @@ class TextDocument
|
||||||
*
|
*
|
||||||
* @param TextDocumentIdentifier The text document
|
* @param TextDocumentIdentifier The text document
|
||||||
* @param Position $position The position
|
* @param Position $position The position
|
||||||
|
* @param CompletionContext|null $context The completion context
|
||||||
* @return Promise <CompletionItem[]|CompletionList>
|
* @return Promise <CompletionItem[]|CompletionList>
|
||||||
*/
|
*/
|
||||||
public function completion(TextDocumentIdentifier $textDocument, Position $position): Promise
|
public function completion(TextDocumentIdentifier $textDocument, Position $position, CompletionContext $context = null): Promise
|
||||||
{
|
{
|
||||||
return coroutine(function () use ($textDocument, $position) {
|
return coroutine(function () use ($textDocument, $position, $context) {
|
||||||
$document = yield $this->documentLoader->getOrLoad($textDocument->uri);
|
$document = yield $this->documentLoader->getOrLoad($textDocument->uri);
|
||||||
return $this->completionProvider->provideCompletion($document, $position);
|
return $this->completionProvider->provideCompletion($document, $position, $context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,9 @@ use LanguageServer\Protocol\{
|
||||||
Position,
|
Position,
|
||||||
CompletionList,
|
CompletionList,
|
||||||
CompletionItem,
|
CompletionItem,
|
||||||
CompletionItemKind
|
CompletionItemKind,
|
||||||
|
CompletionContext,
|
||||||
|
CompletionTriggerKind
|
||||||
};
|
};
|
||||||
use function LanguageServer\pathToUri;
|
use function LanguageServer\pathToUri;
|
||||||
|
|
||||||
|
@ -464,6 +466,41 @@ class CompletionTest extends TestCase
|
||||||
], true), $items);
|
], true), $items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHtmlPrefixShouldNotTriggerCompletion()
|
||||||
|
{
|
||||||
|
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php');
|
||||||
|
$this->loader->open($completionUri, file_get_contents($completionUri));
|
||||||
|
$items = $this->textDocument->completion(
|
||||||
|
new TextDocumentIdentifier($completionUri),
|
||||||
|
new Position(0, 1),
|
||||||
|
new CompletionContext(CompletionTriggerKind::TRIGGER_CHARACTER, '>')
|
||||||
|
)->wait();
|
||||||
|
$this->assertEquals(new CompletionList([], true), $items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHtmlPrefixShouldTriggerCompletionIfManuallyInvoked()
|
||||||
|
{
|
||||||
|
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php');
|
||||||
|
$this->loader->open($completionUri, file_get_contents($completionUri));
|
||||||
|
$items = $this->textDocument->completion(
|
||||||
|
new TextDocumentIdentifier($completionUri),
|
||||||
|
new Position(0, 1),
|
||||||
|
new CompletionContext(CompletionTriggerKind::INVOKED)
|
||||||
|
)->wait();
|
||||||
|
$this->assertEquals(new CompletionList([
|
||||||
|
new CompletionItem(
|
||||||
|
'<?php',
|
||||||
|
CompletionItemKind::KEYWORD,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new TextEdit(new Range(new Position(0, 1), new Position(0, 1)), '?php')
|
||||||
|
)
|
||||||
|
], true), $items);
|
||||||
|
}
|
||||||
|
|
||||||
public function testNamespace()
|
public function testNamespace()
|
||||||
{
|
{
|
||||||
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/namespace.php');
|
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/namespace.php');
|
||||||
|
@ -605,7 +642,7 @@ class CompletionTest extends TestCase
|
||||||
)
|
)
|
||||||
], true), $items);
|
], true), $items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testThisWithPrefix()
|
public function testThisWithPrefix()
|
||||||
{
|
{
|
||||||
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this_with_prefix.php');
|
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this_with_prefix.php');
|
||||||
|
|
Loading…
Reference in New Issue