diff options
Diffstat (limited to 'src/shared/lsp/jsonobject.h')
-rw-r--r-- | src/shared/lsp/jsonobject.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/shared/lsp/jsonobject.h b/src/shared/lsp/jsonobject.h new file mode 100644 index 000000000..29811839f --- /dev/null +++ b/src/shared/lsp/jsonobject.h @@ -0,0 +1,181 @@ +// 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 "algorithm.h" +#include "languageserverprotocol_global.h" +#include "lsputils.h" + +#include <QCoreApplication> +#include <QDebug> +#include <QJsonObject> + +#include <optional> + +namespace lsp { + +class LANGUAGESERVERPROTOCOL_EXPORT JsonObject +{ +public: + using iterator = QJsonObject::iterator; + using const_iterator = QJsonObject::const_iterator; + + JsonObject() = default; + + explicit JsonObject(const QJsonObject &object) : m_jsonObject(object) { } + explicit JsonObject(QJsonObject &&object) : m_jsonObject(std::move(object)) { } + + JsonObject(const JsonObject &object) : m_jsonObject(object.m_jsonObject) { } + JsonObject(JsonObject &&object) : m_jsonObject(std::move(object.m_jsonObject)) { } + + explicit JsonObject(const QJsonValue &value) : m_jsonObject(value.toObject()) { } + + virtual ~JsonObject() = default; + + JsonObject &operator=(const JsonObject &other); + JsonObject &operator=(JsonObject &&other); + + bool operator==(const JsonObject &other) const { return m_jsonObject == other.m_jsonObject; } + + operator const QJsonObject&() const { return m_jsonObject; } + + virtual bool isValid() const { return true; } + + iterator end() { return m_jsonObject.end(); } + const_iterator end() const { return m_jsonObject.end(); } + + iterator insert(const std::string_view key, const JsonObject &value); + iterator insert(const std::string_view key, const QJsonValue &value); + +protected: + + template <typename T, typename V> + iterator insertVariant(const std::string_view key, const V &variant); + template <typename T1, typename T2, typename... Args, typename V> + iterator insertVariant(const std::string_view key, const V &variant); + + // QJSonObject redirections + QJsonValue value(const std::string_view key) const { return m_jsonObject.value(QLatin1String(key.data())); } + bool contains(const std::string_view key) const { return m_jsonObject.contains(QLatin1String(key.data())); } + iterator find(const std::string_view key) { return m_jsonObject.find(QLatin1String(key.data())); } + const_iterator find(const std::string_view key) const { return m_jsonObject.find(QLatin1String(key.data())); } + void remove(const std::string_view key) { m_jsonObject.remove(QLatin1String(key.data())); } + QStringList keys() const { return m_jsonObject.keys(); } + + // convenience value access + template<typename T> + T typedValue(const std::string_view key) const; + template<typename T> + std::optional<T> optionalValue(const std::string_view key) const; + template<typename T> + LanguageClientValue<T> clientValue(const std::string_view key) const; + template<typename T> + std::optional<LanguageClientValue<T>> optionalClientValue(const std::string_view key) const; + template<typename T> + QList<T> array(const std::string_view key) const; + template<typename T> + std::optional<QList<T>> optionalArray(const std::string_view key) const; + template<typename T> + LanguageClientArray<T> clientArray(const std::string_view key) const; + template<typename T> + std::optional<LanguageClientArray<T>> optionalClientArray(const std::string_view key) const; + template<typename T> + void insertArray(const std::string_view key, const QList<T> &array); + template<typename> + void insertArray(const std::string_view key, const QList<JsonObject> &array); + +private: + QJsonObject m_jsonObject; +}; + +template<typename T, typename V> +JsonObject::iterator JsonObject::insertVariant(const std::string_view key, const V &variant) +{ + return std::holds_alternative<T>(variant) ? insert(key, std::get<T>(variant)) : end(); +} + +template<typename T1, typename T2, typename... Args, typename V> +JsonObject::iterator JsonObject::insertVariant(const std::string_view key, const V &variant) +{ + auto result = insertVariant<T1>(key, variant); + return result != end() ? result : insertVariant<T2, Args...>(key, variant); +} + +template<typename T> +T JsonObject::typedValue(const std::string_view key) const +{ + return fromJsonValue<T>(value(key)); +} + +template<typename T> +std::optional<T> JsonObject::optionalValue(const std::string_view key) const +{ + const QJsonValue &val = value(key); + return val.isUndefined() ? std::nullopt : std::make_optional(fromJsonValue<T>(val)); +} + +template<typename T> +LanguageClientValue<T> JsonObject::clientValue(const std::string_view key) const +{ + return LanguageClientValue<T>(value(key)); +} + +template<typename T> +std::optional<LanguageClientValue<T>> JsonObject::optionalClientValue(const std::string_view key) const +{ + return contains(key) ? std::make_optional(clientValue<T>(key)) : std::nullopt; +} + +template<typename T> +QList<T> JsonObject::array(const std::string_view key) const +{ + if (const std::optional<QList<T>> &array = optionalArray<T>(key)) + return *array; + qCDebug(conversionLog) << QString("Expected array under %1 in:") + .arg(QLatin1String(key.data())) << *this; + return {}; +} + +template<typename T> +std::optional<QList<T>> JsonObject::optionalArray(const std::string_view key) const +{ + const QJsonValue &jsonValue = value(key); + if (jsonValue.isUndefined()) + return std::nullopt; + return Utils::transform<QList<T>>(jsonValue.toArray(), &fromJsonValue<T>); +} + +template<typename T> +LanguageClientArray<T> JsonObject::clientArray(const std::string_view key) const +{ + return LanguageClientArray<T>(value(key)); +} + +template<typename T> +std::optional<LanguageClientArray<T>> JsonObject::optionalClientArray(const std::string_view key) const +{ + const QJsonValue &val = value(key); + return !val.isUndefined() ? std::make_optional(LanguageClientArray<T>(value(key))) + : std::nullopt; +} + +template<typename T> +void JsonObject::insertArray(const std::string_view key, const QList<T> &array) +{ + QJsonArray jsonArray; + for (const T &item : array) + jsonArray.append(QJsonValue(item)); + insert(key, jsonArray); +} + +template<typename > +void JsonObject::insertArray(const std::string_view key, const QList<JsonObject> &array) +{ + QJsonArray jsonArray; + for (const JsonObject &item : array) + jsonArray.append(item.m_jsonObject); + insert(key, jsonArray); +} + +} // namespace lsp |