Commit 1ee58dd3 authored by Gert's avatar Gert

Rewrite queue item handler interface to use promises (futures)

This rewrites all queue item handlers to return a promise. The actual
response message isn't sent over the message until the promise
actually resolves completely.

All queue item handlers currently still do their work synchronously
and return an artificially created promise, but this change allows
each queue handler to start doing some work only after some other
promise resolves (and, eventually, something asynchronous is done).

References #312
parent e331ae5a
Pipeline #112426314 passed with stages
in 12 minutes and 29 seconds
......@@ -8,6 +8,8 @@ use RuntimeException;
use Ds\Vector;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Indexing\IncorrectDatabaseVersionException;
use Serenata\UserInterface\JsonRpcQueueItemHandler;
......@@ -60,47 +62,75 @@ final class JsonRpcQueueItemProcessor
*/
public function process(JsonRpcQueueItem $queueItem): void
{
$error = null;
$message = null;
if ($this->activeWorkspaceManager->getActiveWorkspace() === null &&
$queueItem->getRequest()->getMethod() !== 'initialize'
) {
$error = new JsonRpcError(
JsonRpcErrorCode::SERVER_NOT_INITIALIZED,
'Server not initialized yet, no active workspace'
$queueItem->getJsonRpcMessageSender()->send(
new JsonRpcResponse($queueItem->getRequest()->getId(), null, new JsonRpcError(
JsonRpcErrorCode::SERVER_NOT_INITIALIZED,
'Server not initialized yet, no active workspace'
))
);
} elseif (!$queueItem->getIsCancelled()) {
try {
$message = $this->handle($queueItem);
} catch (UnknownJsonRpcRequestMethodException $e) {
$error = new JsonRpcError(JsonRpcErrorCode::METHOD_NOT_FOUND, $e->getMessage());
} catch (RequestParsingException $e) {
$error = new JsonRpcError(JsonRpcErrorCode::INVALID_PARAMS, $e->getMessage());
} catch (JsonRpcQueueItemHandler\InvalidArgumentsException $e) {
$error = new JsonRpcError(JsonRpcErrorCode::INVALID_PARAMS, $e->getMessage());
} catch (IncorrectDatabaseVersionException $e) {
$error = new JsonRpcError(JsonRpcErrorCode::DATABASE_VERSION_MISMATCH, $e->getMessage());
} catch (RuntimeException $e) {
$error = new JsonRpcError(JsonRpcErrorCode::GENERIC_RUNTIME_ERROR, $e->getMessage());
} catch (Throwable $e) {
$error = new JsonRpcError(JsonRpcErrorCode::FATAL_SERVER_ERROR, $e->getMessage(), [
'line' => $e->getLine(),
'file' => $e->getFile(),
'backtrace' => $this->getCompleteBacktraceFromThrowable($e),
]);
}
} else {
$error = new JsonRpcError(JsonRpcErrorCode::REQUEST_CANCELLED, 'Request was cancelled');
return;
}
if ($error !== null) {
$message = new JsonRpcResponse($queueItem->getRequest()->getId(), null, $error);
if ($queueItem->getIsCancelled()) {
$queueItem->getJsonRpcMessageSender()->send(
new JsonRpcResponse($queueItem->getRequest()->getId(), null, new JsonRpcError(
JsonRpcErrorCode::REQUEST_CANCELLED,
'Request was cancelled'
))
);
return;
}
if ($message !== null) {
$queueItem->getJsonRpcMessageSender()->send($message);
$onFulfilled = function (?JsonRpcMessageInterface $message) use ($queueItem): void {
if ($message !== null) {
$queueItem->getJsonRpcMessageSender()->send($message);
}
};
$onRejected = function (Throwable $throwable) use ($queueItem): void {
$queueItem->getJsonRpcMessageSender()->send(new JsonRpcResponse(
$queueItem->getRequest()->getId(),
null,
$this->convertExceptionToJsonRpcError($throwable)
));
};
try {
$this->handle($queueItem)->then($onFulfilled, $onRejected);
} catch (Throwable $throwable) {
$onRejected($throwable);
}
}
/**
* @param Throwable $throwable
*
* @return JsonRpcError
*/
private function convertExceptionToJsonRpcError(Throwable $throwable): JsonRpcError
{
if ($throwable instanceof UnknownJsonRpcRequestMethodException) {
return new JsonRpcError(JsonRpcErrorCode::METHOD_NOT_FOUND, $throwable->getMessage());
} elseif ($throwable instanceof RequestParsingException) {
return new JsonRpcError(JsonRpcErrorCode::INVALID_PARAMS, $throwable->getMessage());
} elseif ($throwable instanceof JsonRpcQueueItemHandler\InvalidArgumentsException) {
return new JsonRpcError(JsonRpcErrorCode::INVALID_PARAMS, $throwable->getMessage());
} elseif ($throwable instanceof IncorrectDatabaseVersionException) {
return new JsonRpcError(JsonRpcErrorCode::DATABASE_VERSION_MISMATCH, $throwable->getMessage());
} elseif ($throwable instanceof RuntimeException) {
return new JsonRpcError(JsonRpcErrorCode::GENERIC_RUNTIME_ERROR, $throwable->getMessage());
}
return new JsonRpcError(JsonRpcErrorCode::FATAL_SERVER_ERROR, $throwable->getMessage(), [
'line' => $throwable->getLine(),
'file' => $throwable->getFile(),
'backtrace' => $this->getCompleteBacktraceFromThrowable($throwable),
]);
}
/**
......@@ -111,9 +141,9 @@ final class JsonRpcQueueItemProcessor
* @throws UnknownJsonRpcRequestMethodException
* @throws Throwable
*
* @return JsonRpcMessageInterface|null
* @return ExtendedPromiseInterface ExtendedPromiseInterface<JsonRpcMessageInterface|null>
*/
private function handle(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
private function handle(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$params = $queueItem->getRequest()->getParams();
......
......@@ -3,7 +3,7 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
/**
* Base class for commands.
* Base class for queue item handlers.
*/
abstract class AbstractJsonRpcQueueItemHandler implements JsonRpcQueueItemHandlerInterface
{
......
......@@ -2,9 +2,11 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Sockets\JsonRpcQueue;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* JsonRpcQueueItemHandlerthat cancels an open request.
......@@ -27,7 +29,7 @@ final class CancelRequestJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIte
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
......@@ -37,6 +39,10 @@ final class CancelRequestJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIte
$this->requestQueue->cancel($parameters['id']);
return null;
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return $deferred->promise();
}
}
......@@ -2,13 +2,15 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Analysis\ClasslikeInfoBuilderInterface;
use Serenata\Analysis\Typing\TypeAnalyzer;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* JsonRpcQueueItemHandlerthat shows information about a class, interface or trait.
......@@ -40,7 +42,7 @@ final class ClassInfoJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
......@@ -50,7 +52,13 @@ final class ClassInfoJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
);
}
return new JsonRpcResponse($queueItem->getRequest()->getId(), $this->getClassInfo($arguments['name']));
$deferred = new Deferred();
$deferred->resolve(new JsonRpcResponse(
$queueItem->getRequest()->getId(),
$this->getClassInfo($arguments['name'])
));
return $deferred->promise();
}
/**
......
......@@ -2,6 +2,9 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Analysis\ClasslikeListProviderInterface;
use Serenata\Analysis\Typing\FileClasslikeListProviderInterface;
......@@ -10,7 +13,6 @@ use Serenata\Indexing\StorageInterface;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* JsonRpcQueueItemHandlerthat shows a list of available classes, interfaces and traits.
......@@ -52,16 +54,21 @@ final class ClassListJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$uri = $arguments['uri'] ?? null;
return new JsonRpcResponse(
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
($uri !== null) ? $this->getAllForFilePath($uri) : $this->getAll()
);
$deferred = new Deferred();
$deferred->resolve($response);
return $deferred->promise();
}
/**
......
......@@ -2,6 +2,9 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\CodeLenses\CodeLens;
use Serenata\CodeLenses\CodeLensesRetriever;
......@@ -9,7 +12,6 @@ use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Utility\TextDocumentItem;
......@@ -43,17 +45,22 @@ final class CodeLensJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHand
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
return new JsonRpcResponse(
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
$this->getAll(
$parameters['textDocument']['uri'],
$this->textDocumentContentRegistry->get($parameters['textDocument']['uri'])
)
);
$deferred = new Deferred();
$deferred->resolve($response);
return $deferred->promise();
}
/**
......
......@@ -2,6 +2,9 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Autocompletion\CompletionList;
use Serenata\Autocompletion\AutocompletionPrefixDeterminerInterface;
......@@ -14,7 +17,6 @@ use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Utility\TextDocumentItem;
......@@ -56,11 +58,11 @@ final class CompletionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
return new JsonRpcResponse($queueItem->getRequest()->getId(), new CompletionList(
$response = new JsonRpcResponse($queueItem->getRequest()->getId(), new CompletionList(
true,
$this->getSuggestions(
$parameters['textDocument']['uri'],
......@@ -68,6 +70,11 @@ final class CompletionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
new Position($parameters['position']['line'], $parameters['position']['character'])
)
));
$deferred = new Deferred();
$deferred->resolve($response);
return $deferred->promise();
}
/**
......
......@@ -2,13 +2,15 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Analysis\Typing\Deduction\ExpressionTypeDeducer;
use Serenata\Common\Position;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Utility\TextDocumentItem;
use Serenata\Utility\SourceCodeStreamReader;
......@@ -45,7 +47,7 @@ final class DeduceTypesJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
......@@ -77,7 +79,10 @@ final class DeduceTypesJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
isset($arguments['ignore-last-element']) && $arguments['ignore-last-element']
);
return new JsonRpcResponse($queueItem->getRequest()->getId(), $result);
$deferred = new Deferred();
$deferred->resolve(new JsonRpcResponse($queueItem->getRequest()->getId(), $result));
return $deferred->promise();
}
/**
......
......@@ -2,6 +2,9 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Common\Position;
use Serenata\Indexing\TextDocumentContentRegistry;
......@@ -10,7 +13,6 @@ use Serenata\GotoDefinition\DefinitionLocator;
use Serenata\Sockets\JsonRpcResponse;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Utility\Location;
use Serenata\Utility\TextDocumentItem;
......@@ -45,11 +47,11 @@ final class DefinitionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
return new JsonRpcResponse(
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
$this->gotoDefinition(
$parameters['textDocument']['uri'],
......@@ -57,6 +59,11 @@ final class DefinitionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
new Position($parameters['position']['line'], $parameters['position']['character'])
)
);
$deferred = new Deferred();
$deferred->resolve($response);
return $deferred->promise();
}
/**
......
......@@ -2,6 +2,9 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Linting\Linter;
......@@ -9,7 +12,6 @@ use Serenata\Linting\PublishDiagnosticsParams;
use Serenata\Sockets\JsonRpcRequest;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* Handles diagnostics requests.
......@@ -42,7 +44,7 @@ final class DiagnosticsJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
......@@ -51,7 +53,7 @@ final class DiagnosticsJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
}
// Don't send a response, but send a notification (request with null ID) instead.
return new JsonRpcRequest(
$response = new JsonRpcRequest(
null,
'textDocument/publishDiagnostics',
$this->lint(
......@@ -59,6 +61,11 @@ final class DiagnosticsJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
$this->textDocumentContentRegistry->get($parameters['uri'])
)->jsonSerialize()
);
$deferred = new Deferred();
$deferred->resolve($response);
return $deferred->promise();
}
/**
......
......@@ -2,8 +2,10 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* Handles the "workspace/didChangeConfiguration" notification.
......@@ -13,8 +15,12 @@ final class DidChangeConfigurationJsonRpcQueueItemHandler extends AbstractJsonRp
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
return null; // This is a notification that doesn't expect a response.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return $deferred->promise();
}
}
......@@ -2,11 +2,13 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Indexing\IndexerInterface;
use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Sockets\JsonRpcMessageSenderInterface;
/**
......@@ -37,7 +39,7 @@ final class DidChangeJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams();
......@@ -51,7 +53,11 @@ final class DidChangeJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
$queueItem->getJsonRpcMessageSender()
);
return null; // This is a notification that doesn't expect a response.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return $deferred->promise();
}
/**
......
......@@ -2,12 +2,14 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Indexing\IndexerInterface;
use Serenata\Indexing\StorageInterface;
use Serenata\Indexing\FileNotFoundStorageException;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Sockets\JsonRpcMessageSenderInterface;
use Serenata\Utility\FileEvent;
......@@ -42,7 +44,7 @@ final class DidChangeWatchedFilesJsonRpcQueueItemHandler extends AbstractJsonRpc
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams();
......@@ -52,7 +54,11 @@ final class DidChangeWatchedFilesJsonRpcQueueItemHandler extends AbstractJsonRpc
$this->handle($this->createParamsFromRawArray($parameters), $queueItem->getJsonRpcMessageSender());
return null; // This is a notification that doesn't expect a response.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return $deferred->promise();
}
/**
......
......@@ -2,8 +2,10 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* Handles the "textDocument/didClose" notification.
......@@ -13,11 +15,14 @@ final class DidCloseJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHand
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
// Stubbed for now, InitializeJsonRpcQueueItemHandler indicates we don't support this yet, but stub it to avoid
// generating errors with some clients that try to send them anyway.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return null; // This is a notification that doesn't expect a response.
return $deferred->promise();
}
}
......@@ -2,8 +2,10 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
/**
* Handles the "textDocument/didOpen" notification.
......@@ -13,11 +15,14 @@ final class DidOpenJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHandl
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
// Stubbed for now, InitializeJsonRpcQueueItemHandler indicates we don't support this yet, but stub it to avoid
// generating errors with some clients that try to send them anyway.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return null; // This is a notification that doesn't expect a response.
return $deferred->promise();
}
}
......@@ -2,11 +2,13 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Indexing\IndexerInterface;
use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Sockets\JsonRpcQueueItem;
use Serenata\Sockets\JsonRpcMessageInterface;
use Serenata\Sockets\JsonRpcMessageSenderInterface;
/**
......@@ -45,7 +47,7 @@ final class DidSaveJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHandl
/**
* @inheritDoc
*/
public function execute(JsonRpcQueueItem $queueItem): ?JsonRpcMessageInterface
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams();
......@@ -55,7 +57,11 @@ final class DidSaveJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHandl
$this->handle($parameters['textDocument']['uri'], $parameters['text'], $queueItem->getJsonRpcMessageSender());
return null; // This is a notification that doesn't expect a response.
// This is a notification that doesn't expect a response.
$deferred = new Deferred();
$deferred->resolve(null);
return $deferred->promise();
}
/**
......
......@@ -2,13 +2,15 @@
namespace Serenata\UserInterface\JsonRpcQueueItemHandler;
use React\Promise\Deferred;
use React\Promise\ExtendedPromiseInterface;
use Serenata\Common\Position;
use Serenata\Indexing\TextDocumentContentRegistry;
use Serenata\Sockets\JsonRpcResponse;