Skip to content

Commit

Permalink
fix(completion): don't suggest <?php on > characer
Browse files Browse the repository at this point in the history
closes #372
  • Loading branch information
felixfbecker committed Nov 15, 2017
1 parent 1ec8d8d commit 3cf3401
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 9 deletions.
1 change: 1 addition & 0 deletions fixtures/completion/html_no_completion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<
23 changes: 20 additions & 3 deletions src/CompletionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
Position,
CompletionList,
CompletionItem,
CompletionItemKind
CompletionItemKind,
CompletionContext,
CompletionTriggerKind
};
use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
Expand Down Expand Up @@ -122,9 +124,10 @@ public function __construct(DefinitionResolver $definitionResolver, ReadableInde
*
* @param PhpDocument $doc The opened document
* @param Position $pos The cursor position
* @param CompletionContext $context The completion context
* @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.
$node = $doc->getNodeAtPosition($pos);
Expand Down Expand Up @@ -152,7 +155,21 @@ public function provideCompletion(PhpDocument $doc, Position $pos): CompletionLi

// 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

// Inside HTML and at the beginning of the file, propose <?php
Expand Down
30 changes: 30 additions & 0 deletions src/Protocol/CompletionContext.php
Original file line number Diff line number Diff line change
@@ -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;
}
}
16 changes: 16 additions & 0 deletions src/Protocol/CompletionTriggerKind.php
Original file line number Diff line number Diff line change
@@ -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;
}
10 changes: 6 additions & 4 deletions src/Server/TextDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
SymbolLocationInformation,
TextDocumentIdentifier,
TextDocumentItem,
VersionedTextDocumentIdentifier
VersionedTextDocumentIdentifier,
CompletionContext
};
use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
Expand Down Expand Up @@ -335,13 +336,14 @@ public function hover(TextDocumentIdentifier $textDocument, Position $position):
*
* @param TextDocumentIdentifier The text document
* @param Position $position The position
* @param CompletionContext|null $context The completion context
* @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);
return $this->completionProvider->provideCompletion($document, $position);
return $this->completionProvider->provideCompletion($document, $position, $context);
});
}

Expand Down
41 changes: 39 additions & 2 deletions tests/Server/TextDocument/CompletionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
Position,
CompletionList,
CompletionItem,
CompletionItemKind
CompletionItemKind,
CompletionContext,
CompletionTriggerKind
};
use function LanguageServer\pathToUri;

Expand Down Expand Up @@ -464,6 +466,41 @@ public function testHtmlWithPrefix()
], 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()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/namespace.php');
Expand Down Expand Up @@ -605,7 +642,7 @@ public function testThisWithoutPrefix()
)
], true), $items);
}

public function testThisWithPrefix()
{
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this_with_prefix.php');
Expand Down

0 comments on commit 3cf3401

Please sign in to comment.