2018-10-17 21:52:26 +02:00
|
|
|
<?php
|
|
|
|
declare(strict_types = 1);
|
2018-11-06 03:57:36 +01:00
|
|
|
namespace Psalm\Internal\LanguageServer;
|
2018-10-17 21:52:26 +02:00
|
|
|
|
|
|
|
use AdvancedJsonRpc;
|
2019-07-05 22:24:00 +02:00
|
|
|
use function Amp\call;
|
2019-02-06 02:00:13 +01:00
|
|
|
use Amp\Deferred;
|
2019-01-19 06:58:08 +01:00
|
|
|
use Amp\Promise;
|
2019-06-26 22:52:29 +02:00
|
|
|
use function error_log;
|
2018-10-17 21:52:26 +02:00
|
|
|
|
2018-12-02 00:37:49 +01:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2018-10-17 21:52:26 +02:00
|
|
|
class ClientHandler
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var ProtocolReader
|
|
|
|
*/
|
|
|
|
public $protocolReader;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var ProtocolWriter
|
|
|
|
*/
|
|
|
|
public $protocolWriter;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var IdGenerator
|
|
|
|
*/
|
|
|
|
public $idGenerator;
|
|
|
|
|
|
|
|
public function __construct(ProtocolReader $protocolReader, ProtocolWriter $protocolWriter)
|
|
|
|
{
|
|
|
|
$this->protocolReader = $protocolReader;
|
|
|
|
$this->protocolWriter = $protocolWriter;
|
|
|
|
$this->idGenerator = new IdGenerator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a request to the client and returns a promise that is resolved with the result or rejected with the error
|
|
|
|
*
|
|
|
|
* @param string $method The method to call
|
|
|
|
* @param array|object $params The method parameters
|
2019-07-05 22:24:00 +02:00
|
|
|
*
|
2019-02-06 17:40:18 +01:00
|
|
|
* @return Promise<mixed> Resolved with the result of the request or rejected with an error
|
2018-10-17 21:52:26 +02:00
|
|
|
*/
|
|
|
|
public function request(string $method, $params): Promise
|
|
|
|
{
|
|
|
|
$id = $this->idGenerator->generate();
|
2019-01-19 06:58:08 +01:00
|
|
|
|
2019-02-06 17:40:18 +01:00
|
|
|
return call(
|
|
|
|
/**
|
2020-10-17 18:36:44 +02:00
|
|
|
* @return \Generator<int, \Amp\Promise, mixed, \Amp\Promise<mixed>>
|
2019-02-06 17:40:18 +01:00
|
|
|
*/
|
2020-10-17 18:36:44 +02:00
|
|
|
function () use ($id, $method, $params): \Generator {
|
2019-02-06 17:40:18 +01:00
|
|
|
yield $this->protocolWriter->write(
|
|
|
|
new Message(
|
|
|
|
new AdvancedJsonRpc\Request($id, $method, (object) $params)
|
|
|
|
)
|
|
|
|
);
|
2019-01-19 06:58:08 +01:00
|
|
|
|
2019-02-06 17:40:18 +01:00
|
|
|
$deferred = new Deferred();
|
2019-01-19 06:58:08 +01:00
|
|
|
|
2019-02-06 17:40:18 +01:00
|
|
|
$listener =
|
2020-10-12 21:02:52 +02:00
|
|
|
function (Message $msg) use ($id, $deferred, &$listener): void {
|
2019-02-06 17:40:18 +01:00
|
|
|
error_log('request handler');
|
|
|
|
/**
|
|
|
|
* @psalm-suppress UndefinedPropertyFetch
|
|
|
|
* @psalm-suppress MixedArgument
|
|
|
|
*/
|
|
|
|
if ($msg->body
|
|
|
|
&& AdvancedJsonRpc\Response::isResponse($msg->body)
|
|
|
|
&& $msg->body->id === $id
|
|
|
|
) {
|
|
|
|
// Received a response
|
|
|
|
$this->protocolReader->removeListener('message', $listener);
|
|
|
|
if (AdvancedJsonRpc\SuccessResponse::isSuccessResponse($msg->body)) {
|
|
|
|
$deferred->resolve($msg->body->result);
|
|
|
|
} else {
|
|
|
|
$deferred->fail($msg->body->error);
|
|
|
|
}
|
2018-10-17 21:52:26 +02:00
|
|
|
}
|
2019-02-06 17:40:18 +01:00
|
|
|
};
|
|
|
|
$this->protocolReader->on('message', $listener);
|
2019-07-05 22:24:00 +02:00
|
|
|
|
2019-02-06 17:40:18 +01:00
|
|
|
return $deferred->promise();
|
|
|
|
}
|
|
|
|
);
|
2018-10-17 21:52:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a notification to the client
|
|
|
|
*
|
|
|
|
* @param string $method The method to call
|
|
|
|
* @param array|object $params The method parameters
|
2019-07-05 22:24:00 +02:00
|
|
|
*
|
2020-04-03 04:38:10 +02:00
|
|
|
* @return Promise<void> Will be resolved as soon as the notification has been sent
|
2018-10-17 21:52:26 +02:00
|
|
|
*/
|
|
|
|
public function notify(string $method, $params): Promise
|
|
|
|
{
|
2020-04-03 04:38:10 +02:00
|
|
|
/** @var Promise<void> */
|
2018-10-17 21:52:26 +02:00
|
|
|
return $this->protocolWriter->write(
|
|
|
|
new Message(
|
|
|
|
new AdvancedJsonRpc\Notification($method, (object)$params)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|