aboutsummaryrefslogtreecommitdiffstats
path: root/src/shared/lsp/lsputils.h
blob: eb7a1834239e83db9563931aa337403f0a354314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "languageserverprotocol_global.h"

#include <tools/qbsassert.h>

#include <QJsonArray>
#include <QJsonObject>
#include <QLoggingCategory>

#include <variant>

namespace lsp {

LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(conversionLog)

template <typename T>
T fromJsonValue(const QJsonValue &value)
{
    if (conversionLog().isDebugEnabled() && !value.isObject())
        qCDebug(conversionLog) << "Expected Object in json value but got: " << value;
    T result(value.toObject());
    if (conversionLog().isDebugEnabled() && !result.isValid())
        qCDebug(conversionLog) << typeid(result).name() << " is not valid: " << result;
    return result;
}

template<>
LANGUAGESERVERPROTOCOL_EXPORT QString fromJsonValue<QString>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT int fromJsonValue<int>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT double fromJsonValue<double>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT bool fromJsonValue<bool>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT QJsonObject fromJsonValue<QJsonObject>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT QJsonArray fromJsonValue<QJsonArray>(const QJsonValue &value);

template<>
LANGUAGESERVERPROTOCOL_EXPORT QJsonValue fromJsonValue<QJsonValue>(const QJsonValue &value);

template <typename T>
class LanguageClientArray : public std::variant<QList<T>, std::nullptr_t>
{
public:
    using std::variant<QList<T>, std::nullptr_t>::variant;
    using std::variant<QList<T>, std::nullptr_t>::operator=;

    LanguageClientArray() {}

    explicit LanguageClientArray(const QList<T> &list)
    { *this = list; }

    explicit LanguageClientArray(const QJsonValue &value)
    {
        if (value.isArray()) {
            QList<T> values;
            values.reserve(value.toArray().count());
            for (auto arrayValue : value.toArray())
                values << fromJsonValue<T>(arrayValue);
            *this = values;
        } else {
            *this = nullptr;
        }
    }

    QJsonValue toJson() const
    {
        if (const auto list = std::get_if<QList<T>>(this)) {
            QJsonArray array;
            for (const T &value : *list)
                array.append(QJsonValue(value));
            return array;
        }
        return QJsonValue();
    }

    QList<T> toListOrEmpty() const
    {
        if (std::holds_alternative<QList<T>>(*this))
            return std::get<QList<T>>(*this);
        return {};
    }

    QList<T> toList() const
    {
        QBS_ASSERT(std::holds_alternative<QList<T>>(*this), return {});
        return std::get<QList<T>>(*this);
    }
    bool isNull() const { return std::holds_alternative<std::nullptr_t>(*this); }
};

template <typename T>
class LanguageClientValue : public std::variant<T, std::nullptr_t>
{
public:
    using std::variant<T, std::nullptr_t>::operator=;

    LanguageClientValue() : std::variant<T, std::nullptr_t>(nullptr) { }
    LanguageClientValue(const T &value) : std::variant<T, std::nullptr_t>(value) { }
    LanguageClientValue(const QJsonValue &value)
    {
        if (!QBS_GUARD(!value.isUndefined()) || value.isNull())
            *this = nullptr;
        else
            *this = fromJsonValue<T>(value);
    }

    operator const QJsonValue() const
    {
        if (auto val = std::get_if<T>(this))
            return QJsonValue(*val);
        return QJsonValue();
    }

    T value(const T &defaultValue = T()) const
    {
        QBS_ASSERT(std::holds_alternative<T>(*this), return defaultValue);
        return std::get<T>(*this);
    }

    template<typename Type>
    LanguageClientValue<Type> transform()
    {
        QBS_ASSERT(!std::holds_alternative<T>(*this), return LanguageClientValue<Type>());
        return Type(std::get<T>(*this));
    }

    bool isNull() const { return std::holds_alternative<std::nullptr_t>(*this); }
};

template <typename T>
QJsonArray enumArrayToJsonArray(const QList<T> &values)
{
    QJsonArray array;
    for (T value : values)
        array.append(static_cast<int>(value));
    return array;
}

template <typename T>
QList<T> jsonArrayToList(const QJsonArray &array)
{
    QList<T> list;
    for (const QJsonValue &val : array)
        list << fromJsonValue<T>(val);
    return list;
}

} // namespace lsp