Skip to content

Ensure diagnostics are cleared on file deletion #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/LanguageServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath =
}
if ($this->workspace === null) {
$this->workspace = new Server\Workspace(
$this->client,
$this->projectIndex,
$dependenciesIndex,
$sourceIndex,
Expand Down
10 changes: 10 additions & 0 deletions src/Protocol/FileEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,14 @@ class FileEvent
* @var int
*/
public $type;

/**
* @param string $uri
* @param int $type
*/
public function __construct(string $uri, int $type)
{
$this->uri = $uri;
$this->type = $type;
}
}
34 changes: 32 additions & 2 deletions src/Server/Workspace.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@

use LanguageServer\{LanguageClient, Project, PhpDocumentLoader};
use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
use LanguageServer\Protocol\{SymbolInformation, SymbolDescriptor, ReferenceInformation, DependencyReference, Location};
use LanguageServer\Protocol\{
FileChangeType,
FileEvent,
SymbolInformation,
SymbolDescriptor,
ReferenceInformation,
DependencyReference,
Location
};
use Sabre\Event\Promise;
use function Sabre\Event\coroutine;
use function LanguageServer\{waitForEvent, getPackageName};
Expand All @@ -15,6 +23,11 @@
*/
class Workspace
{
/**
* @var LanguageClient
*/
public $client;

/**
* The symbol index for the workspace
*
Expand Down Expand Up @@ -43,14 +56,16 @@ class Workspace
public $documentLoader;

/**
* @param LanguageClient $client LanguageClient instance used to signal updated results
* @param ProjectIndex $index Index that is searched on a workspace/symbol request
* @param DependenciesIndex $dependenciesIndex Index that is used on a workspace/xreferences request
* @param DependenciesIndex $sourceIndex Index that is used on a workspace/xreferences request
* @param \stdClass $composerLock The parsed composer.lock of the project, if any
* @param PhpDocumentLoader $documentLoader PhpDocumentLoader instance to load documents
*/
public function __construct(ProjectIndex $index, DependenciesIndex $dependenciesIndex, Index $sourceIndex, \stdClass $composerLock = null, PhpDocumentLoader $documentLoader, \stdClass $composerJson = null)
public function __construct(LanguageClient $client, ProjectIndex $index, DependenciesIndex $dependenciesIndex, Index $sourceIndex, \stdClass $composerLock = null, PhpDocumentLoader $documentLoader, \stdClass $composerJson = null)
{
$this->client = $client;
$this->sourceIndex = $sourceIndex;
$this->index = $index;
$this->dependenciesIndex = $dependenciesIndex;
Expand Down Expand Up @@ -82,6 +97,21 @@ public function symbol(string $query): Promise
});
}

/**
* The watched files notification is sent from the client to the server when the client detects changes to files watched by the language client.
*
* @param FileEvent[] $changes
* @return void
*/
public function didChangeWatchedFiles(array $changes)
{
foreach ($changes as $change) {
if ($change->type === FileChangeType::DELETED) {
$this->client->textDocument->publishDiagnostics($change->uri, []);
}
}
}

/**
* The workspace references request is sent from the client to the server to locate project-wide references to a symbol given its description / metadata.
*
Expand Down
2 changes: 1 addition & 1 deletion tests/Server/ServerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function setUp()
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex);
$this->workspace = new Server\Workspace($projectIndex, $dependenciesIndex, $sourceIndex, null, $this->documentLoader);
$this->workspace = new Server\Workspace($client, $projectIndex, $dependenciesIndex, $sourceIndex, null, $this->documentLoader);

$globalSymbolsUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_symbols.php'));
$globalReferencesUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_references.php'));
Expand Down
41 changes: 41 additions & 0 deletions tests/Server/Workspace/DidChangeWatchedFilesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\Tests\Server\Workspace;

use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\{DefinitionResolver, LanguageClient, PhpDocumentLoader, Server};
use LanguageServer\Index\{DependenciesIndex, Index, ProjectIndex};
use LanguageServer\Protocol\{FileChangeType, FileEvent, Message};
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\Server\Workspace;
use Sabre\Event\Loop;

class DidChangeWatchedFilesTest extends ServerTestCase
{
public function testDeletingFileClearsAllDiagnostics()
{
$client = new LanguageClient(new MockProtocolStream(), $writer = new MockProtocolStream());
$projectIndex = new ProjectIndex($sourceIndex = new Index(), $dependenciesIndex = new DependenciesIndex());
$definitionResolver = new DefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever(), $projectIndex, $definitionResolver);
$workspace = new Server\Workspace($client, $projectIndex, $dependenciesIndex, $sourceIndex, null, $loader, null);

$fileEvent = new FileEvent('my uri', FileChangeType::DELETED);

$isDiagnosticsCleared = false;
$writer->on('message', function (Message $message) use ($fileEvent, &$isDiagnosticsCleared) {
if ($message->body->method === "textDocument/publishDiagnostics") {
$this->assertEquals($message->body->params->uri, $fileEvent->uri);
$this->assertEquals($message->body->params->diagnostics, []);
$isDiagnosticsCleared = true;
}
});

$workspace->didChangeWatchedFiles([$fileEvent]);
Loop\tick(true);

$this->assertTrue($isDiagnosticsCleared, "Deleting file should clear all diagnostics.");
}
}