1
0
Fork 0

fix tests

pull/746/head
Robert Lu 2019-06-18 16:59:40 +08:00
parent 60ed930a50
commit a5433b211a
24 changed files with 2013 additions and 1770 deletions

View File

@ -1,43 +1,48 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase;
use LanguageServer\ClientHandler;
use LanguageServer\Message;
use AdvancedJsonRpc;
use Sabre\Event\Loop;
use Amp\Loop;
use LanguageServer\ClientHandler;
use LanguageServer\Event\MessageEvent;
use LanguageServer\Message;
use PHPUnit\Framework\TestCase;
class ClientHandlerTest extends TestCase
{
public function testRequest()
{
Loop::run(function () {
$reader = new MockProtocolStream;
$writer = new MockProtocolStream;
$handler = new ClientHandler($reader, $writer);
$writer->once('message', function (Message $msg) use ($reader) {
$writer->addOneTimeListener('message', function (MessageEvent $messageEvent) use ($reader) {
$msg = $messageEvent->getMessage();
// Respond to request
Loop\setTimeout(function () use ($reader, $msg) {
$reader->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, 'pong')));
}, 0);
Loop::defer(function () use ($reader, $msg) {
yield from $reader->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, 'pong')));
});
$handler->request('testMethod', ['ping'])->then(function ($result) {
});
$result = yield from $handler->request('testMethod', ['ping']);
$this->assertEquals('pong', $result);
})->wait();
// No event listeners
$this->assertEquals([], $reader->listeners('message'));
$this->assertEquals([], $writer->listeners('message'));
$this->assertEquals([], $reader->getListeners('message'));
$this->assertEquals([], $writer->getListeners('message'));
});
}
public function testNotify()
{
Loop::run(function () {
$reader = new MockProtocolStream;
$writer = new MockProtocolStream;
$handler = new ClientHandler($reader, $writer);
$handler->notify('testMethod', ['ping'])->wait();
yield from $handler->notify('testMethod', ['ping']);
// No event listeners
$this->assertEquals([], $reader->listeners('message'));
$this->assertEquals([], $writer->listeners('message'));
$this->assertEquals([], $reader->getListeners('message'));
$this->assertEquals([], $writer->getListeners('message'));
});
}
}

View File

@ -1,35 +1,36 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase;
use AdvancedJsonRpc;
use Amp\Deferred;
use Amp\Loop;
use Exception;
use LanguageServer\Event\MessageEvent;
use LanguageServer\LanguageServer;
use LanguageServer\Message;
use LanguageServerProtocol\{
ClientCapabilities,
TextDocumentSyncKind,
MessageType,
TextDocumentItem,
TextDocumentIdentifier,
InitializeResult,
ServerCapabilities,
use LanguageServerProtocol\{ClientCapabilities,
CompletionOptions,
SignatureHelpOptions
};
use AdvancedJsonRpc;
InitializeResult,
MessageType,
ServerCapabilities,
SignatureHelpOptions,
TextDocumentIdentifier,
TextDocumentItem,
TextDocumentSyncKind};
use PHPUnit\Framework\TestCase;
use Webmozart\Glob\Glob;
use Webmozart\PathUtil\Path;
use Sabre\Event\Promise;
use Exception;
use function LanguageServer\pathToUri;
class LanguageServerTest extends TestCase
{
public function testInitialize()
{
Loop::run(function () {
$server = new LanguageServer(new MockProtocolStream, new MockProtocolStream);
$result = $server->initialize(new ClientCapabilities, __DIR__, getmypid())->wait();
$result = yield $server->initialize(new ClientCapabilities, __DIR__, getmypid());
$serverCapabilities = new ServerCapabilities();
$serverCapabilities->textDocumentSync = TextDocumentSyncKind::FULL;
@ -48,38 +49,47 @@ class LanguageServerTest extends TestCase
$serverCapabilities->xdependenciesProvider = true;
$this->assertEquals(new InitializeResult($serverCapabilities), $result);
});
}
public function testIndexingWithDirectFileAccess()
{
$promise = new Promise;
Loop::run(function () {
$deferred = new Deferred();
$input = new MockProtocolStream;
$output = new MockProtocolStream;
$output->on('message', function (Message $msg) use ($promise) {
if ($msg->body->method === 'window/logMessage' && $promise->state === Promise::PENDING) {
$output->addListener('message', function (MessageEvent $messageEvent) use ($deferred) {
$msg = $messageEvent->getMessage();
Loop::defer(function () use ($deferred, $msg) {
if ($msg->body->method === 'window/logMessage') {
if ($msg->body->params->type === MessageType::ERROR) {
$promise->reject(new Exception($msg->body->params->message));
$deferred->fail(new Exception($msg->body->params->message));
} else if (preg_match('/All \d+ PHP files parsed/', $msg->body->params->message)) {
$promise->fulfill();
$deferred->resolve(true);
}
}
});
});
$server = new LanguageServer($input, $output);
$capabilities = new ClientCapabilities;
$server->initialize($capabilities, realpath(__DIR__ . '/../fixtures'), getmypid());
$promise->wait();
yield $server->initialize($capabilities, realpath(__DIR__ . '/../fixtures'), getmypid());
$this->assertTrue(yield $deferred->promise());
});
}
public function testIndexingWithFilesAndContentRequests()
{
$promise = new Promise;
Loop::run(function () {
$deferred = new Deferred();
$filesCalled = false;
$contentCalled = false;
$rootPath = realpath(__DIR__ . '/../fixtures');
$input = new MockProtocolStream;
$output = new MockProtocolStream;
$run = 1;
$output->on('message', function (Message $msg) use ($promise, $input, $rootPath, &$filesCalled, &$contentCalled, &$run) {
$output->addListener('message', function (MessageEvent $messageEvent) use ($deferred, $input, $rootPath, &$filesCalled, &$contentCalled, &$run) {
$msg = $messageEvent->getMessage();
Loop::defer(function () use ($msg, $deferred, $input, $rootPath, &$filesCalled, &$contentCalled, &$run) {
if ($msg->body->method === 'textDocument/xcontent') {
// Document content requested
$contentCalled = true;
@ -88,7 +98,7 @@ class LanguageServerTest extends TestCase
$textDocumentItem->version = 1;
$textDocumentItem->languageId = 'php';
$textDocumentItem->text = file_get_contents($msg->body->params->textDocument->uri);
$input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $textDocumentItem)));
yield from $input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $textDocumentItem)));
} else if ($msg->body->method === 'workspace/xfiles') {
// Files requested
$filesCalled = true;
@ -97,26 +107,26 @@ class LanguageServerTest extends TestCase
foreach (Glob::glob($pattern) as $path) {
$files[] = new TextDocumentIdentifier(pathToUri($path));
}
$input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $files)));
yield from $input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $files)));
} else if ($msg->body->method === 'window/logMessage') {
// Message logged
if ($msg->body->params->type === MessageType::ERROR) {
// Error happened during indexing, fail test
if ($promise->state === Promise::PENDING) {
$promise->reject(new Exception($msg->body->params->message));
}
$deferred->fail(new Exception($msg->body->params->message));
} else if (preg_match('/All \d+ PHP files parsed/', $msg->body->params->message)) {
$promise->fulfill();
$deferred->resolve(true);
}
}
});
});
$server = new LanguageServer($input, $output);
$capabilities = new ClientCapabilities;
$capabilities->xfilesProvider = true;
$capabilities->xcontentProvider = true;
$server->initialize($capabilities, $rootPath, getmypid());
$promise->wait();
yield $server->initialize($capabilities, $rootPath, getmypid());
yield $deferred->promise();
$this->assertTrue($filesCalled);
$this->assertTrue($contentCalled);
});
}
}

View File

