diff --git a/src/Server/Workspace.php b/src/Server/Workspace.php index 7527e2e..98184ba 100644 --- a/src/Server/Workspace.php +++ b/src/Server/Workspace.php @@ -224,12 +224,13 @@ class Workspace * Currently only the vscode format is supported * * @param mixed|null $settings - * @return void + * @return bool + * @throws \Exception Settings format not valid */ - public function didChangeConfiguration($settings = null) + public function didChangeConfiguration($settings = null): bool { if ($settings === null) { - return; + return false; } // VSC sends the settings with the config section as main key @@ -239,13 +240,13 @@ class Workspace } if (!($settings instanceof Options)) { - return; + throw new \Exception('Settings format not valid.'); } $changedOptions = $this->getChangedOptions($settings); if (empty($changedOptions)) { - return; + return false; } foreach (get_object_vars($settings) as $prop => $val) { @@ -259,6 +260,8 @@ class Workspace $this->index->wipe(); $this->indexer->index()->otherwise('\\LanguageServer\\crash'); } + + return true; } /** diff --git a/tests/Server/ServerTestCase.php b/tests/Server/ServerTestCase.php index 7bee051..5d9e309 100644 --- a/tests/Server/ServerTestCase.php +++ b/tests/Server/ServerTestCase.php @@ -31,10 +31,6 @@ abstract class ServerTestCase extends TestCase */ protected $documentLoader; - protected $projectIndex; - protected $input; - protected $output; - /** * Map from FQN to Location of definition * @@ -53,23 +49,20 @@ abstract class ServerTestCase extends TestCase { $sourceIndex = new Index; $dependenciesIndex = new DependenciesIndex; - $this->projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); - $this->projectIndex->setComplete(); + $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); + $projectIndex->setComplete(); $rootPath = realpath(__DIR__ . '/../../fixtures/'); $options = new Options; $filesFinder = new FileSystemFilesFinder; $cache = new FileSystemCache; - $this->input = new MockProtocolStream; - $this->output = new MockProtocolStream; - - $definitionResolver = new DefinitionResolver($this->projectIndex); - $client = new LanguageClient($this->input, $this->output); - $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $this->projectIndex, $definitionResolver); - $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $this->projectIndex); + $definitionResolver = new DefinitionResolver($projectIndex); + $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); $indexer = new Indexer($filesFinder, $rootPath, $client, $cache, $dependenciesIndex, $sourceIndex, $this->documentLoader, null, null, $options); - $this->workspace = new Server\Workspace($client, $this->projectIndex, $dependenciesIndex, $sourceIndex, null, $this->documentLoader, null, $indexer, $options); + $this->workspace = new Server\Workspace($client, $projectIndex, $dependenciesIndex, $sourceIndex, null, $this->documentLoader, null, $indexer, $options); $globalSymbolsUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_symbols.php')); $globalReferencesUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_references.php')); diff --git a/tests/Server/Workspace/DidChangeConfigurationTest.php b/tests/Server/Workspace/DidChangeConfigurationTest.php index 8479764..e0ad2ea 100644 --- a/tests/Server/Workspace/DidChangeConfigurationTest.php +++ b/tests/Server/Workspace/DidChangeConfigurationTest.php @@ -3,51 +3,135 @@ declare(strict_types = 1); namespace LanguageServer\Tests\Server\Workspace; -use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\Server\ServerTestCase; -use LanguageServer\{Server, Client, LanguageClient, Project, PhpDocument, Options}; -use LanguageServer\Protocol\{ - Message, - MessageType, - TextDocumentItem, - TextDocumentIdentifier, - SymbolInformation, - SymbolKind, - DiagnosticSeverity, - FormattingOptions, - Location, - Range, - Position -}; -use AdvancedJsonRpc\{Request as RequestBody, Response as ResponseBody}; -use function LanguageServer\pathToUri; +use LanguageServer\Tests\MockProtocolStream; +use LanguageServer\{Server, LanguageClient, PhpDocumentLoader, DefinitionResolver, Options, Indexer}; +use LanguageServer\Index\{ProjectIndex, StubsIndex, GlobalIndex, DependenciesIndex, Index}; +use LanguageServer\ContentRetriever\FileSystemContentRetriever; +use LanguageServer\Protocol\{Position, Location, Range, ClientCapabilities, Message, MessageType}; +use LanguageServer\FilesFinder\FileSystemFilesFinder; +use LanguageServer\Cache\FileSystemCache; +use LanguageServer\Server\Workspace; use Sabre\Event\Promise; use Exception; class DidChangeConfigurationTest extends ServerTestCase { - public function testWipingIndex() + /** + * didChangeConfiguration does not need to do anything when no options/settings are passed + */ + public function test_no_option_passed() { - $promise = new Promise; + $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); + + $result = $workspace->didChangeConfiguration(); + $this->assertFalse($result); + } + + /** + * When the passed options/settings do not differ from the previous, it has nothing to do + */ + public function test_fails_with_invalid_options_type_or_format() + { + $options = new Options; + $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, null, null, null, $options); + + $this->expectException(\Exception::class); + $this->workspace->didChangeConfiguration(['invalid' => 'options format']); + } + + /** + * When the passed options/settings do not differ from the previous, it has nothing to do + */ + public function test_no_changed_options() + { + $options = new Options; + $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, null, null, null, $options); + + $result = $this->workspace->didChangeConfiguration($options); + $this->assertFalse($result); + } + + /** + * Verify that the required methods for a reindex are called + */ + public function test_fileTypes_option_triggers_a_reindex() + { + $sourceIndex = new Index; + $dependenciesIndex = new DependenciesIndex; + $projectIndex = $this->getMockBuilder('LanguageServer\Index\ProjectIndex') + ->setConstructorArgs([$sourceIndex, $dependenciesIndex]) + ->setMethods(['wipe']) + ->getMock(); + $projectIndex->setComplete(); + + $rootPath = realpath(__DIR__ . '/../../../fixtures/'); + $filesFinder = new FileSystemFilesFinder; + $cache = new FileSystemCache; + + $definitionResolver = new DefinitionResolver($projectIndex); + $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); + $documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); + $textDocument = new Server\TextDocument($documentLoader, $definitionResolver, $client, $projectIndex); + $indexer = $this->getMockBuilder('LanguageServer\Indexer') + ->setConstructorArgs([$filesFinder, $rootPath, $client, $cache, $dependenciesIndex, $sourceIndex, $documentLoader, null, null, new Options]) + ->setMethods(['index']) + ->getMock(); + $workspace = new Server\Workspace($client, $projectIndex, $dependenciesIndex, $sourceIndex, null, $documentLoader, null, $indexer, new Options); - $this->projectIndex->on('wipe', function() use ($promise) { - $promise->fulfill(); - }); $options = new Options; $options->fileTypes = [ '.inc' ]; - $this->workspace->didChangeConfiguration($options); - $promise->wait(); + $projectIndex->expects($this->once())->method('wipe'); + $indexer->expects($this->once())->method('index'); + + // invoke event + $result = $workspace->didChangeConfiguration($options); + $this->assertTrue($result); } - public function testReindexingAfterWipe() + /** + * Be sure that the indexer gets the new options/settings and uses them + */ + public function test_indexer_uses_new_options() { $promise = new Promise; + $sourceIndex = new Index; + $dependenciesIndex = new DependenciesIndex; + $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); + $projectIndex->setComplete(); - $this->output->on('message', function (Message $msg) use ($promise) { + $rootPath = realpath(__DIR__ . '/../../../fixtures/'); + $filesFinder = new FileSystemFilesFinder; + $cache = new FileSystemCache; + $initialOptions = new Options; + + $input = new MockProtocolStream; + $output = new MockProtocolStream; + + $definitionResolver = new DefinitionResolver($projectIndex); + $client = new LanguageClient($input, $output); + $documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); + $textDocument = new Server\TextDocument($documentLoader, $definitionResolver, $client, $projectIndex); + $indexer = new Indexer($filesFinder, $rootPath, $client, $cache, $dependenciesIndex, $sourceIndex, $documentLoader, null, null, $initialOptions); + $workspace = new Server\Workspace($client, $projectIndex, $dependenciesIndex, $sourceIndex, null, $documentLoader, null, $indexer, $initialOptions); + + $output->on('message', function (Message $msg) use ($promise) { if ($msg->body->method === 'window/logMessage' && $promise->state === Promise::PENDING) { if ($msg->body->params->type === MessageType::ERROR) { $promise->reject(new Exception($msg->body->params->message)); @@ -62,11 +146,8 @@ class DidChangeConfigurationTest extends ServerTestCase '.inc' ]; - $this->workspace->didChangeConfiguration($options); + $result = $workspace->didChangeConfiguration($options); + $this->assertTrue($result); $promise->wait(); } - - public function testGetChangedOptions() - { - } }