1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QLANGUAGESERVERBASE_P_H
5#define QLANGUAGESERVERBASE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtLanguageServer/qtlanguageserverglobal.h>
19#include <QtLanguageServer/private/qlanguageserverspec_p.h>
20#include <QtJsonRpc/private/qjsonrpcprotocol_p.h>
21#include <QtJsonRpc/private/qjsonrpctransport_p.h>
22
23#include <QtCore/QByteArray>
24
25#include <functional>
26#include <memory>
27
28QT_BEGIN_NAMESPACE
29
30namespace QLspSpecification {
31
32Q_DECLARE_LOGGING_CATEGORY(lspLog);
33
34class ProtocolBasePrivate;
35class Q_LANGUAGESERVER_EXPORT ProtocolBase
36{
37 Q_DISABLE_COPY_MOVE(ProtocolBase)
38public:
39 ~ProtocolBase();
40 using GenericRequestHandler = std::function<void(const QJsonRpc::IdType &, const QByteArray &,
41 const QLspSpecification::RequestParams &,
42 QJsonRpc::TypedResponse &&)>;
43 using GenericNotificationHandler =
44 std::function<void(const QByteArray &, const QLspSpecification::NotificationParams &)>;
45 using ResponseErrorHandler = std::function<void(const QLspSpecification::ResponseError &)>;
46
47 // generated, defined in qlanguageservergen.cpp
48 static QByteArray requestMethodToBaseCppName(const QByteArray &);
49
50 // generated, defined in qlanguageservergen.cpp
51 static QByteArray notificationMethodToBaseCppName(const QByteArray &);
52
53 static void defaultUndispatchedRequestHandler(
54 const QJsonRpc::IdType &id, const QByteArray &method,
55 const QLspSpecification::RequestParams &params, QJsonRpc::TypedResponse &&response);
56 static void defaultUndispatchedNotificationHandler(
57 const QByteArray &method, const QLspSpecification::NotificationParams &params);
58 static void defaultResponseErrorHandler(const QLspSpecification::ResponseError &err);
59
60 void registerResponseErrorHandler(const ResponseErrorHandler &h);
61 void registerUndispatchedRequestHandler(const GenericRequestHandler &handler);
62 void registerUndispatchedNotificationHandler(const GenericNotificationHandler &handler);
63
64 void handleResponseError(const ResponseError &err);
65 void handleUndispatchedRequest(const QJsonRpc::IdType &id, const QByteArray &method,
66 const QLspSpecification::RequestParams &params,
67 QJsonRpc::TypedResponse &&response);
68 void handleUndispatchedNotification(const QByteArray &method,
69 const QLspSpecification::NotificationParams &params);
70 QJsonRpc::TypedRpc *typedRpc();
71
72protected:
73 std::unique_ptr<ProtocolBasePrivate> d_ptr;
74
75 ProtocolBase(std::unique_ptr<ProtocolBasePrivate> &&priv);
76 QJsonRpcTransport *transport();
77
78private:
79 void registerMethods(QJsonRpc::TypedRpc *);
80 Q_DECLARE_PRIVATE(ProtocolBase)
81};
82
83template<typename T, typename F>
84void decodeAndCall(QJsonValue value, F funct,
85 ProtocolBase::ResponseErrorHandler errorHandler =
86 &ProtocolBase::defaultResponseErrorHandler)
87{
88 using namespace Qt::StringLiterals;
89
90 T result;
91 QTypedJson::Reader r(value);
92 doWalk(r, result);
93 if (!r.errorMessages().isEmpty()) {
94 errorHandler(QLspSpecification::ResponseError {
95 .code: int(QLspSpecification::ErrorCodes::ParseError),
96 .message: u"Errors decoding data:\n %1"_s.arg(a: r.errorMessages().join(sep: u"\n ")).toUtf8(),
97 .data: value });
98 r.clearErrorMessages();
99 } else {
100 if constexpr (std::is_same_v<T, std::nullptr_t> && std::is_invocable_v<F>) {
101 funct();
102 } else {
103 funct(result);
104 }
105 }
106}
107
108} // namespace QLspSpecification
109QT_END_NAMESPACE
110#endif // QLANGUAGESERVERBASE_P_H
111

source code of qtlanguageserver/src/languageserver/qlanguageserverbase_p.h