@ -1,11 +1,15 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests;
use LanguageServer\{ProtocolReader, ProtocolWriter};
use Amp\Deferred;
use Amp\Delayed;
use Amp\Loop;
use LanguageServer\{Event\MessageEvent, ProtocolReader, ProtocolWriter};
use LanguageServer\Message;
use Sabre\Event\{Loop, Emitter, Promise};
use League\Event\Emitter;
use League\Event\Event;
/**
* A fake duplex protocol stream
@ -18,11 +22,11 @@ class MockProtocolStream extends Emitter implements ProtocolReader, ProtocolWrit
* @param Message $msg
* @return void
*/
public function write(Message $msg): Promise
public function write(Message $msg): \Generator
{
Loop\nextTick(function () use ($msg) {
$this->emit('message', [Message::parse((string)$msg)]);
Loop::defer(function () use ($msg) {
$this->emit(new MessageEvent('message', Message::parse((string)$msg)));
});
return Promise\resolve(null);
yield new Delayed(0);
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server;
use Amp\Loop;
use LanguageServer\{
PhpDocument, PhpDocumentLoader, Project, DefinitionResolver
};
@ -32,10 +33,12 @@ class PhpDocumentLoaderTest extends TestCase
public function testGetOrLoadLoadsDocument()
{
$document = $this->loader->getOrLoad(pathToUri(__FILE__))->wait();
Loop::run(function () {
$document = yield from $this->loader->getOrLoad(pathToUri(__FILE__));
$this->assertNotNull($document);
$this->assertInstanceOf(PhpDocument::class, $document);
});
}
public function testGetReturnsOpenedInstance()

View File

@ -1,32 +1,49 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase;
use LanguageServer\{LanguageServer, ProtocolStreamReader, ProtocolStreamWriter};
use AdvancedJsonRpc\{Request as RequestBody};
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Deferred;
use Amp\Loop;
use LanguageServer\{Event\MessageEvent, ProtocolStreamReader};
use LanguageServer\Message;
use AdvancedJsonRpc\{Request as RequestBody, Response as ResponseBody};
use Sabre\Event\Loop;
use PHPUnit\Framework\TestCase;
class ProtocolStreamReaderTest extends TestCase
{
public function getStreamPair()
{
$domain = \stripos(PHP_OS, "win") === 0 ? STREAM_PF_INET : STREAM_PF_UNIX;
list($left, $right) = @\stream_socket_pair($domain, \STREAM_SOCK_STREAM, \STREAM_IPPROTO_IP);
$a = new ResourceOutputStream($left);
$b = new ResourceInputStream($right);
return [$a, $b];
}
public function testParsingWorksAndListenerIsCalled()
{
$tmpfile = tempnam('', '');
$writeHandle = fopen($tmpfile, 'w');
$reader = new ProtocolStreamReader(fopen($tmpfile, 'r'));
$msg = null;
$reader->on('message', function (Message $message) use (&$msg) {
$msg = $message;
Loop::run(function () {
/** @var ResourceOutputStream $outputStream */
/** @var ResourceInputStream $inputStream */
list($outputStream, $inputStream) = $this->getStreamPair();
$reader = new ProtocolStreamReader($inputStream);
$deferred = new Deferred();
$reader->addListener('message', function (MessageEvent $messageEvent) use (&$deferred) {
$deferred->resolve($messageEvent->getMessage());
});
$ret = fwrite($writeHandle, (string)new Message(new RequestBody(1, 'aMethod', ['arg' => 'Hello World'])));
Loop\tick();
yield $outputStream->write((string)new Message(new RequestBody(1, 'aMethod', ['arg' => 'Hello World'])));
$msg = yield $deferred->promise();
$this->assertNotNull($msg);
$this->assertInstanceOf(Message::class, $msg);
$this->assertInstanceOf(RequestBody::class, $msg->body);
$this->assertEquals(1, $msg->body->id);
$this->assertEquals('aMethod', $msg->body->method);
$this->assertEquals((object)['arg' => 'Hello World'], $msg->body->params);
});
}
}

View File

@ -1,35 +0,0 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase;
use LanguageServer\ProtocolStreamWriter;
use LanguageServer\Message;
use AdvancedJsonRpc\{Request as RequestBody};
use Sabre\Event\Loop;
class ProtocolStreamWriterTest extends TestCase
{
public function testLargeMessageIsSent()
{
$tmpfile = tempnam('', '');
$writeHandle = fopen($tmpfile, 'w');
stream_set_blocking($writeHandle, false);
$writer = new ProtocolStreamWriter($writeHandle);
$msg = new Message(new RequestBody(1, 'aMethod', ['arg' => str_repeat('X', 100000)]));
$msgString = (string)$msg;
$promise = $writer->write($msg);
Loop\tick();
$promise->wait();
fclose($writeHandle);
$this->assertEquals(strlen($msgString), filesize($tmpfile));
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
@ -46,6 +47,7 @@ abstract class ServerTestCase extends TestCase
public function setUp()
{
Loop::run(function () {
$sourceIndex = new Index;
$dependenciesIndex = new DependenciesIndex;
$projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
@ -63,18 +65,18 @@ abstract class ServerTestCase extends TestCase
$referencesUri = pathToUri(realpath(__DIR__ . '/../../fixtures/references.php'));
$useUri = pathToUri(realpath(__DIR__ . '/../../fixtures/use.php'));
$this->documentLoader->load($symbolsUri)->wait();
$this->documentLoader->load($referencesUri)->wait();
$this->documentLoader->load($globalSymbolsUri)->wait();
$this->documentLoader->load($globalReferencesUri)->wait();
$this->documentLoader->load($useUri)->wait();
yield from $this->documentLoader->load($symbolsUri);
yield from $this->documentLoader->load($referencesUri);
yield from $this->documentLoader->load($globalSymbolsUri);
yield from $this->documentLoader->load($globalReferencesUri);
yield from $this->documentLoader->load($useUri);
// @codingStandardsIgnoreStart
$this->definitionLocations = [
// Global
'TEST_DEFINE_CONSTANT' => new Location($globalSymbolsUri, new Range(new Position(104, 0), new Position(104, 37))),
'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position(9, 6), new Position(9, 22))),
'TestClass' => new Location($globalSymbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
'ChildClass' => new Location($globalSymbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
'TestTrait' => new Location($globalSymbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
@ -86,14 +88,14 @@ abstract class ServerTestCase extends TestCase
'TestClass::testMethod()' => new Location($globalSymbolsUri, new Range(new Position(57, 4), new Position(60, 5))),
'test_function()' => new Location($globalSymbolsUri, new Range(new Position(78, 0), new Position(81, 1))),
'UnusedClass' => new Location($globalSymbolsUri, new Range(new Position(111, 0), new Position(118, 1))),
'UnusedClass::unusedProperty' => new Location($globalSymbolsUri, new Range(new Position(113,11), new Position(113, 26))),
'UnusedClass::unusedProperty' => new Location($globalSymbolsUri, new Range(new Position(113, 11), new Position(113, 26))),
'UnusedClass::unusedMethod' => new Location($globalSymbolsUri, new Range(new Position(115, 4), new Position(117, 5))),
'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))),
// Namespaced
'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 0), new Position( 2, 24))),
'SecondTestNamespace' => new Location($useUri, new Range(new Position( 2, 0), new Position( 2, 30))),
'TestNamespace\\TEST_CONST' => new Location($symbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
'TestNamespace' => new Location($symbolsUri, new Range(new Position(2, 0), new Position(2, 24))),
'SecondTestNamespace' => new Location($useUri, new Range(new Position(2, 0), new Position(2, 30))),
'TestNamespace\\TEST_CONST' => new Location($symbolsUri, new Range(new Position(9, 6), new Position(9, 22))),
'TestNamespace\\TestClass' => new Location($symbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
'TestNamespace\\ChildClass' => new Location($symbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
'TestNamespace\\TestTrait' => new Location($symbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
@ -117,23 +119,23 @@ abstract class ServerTestCase extends TestCase
// Namespaced
'TestNamespace' => [
0 => new Location($referencesUri, new Range(new Position(31, 13), new Position(31, 40))), // use function TestNamespace\test_function;
1 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass;
2 => new Location($useUri, new Range(new Position( 5, 4), new Position( 5, 18))) // use TestNamespace\{TestTrait, TestInterface};
1 => new Location($useUri, new Range(new Position(4, 4), new Position(4, 27))), // use TestNamespace\TestClass;
2 => new Location($useUri, new Range(new Position(5, 4), new Position(5, 18))) // use TestNamespace\{TestTrait, TestInterface};
],
'TestNamespace\\TEST_CONST' => [
0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15)))
],
'TestNamespace\\TestClass' => [
0 => new Location($symbolsUri, new Range(new Position(48, 13), new Position(48, 17))), // echo self::TEST_CLASS_CONST;
1 => new Location($symbolsUri , new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {}
2 => new Location($referencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass();
3 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod();
4 => new Location($referencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty;
5 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST;
1 => new Location($symbolsUri, new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {}
2 => new Location($referencesUri, new Range(new Position(4, 11), new Position(4, 20))), // $obj = new TestClass();
3 => new Location($referencesUri, new Range(new Position(7, 0), new Position(7, 9))), // TestClass::staticTestMethod();
4 => new Location($referencesUri, new Range(new Position(8, 5), new Position(8, 14))), // echo TestClass::$staticTestProperty;
5 => new Location($referencesUri, new Range(new Position(9, 5), new Position(9, 14))), // TestClass::TEST_CLASS_CONST;
6 => new Location($referencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param)
7 => new Location($referencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass
8 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty;
9 => new Location($useUri, new Range(new Position( 4, 4), new Position( 4, 27))), // use TestNamespace\TestClass;
9 => new Location($useUri, new Range(new Position(4, 4), new Position(4, 27))), // use TestNamespace\TestClass;
],
'TestNamespace\\TestChild' => [
0 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 25))), // echo $child->testProperty;
@ -145,23 +147,23 @@ abstract class ServerTestCase extends TestCase
],
'TestNamespace\\TestClass::TEST_CLASS_CONST' => [
0 => new Location($symbolsUri, new Range(new Position(48, 13), new Position(48, 35))), // echo self::TEST_CLASS_CONSTANT
1 => new Location($referencesUri, new Range(new Position( 9, 5), new Position( 9, 32)))
1 => new Location($referencesUri, new Range(new Position(9, 5), new Position(9, 32)))
],
'TestNamespace\\TestClass::testProperty' => [
0 => new Location($symbolsUri, new Range(new Position(59, 8), new Position(59, 27))), // $this->testProperty = $testParameter;
1 => new Location($referencesUri, new Range(new Position( 6, 5), new Position( 6, 23))), // echo $obj->testProperty;
1 => new Location($referencesUri, new Range(new Position(6, 5), new Position(6, 23))), // echo $obj->testProperty;
2 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 18))), // $obj->testProperty->testMethod();
3 => new Location($referencesUri, new Range(new Position(39, 0), new Position(39, 49))) // TestClass::$staticTestProperty[123]->testProperty;
],
'TestNamespace\\TestClass::staticTestProperty' => [
0 => new Location($referencesUri, new Range(new Position( 8, 16), new Position( 8, 35))), // echo TestClass::$staticTestProperty;
0 => new Location($referencesUri, new Range(new Position(8, 16), new Position(8, 35))), // echo TestClass::$staticTestProperty;
1 => new Location($referencesUri, new Range(new Position(39, 11), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty;
],
'TestNamespace\\TestClass::staticTestMethod()' => [
0 => new Location($referencesUri, new Range(new Position( 7, 0), new Position( 7, 27)))
0 => new Location($referencesUri, new Range(new Position(7, 0), new Position(7, 27)))
],
'TestNamespace\\TestClass::testMethod()' => [
0 => new Location($referencesUri, new Range(new Position( 5, 0), new Position( 5, 16))), // $obj->testMethod();
0 => new Location($referencesUri, new Range(new Position(5, 0), new Position(5, 16))), // $obj->testMethod();
1 => new Location($referencesUri, new Range(new Position(38, 0), new Position(38, 30))), // $obj->testProperty->testMethod();
2 => new Location($referencesUri, new Range(new Position(42, 5), new Position(42, 23))) // $child->testMethod();
],
@ -181,10 +183,10 @@ abstract class ServerTestCase extends TestCase
'TestClass' => [
0 => new Location($globalSymbolsUri, new Range(new Position(48, 13), new Position(48, 17))), // echo self::TEST_CLASS_CONST;
1 => new Location($globalSymbolsUri, new Range(new Position(99, 25), new Position(99, 34))), // class ChildClass extends TestClass {}
2 => new Location($globalReferencesUri, new Range(new Position( 4, 11), new Position( 4, 20))), // $obj = new TestClass();
3 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 9))), // TestClass::staticTestMethod();
4 => new Location($globalReferencesUri, new Range(new Position( 8, 5), new Position( 8, 14))), // echo TestClass::$staticTestProperty;
5 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 14))), // TestClass::TEST_CLASS_CONST;
2 => new Location($globalReferencesUri, new Range(new Position(4, 11), new Position(4, 20))), // $obj = new TestClass();
3 => new Location($globalReferencesUri, new Range(new Position(7, 0), new Position(7, 9))), // TestClass::staticTestMethod();
4 => new Location($globalReferencesUri, new Range(new Position(8, 5), new Position(8, 14))), // echo TestClass::$staticTestProperty;
5 => new Location($globalReferencesUri, new Range(new Position(9, 5), new Position(9, 14))), // TestClass::TEST_CLASS_CONST;
6 => new Location($globalReferencesUri, new Range(new Position(21, 18), new Position(21, 27))), // function whatever(TestClass $param)
7 => new Location($globalReferencesUri, new Range(new Position(21, 37), new Position(21, 46))), // function whatever(TestClass $param): TestClass
8 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 9))), // TestClass::$staticTestProperty[123]->testProperty;
@ -199,23 +201,23 @@ abstract class ServerTestCase extends TestCase
],
'TestClass::TEST_CLASS_CONST' => [
0 => new Location($globalSymbolsUri, new Range(new Position(48, 13), new Position(48, 35))), // echo self::TEST_CLASS_CONSTANT
1 => new Location($globalReferencesUri, new Range(new Position( 9, 5), new Position( 9, 32)))
1 => new Location($globalReferencesUri, new Range(new Position(9, 5), new Position(9, 32)))
],
'TestClass::testProperty' => [
0 => new Location($globalSymbolsUri, new Range(new Position(59, 8), new Position(59, 27))), // $this->testProperty = $testParameter;
1 => new Location($globalReferencesUri, new Range(new Position( 6, 5), new Position( 6, 23))), // echo $obj->testProperty;
1 => new Location($globalReferencesUri, new Range(new Position(6, 5), new Position(6, 23))), // echo $obj->testProperty;
2 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 18))), // $obj->testProperty->testMethod();
3 => new Location($globalReferencesUri, new Range(new Position(39, 0), new Position(39, 49))) // TestClass::$staticTestProperty[123]->testProperty;
],
'TestClass::staticTestProperty' => [
0 => new Location($globalReferencesUri, new Range(new Position( 8, 16), new Position( 8, 35))), // echo TestClass::$staticTestProperty;
0 => new Location($globalReferencesUri, new Range(new Position(8, 16), new Position(8, 35))), // echo TestClass::$staticTestProperty;
1 => new Location($globalReferencesUri, new Range(new Position(39, 11), new Position(39, 30))) // TestClass::$staticTestProperty[123]->testProperty;
],
'TestClass::staticTestMethod()' => [
0 => new Location($globalReferencesUri, new Range(new Position( 7, 0), new Position( 7, 27)))
0 => new Location($globalReferencesUri, new Range(new Position(7, 0), new Position(7, 27)))
],
'TestClass::testMethod()' => [
0 => new Location($globalReferencesUri, new Range(new Position( 5, 0), new Position( 5, 16))), // $obj->testMethod();
0 => new Location($globalReferencesUri, new Range(new Position(5, 0), new Position(5, 16))), // $obj->testMethod();
1 => new Location($globalReferencesUri, new Range(new Position(38, 0), new Position(38, 30))), // $obj->testProperty->testMethod();
2 => new Location($globalReferencesUri, new Range(new Position(42, 5), new Position(42, 23))) // $child->testMethod();
],
@ -225,6 +227,7 @@ abstract class ServerTestCase extends TestCase
]
];
// @codingStandardsIgnoreEnd
});
}
protected function getDefinitionLocation(string $fqn): Location

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
@ -37,14 +38,16 @@ class CompletionTest extends TestCase
public function setUp()
{
Loop::run(function () {
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$definitionResolver = new DefinitionResolver($projectIndex);
$contentRetriever = new FileSystemContentRetriever;
$this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver);
$this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait();
$this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/symbols.php'))->wait();
yield from $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'));
yield from $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/symbols.php'));
$this->textDocument = new Server\TextDocument($this->loader, $definitionResolver, $client, $projectIndex);
});
}
/**
@ -52,12 +55,13 @@ class CompletionTest extends TestCase
*/
public function testPropertyAndMethodWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/property_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(3, 7)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'testProperty',
@ -72,6 +76,7 @@ class CompletionTest extends TestCase
'Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.'
)
], true), $items);
});
}
/**
@ -79,12 +84,13 @@ class CompletionTest extends TestCase
*/
public function testGlobalFunctionInsideNamespaceAndClass()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/inside_namespace_and_method.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 11)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'test_function',
@ -96,6 +102,7 @@ class CompletionTest extends TestCase
'\test_function'
)
], true), $items);
});
}
/**
@ -103,12 +110,13 @@ class CompletionTest extends TestCase
*/
public function testPropertyAndMethodWithoutPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/property.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(3, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'testProperty',
@ -123,6 +131,7 @@ class CompletionTest extends TestCase
'Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.'
)
], true), $items);
});
}
/**
@ -130,12 +139,13 @@ class CompletionTest extends TestCase
*/
public function testVariable()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/variable.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 5)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'$var',
@ -158,6 +168,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(8, 5), new Position(8, 5)), 'param')
)
], true), $items);
});
}
/**
@ -165,12 +176,13 @@ class CompletionTest extends TestCase
*/
public function testVariableWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/variable_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'$param',
@ -183,6 +195,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(8, 6), new Position(8, 6)), 'aram')
)
], true), $items);
});
}
/**
@ -190,12 +203,13 @@ class CompletionTest extends TestCase
*/
public function testNewInNamespace()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_new.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(6, 10)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
// Global TestClass definition (inserted as \TestClass)
new CompletionItem(
@ -237,6 +251,7 @@ class CompletionTest extends TestCase
'TestClass'
),
], true), $items);
});
}
/**
@ -244,12 +259,13 @@ class CompletionTest extends TestCase
*/
public function testUsedClass()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_class.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(6, 5)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'TestClass',
@ -269,6 +285,7 @@ class CompletionTest extends TestCase
$this->assertCompletionsListDoesNotContainLabel('OtherClass', $items);
$this->assertCompletionsListDoesNotContainLabel('TestInterface', $items);
});
}
/**
@ -276,12 +293,13 @@ class CompletionTest extends TestCase
*/
public function testUsedNamespaceWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_namespace.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(8, 16)
)->wait();
);
$this->assertEquals(
new CompletionList([
new CompletionItem(
@ -296,6 +314,7 @@ class CompletionTest extends TestCase
], true),
$items
);
});
}
/**
@ -303,12 +322,13 @@ class CompletionTest extends TestCase
*/
public function testUsedNamespaceWithoutPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/used_namespace.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(9, 15)
)->wait();
);
$this->assertEquals(
new CompletionList([
new CompletionItem(
@ -323,6 +343,7 @@ class CompletionTest extends TestCase
], true),
$items
);
});
}
/**
@ -330,12 +351,13 @@ class CompletionTest extends TestCase
*/
public function testStaticPropertyWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/static_property_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(2, 14)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'staticTestProperty',
@ -347,6 +369,7 @@ class CompletionTest extends TestCase
'$staticTestProperty'
)
], true), $items);
});
}
/**
@ -354,12 +377,13 @@ class CompletionTest extends TestCase
*/
public function testStaticWithoutPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/static.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(2, 11)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'TEST_CLASS_CONST',
@ -383,6 +407,7 @@ class CompletionTest extends TestCase
'Do magna consequat veniam minim proident eiusmod incididunt aute proident.'
)
], true), $items);
});
}
/**
@ -390,12 +415,13 @@ class CompletionTest extends TestCase
*/
public function testStaticMethodWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/static_method_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(2, 13)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'staticTestMethod',
@ -404,6 +430,7 @@ class CompletionTest extends TestCase
'Do magna consequat veniam minim proident eiusmod incididunt aute proident.'
)
], true), $items);
});
}
/**
@ -411,12 +438,13 @@ class CompletionTest extends TestCase
*/
public function testClassConstWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/class_const_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(2, 13)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'TEST_CLASS_CONST',
@ -425,6 +453,7 @@ class CompletionTest extends TestCase
'Anim labore veniam consectetur laboris minim quis aute aute esse nulla ad.'
)
], true), $items);
});
}
/**
@ -432,12 +461,13 @@ class CompletionTest extends TestCase
*/
public function testFullyQualifiedClass()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/fully_qualified_class.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(6, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'TestClass',
@ -455,6 +485,7 @@ class CompletionTest extends TestCase
foreach ($items->items as $item) {
$this->assertSame($item->detail, null);
}
});
}
/**
@ -462,16 +493,18 @@ class CompletionTest extends TestCase
*/
public function testKeywords()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/keywords.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(2, 1)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem('class', CompletionItemKind::KEYWORD, null, null, null, null, 'class'),
new CompletionItem('clone', CompletionItemKind::KEYWORD, null, null, null, null, 'clone')
], true), $items);
});
}
/**
@ -479,12 +512,13 @@ class CompletionTest extends TestCase
*/
public function testHtmlWithoutPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(0, 0)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'<?php',
@ -497,6 +531,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), '<?php')
)
], true), $items);
});
}
/**
@ -504,14 +539,16 @@ class CompletionTest extends TestCase
*/
public function testHtmlWontBeProposedWithoutCompletionContext()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(0, 1)
)->wait();
);
$this->assertEquals(new CompletionList([], true), $items);
});
}
/**
@ -519,13 +556,14 @@ class CompletionTest extends TestCase
*/
public function testHtmlWontBeProposedWithPrefixWithCompletionContext()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(0, 1),
new CompletionContext(CompletionTriggerKind::TRIGGER_CHARACTER, '<')
)->wait();
);
$this->assertEquals(new CompletionList([
new CompletionItem(
@ -539,6 +577,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(0, 1), new Position(0, 1)), '?php')
)
], true), $items);
});
}
/**
@ -546,14 +585,16 @@ class CompletionTest extends TestCase
*/
public function testHtmlPrefixShouldNotTriggerCompletion()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(0, 1),
new CompletionContext(CompletionTriggerKind::TRIGGER_CHARACTER, '>')
)->wait();
);
$this->assertEquals(new CompletionList([], true), $items);
});
}
/**
@ -561,13 +602,14 @@ class CompletionTest extends TestCase
*/
public function testHtmlPrefixShouldTriggerCompletionIfManuallyInvoked()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/html_no_completion.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(0, 1),
new CompletionContext(CompletionTriggerKind::INVOKED)
)->wait();
);
$this->assertEquals(new CompletionList([
new CompletionItem(
'<?php',
@ -580,6 +622,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(0, 1), new Position(0, 1)), '?php')
)
], true), $items);
});
}
/**
@ -587,18 +630,20 @@ class CompletionTest extends TestCase
*/
public function testNamespace()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/namespace.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(4, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'SomeNamespace',
CompletionItemKind::MODULE
)
], true), $items);
});
}
/**
@ -606,12 +651,13 @@ class CompletionTest extends TestCase
*/
public function testBarePhpVariable()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/bare_php.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(4, 8)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'$abc2',
@ -634,6 +680,7 @@ class CompletionTest extends TestCase
new TextEdit(new Range(new Position(4, 8), new Position(4, 8)), 'c')
)
], true), $items);
});
}
/**
@ -641,13 +688,15 @@ class CompletionTest extends TestCase
*/
public function testForeach(Position $position, array $expectedItems)
{
Loop::run(function () use ($expectedItems, $position) {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/foreach.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
$position
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList($expectedItems, true), $items);
});
}
public function foreachProvider(): array
@ -793,12 +842,13 @@ class CompletionTest extends TestCase
public function testMethodReturnType()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/method_return_type.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(10, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'foo',
@ -811,16 +861,18 @@ class CompletionTest extends TestCase
null
)
], true), $items);
});
}
public function testStaticMethodReturnType()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/static_method_return_type.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(11, 6)
)->wait();
);
$this->assertCompletionsListSubset(new CompletionList([
new CompletionItem(
'bar',
@ -833,6 +885,7 @@ class CompletionTest extends TestCase
null
)
], true), $items);
});
}
private function assertCompletionsListSubset(CompletionList $subsetList, CompletionList $list)
@ -856,12 +909,13 @@ class CompletionTest extends TestCase
*/
public function testThisWithoutPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(12, 15)
)->wait();
);
$this->assertEquals(new CompletionList([
new CompletionItem(
'foo',
@ -888,6 +942,7 @@ class CompletionTest extends TestCase
null
)
], true), $items);
});
}
/**
@ -895,12 +950,13 @@ class CompletionTest extends TestCase
*/
public function testThisWithPrefix()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this_with_prefix.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(12, 16)
)->wait();
);
$this->assertEquals(new CompletionList([
new CompletionItem(
'foo',
@ -939,6 +995,7 @@ class CompletionTest extends TestCase
'Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.'
),
], true), $items);
});
}
/**
@ -946,12 +1003,13 @@ class CompletionTest extends TestCase
*/
public function testThisReturnValue()
{
Loop::run(function () {
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/this_return_value.php');
$this->loader->open($completionUri, file_get_contents($completionUri));
$items = $this->textDocument->completion(
$items = yield $this->textDocument->completion(
new TextDocumentIdentifier($completionUri),
new Position(17, 23)
)->wait();
);
$this->assertEquals(new CompletionList([
new CompletionItem(
'bar',
@ -969,5 +1027,6 @@ class CompletionTest extends TestCase
'$this' // Return type of the method
),
], true), $items);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\Definition;
use Amp\Loop;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\{
@ -29,34 +30,40 @@ class GlobalFallbackTest extends ServerTestCase
public function testClassDoesNotFallback()
{
Loop::run(function () {
// $obj = new TestClass();
// Get definition for TestClass should not fall back to global
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier('global_fallback'),
new Position(9, 16)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testFallsBackForConstants()
{
Loop::run(function () {
// echo TEST_CONST;
// Get definition for TEST_CONST
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier('global_fallback'),
new Position(6, 10)
)->wait();
);
$this->assertEquals(new Location('global_symbols', new Range(new Position(9, 6), new Position(9, 22))), $result);
});
}
public function testFallsBackForFunctions()
{
Loop::run(function () {
// test_function();
// Get definition for test_function
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier('global_fallback'),
new Position(5, 6)
)->wait();
);
$this->assertEquals(new Location('global_symbols', new Range(new Position(78, 0), new Position(81, 1))), $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\Definition;
use Amp\Loop;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServerProtocol\{TextDocumentIdentifier, Position, Location, Range};
use function LanguageServer\pathToUri;
@ -11,333 +12,389 @@ class GlobalTest extends ServerTestCase
{
public function testDefinitionFileBeginning()
{
Loop::run(function () {
// |<?php
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))),
new Position(0, 0)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testDefinitionEmptyResult()
{
Loop::run(function () {
// namespace keyword
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))),
new Position(1, 0)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testDefinitionForSelfKeyword()
{
Loop::run(function () {
// echo self::TEST_CLASS_CONST;
// Get definition for self
$reference = $this->getReferenceLocations('TestClass')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForClassLike()
{
Loop::run(function () {
// $obj = new TestClass();
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForClassOnStaticMethodCall()
{
Loop::run(function () {
// TestClass::staticTestMethod();
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[2];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForClassOnStaticPropertyFetch()
{
Loop::run(function () {
// echo TestClass::$staticTestProperty;
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[3];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForClassOnConstFetch()
{
Loop::run(function () {
// TestClass::TEST_CLASS_CONST;
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[4];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForImplements()
{
Loop::run(function () {
// class TestClass implements TestInterface
// Get definition for TestInterface
$reference = $this->getReferenceLocations('TestInterface')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestInterface'), $result);
});
}
public function testDefinitionForClassConstants()
{
Loop::run(function () {
// echo TestClass::TEST_CLASS_CONST;
// Get definition for TEST_CLASS_CONST
$reference = $this->getReferenceLocations('TestClass::TEST_CLASS_CONST')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::TEST_CLASS_CONST'), $result);
});
}
public function testDefinitionForClassConstantsOnSelf()
{
Loop::run(function () {
// echo self::TEST_CLASS_CONST;
// Get definition for TEST_CLASS_CONST
$reference = $this->getReferenceLocations('TestClass::TEST_CLASS_CONST')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::TEST_CLASS_CONST'), $result);
});
}
public function testDefinitionForConstants()
{
Loop::run(function () {
// echo TEST_CONST;
// Get definition for TEST_CONST
$reference = $this->getReferenceLocations('TEST_CONST')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TEST_CONST'), $result);
});
}
public function testDefinitionForStaticMethods()
{
Loop::run(function () {
// TestClass::staticTestMethod();
// Get definition for staticTestMethod
$reference = $this->getReferenceLocations('TestClass::staticTestMethod()')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::staticTestMethod()'), $result);
});
}
public function testDefinitionForStaticProperties()
{
Loop::run(function () {
// echo TestClass::$staticTestProperty;
// Get definition for staticTestProperty
$reference = $this->getReferenceLocations('TestClass::staticTestProperty')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::staticTestProperty'), $result);
});
}
public function testDefinitionForMethods()
{
Loop::run(function () {
// $obj->testMethod();
// Get definition for testMethod
$reference = $this->getReferenceLocations('TestClass::testMethod()')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result);
});
}
public function testDefinitionForMethodOnChildClass()
{
Loop::run(function () {
// $child->testMethod();
// Get definition for testMethod
$reference = $this->getReferenceLocations('TestClass::testMethod()')[2];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result);
});
}
public function testDefinitionForProperties()
{
Loop::run(function () {
// echo $obj->testProperty;
// Get definition for testProperty
$reference = $this->getReferenceLocations('TestClass::testProperty')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testProperty'), $result);
});
}
public function testDefinitionForPropertiesOnThis()
{
Loop::run(function () {
// $this->testProperty = $testParameter;
// Get definition for testProperty
$reference = $this->getReferenceLocations('TestClass::testProperty')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testProperty'), $result);
});
}
public function testDefinitionForVariables()
{
Loop::run(function () {
// echo $var;
// Get definition for $var
$uri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($uri),
new Position(13, 7)
)->wait();
);
$this->assertEquals(new Location($uri, new Range(new Position(12, 0), new Position(12, 10))), $result);
});
}
public function testDefinitionForParamTypeHints()
{
Loop::run(function () {
// function whatever(TestClass $param) {
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[5];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForReturnTypeHints()
{
Loop::run(function () {
// function whatever(TestClass $param): TestClass {
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[6];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForMethodReturnTypeHints()
{
Loop::run(function () {
// public function testMethod($testParameter): TestInterface
// Get definition for TestInterface
$reference = $this->getReferenceLocations('TestInterface')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestInterface'), $result);
});
}
public function testDefinitionForParams()
{
Loop::run(function () {
// echo $param;
// Get definition for $param
$uri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($uri),
new Position(22, 13)
)->wait();
);
$this->assertEquals(new Location($uri, new Range(new Position(21, 18), new Position(21, 34))), $result);
});
}
public function testDefinitionForUsedVariables()
{
Loop::run(function () {
// echo $var;
// Get definition for $var
$uri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($uri),
new Position(26, 11)
)->wait();
);
$this->assertEquals(new Location($uri, new Range(new Position(25, 22), new Position(25, 26))), $result);
});
}
public function testDefinitionForFunctions()
{
Loop::run(function () {
// test_function();
// Get definition for test_function
$reference = $this->getReferenceLocations('test_function()')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('test_function()'), $result);
});
}
public function testDefinitionForUseFunctions()
{
Loop::run(function () {
// use function test_function;
// Get definition for test_function
$reference = $this->getReferenceLocations('test_function()')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('test_function()'), $result);
});
}
public function testDefinitionForInstanceOf()
{
Loop::run(function () {
// if ($abc instanceof TestInterface) {
// Get definition for TestInterface
$reference = $this->getReferenceLocations('TestInterface')[2];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestInterface'), $result);
});
}
public function testDefinitionForNestedMethodCall()
{
Loop::run(function () {
// $obj->testProperty->testMethod();
// Get definition for testMethod
$reference = $this->getReferenceLocations('TestClass::testMethod()')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testMethod()'), $result);
});
}
public function testDefinitionForPropertyFetchOnArrayDimFetch()
{
Loop::run(function () {
// TestClass::$staticTestProperty[123]->testProperty;
// Get definition for testProperty
$reference = $this->getReferenceLocations('TestClass::testProperty')[3];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass::testProperty'), $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\Definition;
use Amp\Loop;
use LanguageServerProtocol\{TextDocumentIdentifier, Location};
use function LanguageServer\pathToUri;
@ -20,37 +21,43 @@ class NamespacedTest extends GlobalTest
public function testDefinitionForConstants()
{
Loop::run(function () {
// echo TEST_CONST;
// Get definition for TEST_CONST
$reference = $this->getReferenceLocations('TEST_CONST')[0];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TEST_CONST'), $result);
});
}
public function testDefinitionForClassLikeUseStatement()
{
Loop::run(function () {
// use TestNamespace\TestClass;
// Get definition for TestClass
$reference = $this->getReferenceLocations('TestClass')[7];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
public function testDefinitionForClassLikeGroupUseStatement()
{
Loop::run(function () {
// use TestNamespace\{TestTrait, TestInterface};
// Get definition for TestInterface
$reference = $this->getReferenceLocations('TestClass')[1];
$result = $this->textDocument->definition(
$result = yield $this->textDocument->definition(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getDefinitionLocation('TestClass'), $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
@ -21,6 +22,7 @@ class DidChangeTest extends TestCase
{
public function test()
{
Loop::run(function () {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = new DefinitionResolver($projectIndex);
@ -34,8 +36,9 @@ class DidChangeTest extends TestCase
$changeEvent->rangeLength = 9999;
$changeEvent->text = "<?php\necho 'Goodbye, World'\n";
$textDocument->didChange($identifier, [$changeEvent]);
yield $textDocument->didChange($identifier, [$changeEvent]);
$this->assertEquals("<?php\necho 'Goodbye, World'\n", $phpDocument->getContent());
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
@ -16,6 +17,7 @@ class DidCloseTest extends TestCase
{
public function test()
{
Loop::run(function () {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = new DefinitionResolver($projectIndex);
@ -33,5 +35,6 @@ class DidCloseTest extends TestCase
$textDocument->didClose(new TextDocumentIdentifier($textDocumentItem->uri));
$this->assertFalse($loader->isOpen($textDocumentItem->uri));
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{Server, LanguageClient, Project};
@ -13,9 +14,10 @@ class DocumentSymbolTest extends ServerTestCase
{
public function test()
{
Loop::run(function () {
// Request symbols
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/symbols.php'));
$result = $this->textDocument->documentSymbol(new TextDocumentIdentifier($uri))->wait();
$result = yield $this->textDocument->documentSymbol(new TextDocumentIdentifier($uri));
// @codingStandardsIgnoreStart
$this->assertEquals([
new SymbolInformation('TestNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('TestNamespace'), ''),
@ -37,5 +39,6 @@ class DocumentSymbolTest extends ServerTestCase
new SymbolInformation('InnerClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\InnerNamespace\\InnerClass'), 'TestNamespace\\InnerNamespace'),
], $result);
// @codingStandardsIgnoreEnd
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\{Server, LanguageClient, Project};
@ -13,13 +14,14 @@ class HoverTest extends ServerTestCase
{
public function testHoverForClassLike()
{
Loop::run(function () {
// $obj = new TestClass();
// Get hover for TestClass
$reference = $this->getReferenceLocations('TestClass')[1];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nclass TestClass implements TestInterface"),
'Pariatur ut laborum tempor voluptate consequat ea deserunt.' . "\n\n" .
@ -29,17 +31,19 @@ class HoverTest extends ServerTestCase
'consequat sunt culpa exercitation pariatur id reprehenderit nisi incididunt Lorem' . "\n" .
'sint. Officia culpa pariatur laborum nostrud cupidatat consequat mollit.'
], $reference->range), $result);
});
}
public function testHoverForClassLikeDefinition()
{
Loop::run(function () {
// class TestClass implements TestInterface
// Get hover for TestClass
$definition = $this->getDefinitionLocation('TestClass');
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nclass TestClass implements TestInterface"),
'Pariatur ut laborum tempor voluptate consequat ea deserunt.' . "\n\n" .
@ -49,147 +53,173 @@ class HoverTest extends ServerTestCase
'consequat sunt culpa exercitation pariatur id reprehenderit nisi incididunt Lorem' . "\n" .
'sint. Officia culpa pariatur laborum nostrud cupidatat consequat mollit.'
], $definition->range), $result);
});
}
public function testHoverForMethod()
{
Loop::run(function () {
// $obj->testMethod();
// Get hover for testMethod
$reference = $this->getReferenceLocations('TestClass::testMethod()')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\npublic function testMethod(\$testParameter): TestInterface"),
'Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.'
], $reference->range), $result);
});
}
public function testHoverForProperty()
{
Loop::run(function () {
// echo $obj->testProperty;
// Get hover for testProperty
$reference = $this->getReferenceLocations('TestClass::testProperty')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\npublic \$testProperty;"),
'Reprehenderit magna velit mollit ipsum do.'
], $reference->range), $result);
});
}
public function testHoverForStaticMethod()
{
Loop::run(function () {
// TestClass::staticTestMethod();
// Get hover for staticTestMethod
$reference = $this->getReferenceLocations('TestClass::staticTestMethod()')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\npublic static function staticTestMethod()"),
'Do magna consequat veniam minim proident eiusmod incididunt aute proident.'
], $reference->range), $result);
});
}
public function testHoverForStaticProperty()
{
Loop::run(function () {
// echo TestClass::staticTestProperty;
// Get hover for staticTestProperty
$reference = $this->getReferenceLocations('TestClass::staticTestProperty')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\npublic static \$staticTestProperty;"),
'Lorem excepteur officia sit anim velit veniam enim.'
], $reference->range), $result);
});
}
public function testHoverForClassConstant()
{
Loop::run(function () {
// echo TestClass::TEST_CLASS_CONST;
// Get hover for TEST_CLASS_CONST
$reference = $this->getReferenceLocations('TestClass::TEST_CLASS_CONST')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nconst TEST_CLASS_CONST = 123;"),
'Anim labore veniam consectetur laboris minim quis aute aute esse nulla ad.'
], $reference->range), $result);
});
}
public function testHoverForFunction()
{
Loop::run(function () {
// test_function();
// Get hover for test_function
$reference = $this->getReferenceLocations('test_function()')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nfunction test_function()"),
'Officia aliquip adipisicing et nulla et laboris dolore labore.'
], $reference->range), $result);
});
}
public function testHoverForConstant()
{
Loop::run(function () {
// echo TEST_CONST;
// Get hover for TEST_CONST
$reference = $this->getReferenceLocations('TEST_CONST')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nconst TEST_CONST = 123;"),
'Esse commodo excepteur pariatur Lorem est aute incididunt reprehenderit.'
], $reference->range), $result);
});
}
public function testHoverForGlobalConstant()
{
Loop::run(function () {
// print TEST_DEFINE_CONSTANT ? 'true' : 'false';
// Get hover for TEST_DEFINE_CONSTANT
$reference = $this->getReferenceLocations('TEST_DEFINE_CONSTANT')[0];
$result = $this->textDocument->hover(
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($reference->uri),
$reference->range->end
)->wait();
);
// TODO - should pretty print with fqns, like \define, \false. Not yet supported by tolerant-php-parser
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\ndefine('TEST_DEFINE_CONSTANT', false)"),
'Lorem ipsum dolor sit amet, consectetur.'
], $reference->range), $result);
});
}
public function testHoverForVariable()
{
Loop::run(function () {
// echo $var;
// Get hover for $var
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php'));
$result = $this->textDocument->hover(new TextDocumentIdentifier($uri), new Position(13, 7))->wait();
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($uri),
new Position(13, 7)
);
$this->assertEquals(new Hover(
[new MarkedString('php', "<?php\n\$var = 123")],
new Range(new Position(13, 5), new Position(13, 9))
), $result);
});
}
public function testHoverForParam()
{
Loop::run(function () {
// echo $param;
// Get hover for $param
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php'));
$result = $this->textDocument->hover(new TextDocumentIdentifier($uri), new Position(22, 11))->wait();
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($uri),
new Position(22, 11)
);
$this->assertEquals(new Hover(
[
new MarkedString('php', "<?php\nTestClass \$param"),
@ -197,14 +227,19 @@ class HoverTest extends ServerTestCase
],
new Range(new Position(22, 9), new Position(22, 15))
), $result);
});
}
public function testHoverForThis()
{
Loop::run(function () {
// $this;
// Get hover for $this
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/global_symbols.php'));
$result = $this->textDocument->hover(new TextDocumentIdentifier($uri), new Position(59, 11))->wait();
$result = yield $this->textDocument->hover(
new TextDocumentIdentifier($uri),
new Position(59, 11)
);
$this->assertEquals(new Hover([
new MarkedString('php', "<?php\nclass TestClass implements TestInterface"),
'Pariatur ut laborum tempor voluptate consequat ea deserunt.' . "\n\n" .
@ -214,5 +249,6 @@ class HoverTest extends ServerTestCase
'consequat sunt culpa exercitation pariatur id reprehenderit nisi incididunt Lorem' . "\n" .
'sint. Officia culpa pariatur laborum nostrud cupidatat consequat mollit.'
], new Range(new Position(59, 8), new Position(59, 13))), $result);
});
}
}

View File

@ -1,18 +1,18 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
Server, Client, LanguageClient, ClientHandler, PhpDocumentLoader, DefinitionResolver
};
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServerProtocol\{TextDocumentItem, DiagnosticSeverity};
use Sabre\Event\Promise;
use Amp\Deferred;
use Amp\Delayed;
use Amp\Loop;
use JsonMapper;
use LanguageServer\{Client, ClientHandler, DefinitionResolver, LanguageClient, PhpDocumentLoader, Server};
use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Index\{DependenciesIndex, Index, ProjectIndex};
use LanguageServer\Tests\MockProtocolStream;
use LanguageServerProtocol\{DiagnosticSeverity, TextDocumentItem};
use PHPUnit\Framework\TestCase;
class ParseErrorsTest extends TestCase
{
@ -21,22 +21,31 @@ class ParseErrorsTest extends TestCase
*/
private $textDocument;
/**
* @var Deferred
*/
private $args;
public function setUp()
{
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$client->textDocument = new class($this->args) extends Client\TextDocument {
$this->args = new Deferred();
$client->textDocument = new class($this->args) extends Client\TextDocument
{
/** @var Deferred */
private $args;
public function __construct(&$args)
public function __construct($args)
{
parent::__construct(new ClientHandler(new MockProtocolStream, new MockProtocolStream), new JsonMapper);
$this->args = &$args;
$this->args = $args;
}
public function publishDiagnostics(string $uri, array $diagnostics): Promise
public function publishDiagnostics(string $uri, array $diagnostics): \Generator
{
$this->args = func_get_args();
return Promise\resolve(null);
$this->args->resolve(func_get_args());
yield new Delayed(0);
return null;
}
};
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
@ -57,6 +66,7 @@ class ParseErrorsTest extends TestCase
public function testParseErrorsArePublishedAsDiagnostics()
{
Loop::run(function () {
$this->openFile(__DIR__ . '/../../../fixtures/invalid_file.php');
$this->assertEquals([
'whatever',
@ -124,13 +134,15 @@ class ParseErrorsTest extends TestCase
'source' => 'php',
'message' => "'Name' expected."
]]
], json_decode(json_encode($this->args), true));
], json_decode(json_encode(yield $this->args->promise()), true));
});
}
public function testParseErrorsWithOnlyStartLine()
{
Loop::run(function () {
$this->markTestIncomplete('This diagnostic not yet implemented in tolerant-php-parser');
$this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php');
yield $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php');
$this->assertEquals([
'whatever',
[[
@ -149,6 +161,7 @@ class ParseErrorsTest extends TestCase
'source' => 'php',
'message' => "Namespace declaration statement has to be the very first statement in the script"
]]
], json_decode(json_encode($this->args), true));
], json_decode(json_encode(yield $this->args->promise()), true));
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\References;
use Amp\Loop;
use LanguageServer\{
LanguageClient, PhpDocumentLoader, Server, DefinitionResolver
};
@ -32,37 +33,43 @@ class GlobalFallbackTest extends ServerTestCase
public function testClassDoesNotFallback()
{
Loop::run(function () {
// class TestClass implements TestInterface
// Get references for TestClass
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier('global_symbols'),
new Position(6, 9)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testFallsBackForConstants()
{
Loop::run(function () {
// const TEST_CONST = 123;
// Get references for TEST_CONST
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier('global_symbols'),
new Position(9, 13)
)->wait();
);
$this->assertEquals([new Location('global_fallback', new Range(new Position(6, 5), new Position(6, 15)))], $result);
});
}
public function testFallsBackForFunctions()
{
Loop::run(function () {
// function test_function()
// Get references for test_function
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier('global_symbols'),
new Position(78, 16)
)->wait();
);
$this->assertEquals([new Location('global_fallback', new Range(new Position(5, 0), new Position(5, 13)))], $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\References;
use Amp\Loop;
use LanguageServerProtocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range};
use LanguageServer\Tests\Server\ServerTestCase;
use function LanguageServer\pathToUri;
@ -11,191 +12,219 @@ class GlobalTest extends ServerTestCase
{
public function testReferencesForClassLike()
{
Loop::run(function () {
// class TestClass implements TestInterface
// Get references for TestClass
$definition = $this->getDefinitionLocation('TestClass');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass'), $result);
});
}
public function testReferencesForClassConstants()
{
Loop::run(function () {
// const TEST_CLASS_CONST = 123;
// Get references for TEST_CLASS_CONST
$definition = $this->getDefinitionLocation('TestClass::TEST_CLASS_CONST');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass::TEST_CLASS_CONST'), $result);
});
}
public function testReferencesForConstants()
{
Loop::run(function () {
// const TEST_CONST = 123;
// Get references for TEST_CONST
$definition = $this->getDefinitionLocation('TEST_CONST');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TEST_CONST'), $result);
});
}
public function testReferencesForStaticMethods()
{
Loop::run(function () {
// public static function staticTestMethod()
// Get references for staticTestMethod
$definition = $this->getDefinitionLocation('TestClass::staticTestMethod()');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass::staticTestMethod()'), $result);
});
}
public function testReferencesForStaticProperties()
{
Loop::run(function () {
// public static $staticTestProperty;
// Get references for $staticTestProperty
$definition = $this->getDefinitionLocation('TestClass::staticTestProperty');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass::staticTestProperty'), $result);
});
}
public function testReferencesForMethods()
{
Loop::run(function () {
// public function testMethod($testParameter)
// Get references for testMethod
$definition = $this->getDefinitionLocation('TestClass::testMethod()');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass::testMethod()'), $result);
});
}
public function testReferencesForProperties()
{
Loop::run(function () {
// public $testProperty;
// Get references for testProperty
$definition = $this->getDefinitionLocation('TestClass::testProperty');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass::testProperty'), $result);
});
}
public function testReferencesForVariables()
{
Loop::run(function () {
// $var = 123;
// Get definition for $var
$uri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($uri),
new Position(12, 3)
)->wait();
);
$this->assertEquals([
new Location($uri, new Range(new Position(12, 0), new Position(12, 4))),
new Location($uri, new Range(new Position(13, 5), new Position(13, 9))),
new Location($uri, new Range(new Position(26, 9), new Position(26, 13)))
], $result);
});
}
public function testReferencesForFunctionParams()
{
Loop::run(function () {
// function whatever(TestClass $param): TestClass
// Get references for $param
$uri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($uri),
new Position(21, 32)
)->wait();
);
$this->assertEquals([new Location($uri, new Range(new Position(22, 9), new Position(22, 15)))], $result);
});
}
public function testReferencesForFunctions()
{
Loop::run(function () {
// function test_function()
// Get references for test_function
$referencesUri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'));
$symbolsUri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/symbols.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($symbolsUri),
new Position(78, 16)
)->wait();
);
$this->assertEquals([
new Location($referencesUri, new Range(new Position(10, 0), new Position(10, 13))),
new Location($referencesUri, new Range(new Position(31, 13), new Position(31, 40)))
], $result);
});
}
public function testReferencesForReference()
{
Loop::run(function () {
// $obj = new TestClass();
// Get references for TestClass
$reference = $this->getReferenceLocations('TestClass')[1];
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($reference->uri),
$reference->range->start
)->wait();
);
$this->assertEquals($this->getReferenceLocations('TestClass'), $result);
});
}
public function testReferencesForUnusedClass()
{
Loop::run(function () {
// class UnusedClass
// Get references for UnusedClass
$symbolsUri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/global_symbols.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($symbolsUri),
new Position(111, 10)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testReferencesForUnusedProperty()
{
Loop::run(function () {
// public $unusedProperty
// Get references for unusedProperty
$symbolsUri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/global_symbols.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($symbolsUri),
new Position(113, 18)
)->wait();
);
$this->assertEquals([], $result);
});
}
public function testReferencesForUnusedMethod()
{
Loop::run(function () {
// public function unusedMethod()
// Get references for unusedMethod
$symbolsUri = pathToUri(realpath(__DIR__ . '/../../../../fixtures/global_symbols.php'));
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($symbolsUri),
new Position(115, 26)
)->wait();
);
$this->assertEquals([], $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument\References;
use Amp\Loop;
use LanguageServerProtocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range};
use function LanguageServer\pathToUri;
@ -20,14 +21,16 @@ class NamespacedTest extends GlobalTest
public function testReferencesForNamespaces()
{
Loop::run(function () {
// namespace TestNamespace;
// Get references for TestNamespace
$definition = parent::getDefinitionLocation('TestNamespace');
$result = $this->textDocument->references(
$result = yield $this->textDocument->references(
new ReferenceContext,
new TextDocumentIdentifier($definition->uri),
$definition->range->end
)->wait();
);
$this->assertEquals(parent::getReferenceLocations('TestNamespace'), $result);
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\TextDocument;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
@ -50,13 +51,15 @@ class SignatureHelpTest extends TestCase
*/
public function testSignatureHelp(Position $position, SignatureHelp $expectedSignature)
{
Loop::run(function () use ($position, $expectedSignature) {
$callsUri = pathToUri(__DIR__ . '/../../../fixtures/signature_help/calls.php');
$this->loader->open($callsUri, file_get_contents($callsUri));
$signatureHelp = $this->textDocument->signatureHelp(
$signatureHelp = yield $this->textDocument->signatureHelp(
new TextDocumentIdentifier($callsUri),
$position
)->wait();
);
$this->assertEquals($expectedSignature, $signatureHelp);
});
}
public function signatureHelpProvider(): array

View File

@ -1,22 +1,24 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\Workspace;
use Amp\Deferred;
use Amp\Loop;
use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\{DefinitionResolver, LanguageClient, PhpDocumentLoader, Server};
use LanguageServer\{DefinitionResolver, Event\MessageEvent, LanguageClient, PhpDocumentLoader, Server};
use LanguageServer\Index\{DependenciesIndex, Index, ProjectIndex};
use LanguageServerProtocol\{FileChangeType, FileEvent};
use LanguageServer\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()
{
Loop::run(function () {
$client = new LanguageClient(new MockProtocolStream(), $writer = new MockProtocolStream());
$projectIndex = new ProjectIndex($sourceIndex = new Index(), $dependenciesIndex = new DependenciesIndex());
$definitionResolver = new DefinitionResolver($projectIndex);
@ -26,17 +28,19 @@ class DidChangeWatchedFilesTest extends ServerTestCase
$fileEvent = new FileEvent('my uri', FileChangeType::DELETED);
$isDiagnosticsCleared = false;
$writer->on('message', function (Message $message) use ($fileEvent, &$isDiagnosticsCleared) {
$deferred = new Deferred();
$writer->addListener('message', function (MessageEvent $messageEvent) use ($deferred, $fileEvent, &$isDiagnosticsCleared) {
$message = $messageEvent->getMessage();
if ($message->body->method === "textDocument/publishDiagnostics") {
$this->assertEquals($message->body->params->uri, $fileEvent->uri);
$this->assertEquals($message->body->params->diagnostics, []);
$isDiagnosticsCleared = true;
$deferred->resolve(true);
}
});
$workspace->didChangeWatchedFiles([$fileEvent]);
Loop\tick(true);
$this->assertTrue($isDiagnosticsCleared, "Deleting file should clear all diagnostics.");
$this->assertTrue(yield $deferred->promise(), "Deleting file should clear all diagnostics.");
});
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace LanguageServer\Tests\Server\Workspace;
use Amp\Loop;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\{Server, Client, LanguageClient, Project, PhpDocument};
@ -24,8 +25,9 @@ class SymbolTest extends ServerTestCase
{
public function testEmptyQueryReturnsAllSymbols()
{
Loop::run(function () {
// Request symbols
$result = $this->workspace->symbol('')->wait();
$result = yield $this->workspace->symbol('');
$referencesUri = pathToUri(realpath(__DIR__ . '/../../../fixtures/references.php'));
// @codingStandardsIgnoreStart
@ -70,12 +72,14 @@ class SymbolTest extends ServerTestCase
new SymbolInformation('SecondTestNamespace', SymbolKind::NAMESPACE, $this->getDefinitionLocation('SecondTestNamespace'), ''),
], $result);
// @codingStandardsIgnoreEnd
});
}
public function testQueryFiltersResults()
{
Loop::run(function () {
// Request symbols
$result = $this->workspace->symbol('testmethod')->wait();
$result = yield $this->workspace->symbol('testmethod');
// @codingStandardsIgnoreStart
$this->assertEquals([
new SymbolInformation('staticTestMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestNamespace\\TestClass::staticTestMethod()'), 'TestNamespace\\TestClass'),
@ -84,5 +88,6 @@ class SymbolTest extends ServerTestCase
new SymbolInformation('testMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestClass::testMethod()'), 'TestClass')
], $result);
// @codingStandardsIgnoreEnd
});
}
}

View File

@ -1,4 +1,4 @@
<?php
use function LanguageServer\{pathToUri, timeout};
use function LanguageServer\{pathToUri};

View File

@ -5,9 +5,6 @@
],
"LanguageServer\\pathToUri()": [
"./functionUse2.php"
],
"LanguageServer\\timeout()": [
"./functionUse2.php"
]
},
"definitions": []