♻️ 重构优化LSPAny相关代码

This commit is contained in:
csh
2025-11-02 15:47:40 +08:00
parent c690b76fcf
commit a81d9de71d
7 changed files with 512 additions and 585 deletions
+201 -216
View File
@@ -1,249 +1,210 @@
#pragma once
#include "./transformer.hpp"
namespace lsp::transform
{
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(protocol::boolean value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(int value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long long value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned int value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned long value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned long long value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(float value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(double value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long double value)
{
return protocol::LSPAny(value);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const protocol::string& str)
{
return protocol::LSPAny(str);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const char* str)
{
return protocol::LSPAny(str);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(std::nullptr_t)
{
return protocol::LSPAny(nullptr);
}
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const protocol::LSPAny& any)
{
return any;
}
inline protocol::boolean LSPAnyConverter::ToBool(const protocol::LSPAny& any)
{
if (!any.is<protocol::boolean>())
throw ConversionError("LSPAny does not contain a boolean");
return any.get<protocol::boolean>();
}
inline protocol::string LSPAnyConverter::ToString(const protocol::LSPAny& any)
{
if (!any.is<protocol::string>())
throw ConversionError("LSPAny does not contain a string");
return any.get<protocol::string>();
}
inline protocol::LSPObject LSPAnyConverter::ToLSPObject(const protocol::LSPAny& any)
{
if (!any.is<protocol::LSPObject>())
throw ConversionError("LSPAny does not contain LSPObject");
return any.get<protocol::LSPObject>();
}
inline protocol::LSPArray LSPAnyConverter::ToLSPArray(const protocol::LSPAny& any)
{
if (!any.is<protocol::LSPArray>())
throw ConversionError("LSPAny does not contain LSPArray");
return any.get<protocol::LSPArray>();
}
// 模板实现
template<typename T>
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::vector<T>& vec)
{
protocol::LSPArray arr;
arr.reserve(vec.size());
for (const auto& item : vec)
arr.push_back(ToLSPAny(item));
return protocol::LSPAny(std::move(arr));
}
// ==================== ToLSPAny 实现 ====================
template<typename T>
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::map<protocol::string, T>& map)
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const T& value)
{
protocol::LSPObject obj;
for (const auto& [key, value] : map)
obj[key] = ToLSPAny(value);
return protocol::LSPAny(std::move(obj));
}
using Type = std::decay_t<T>;
template<typename T>
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::optional<T>& opt)
{
if (opt.has_value())
return ToLSPAny(*opt);
return protocol::LSPAny(nullptr);
}
template<typename T>
inline typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type
LSPAnyConverter::ToLSPAny(const T& obj)
{
try
// LSPAny 直接返回
if constexpr (std::is_same_v<Type, protocol::LSPAny>)
{
// 使用glaze序列化为JSON字符串
std::string json;
auto ec = glz::write_json(obj, json);
if (ec)
{
throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json)));
}
return value;
}
// LSPObject 直接返回
else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
{
return protocol::LSPAny(value);
}
// LSPArray 直接返回
else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
{
return protocol::LSPAny(value);
}
else if constexpr (std::is_same_v<Type, const char*> ||
std::is_same_v<Type, char*>)
{
return protocol::LSPAny(protocol::string(value));
}
// LSP 基本类型(boolean, string, decimal, nullptr
else if constexpr (is_lsp_basic_type_v<Type>)
{
return protocol::LSPAny(value);
}
// 整数类型(依赖 LSPAny 模板构造函数)
else if constexpr (std::is_integral_v<Type> &&
!std::is_same_v<Type, bool>)
{
return protocol::LSPAny(value);
}
// 浮点类型
else if constexpr (std::is_floating_point_v<Type>)
{
return protocol::LSPAny(value);
}
// vector → LSPArray
else if constexpr (is_vector_v<Type>)
{
protocol::LSPArray arr;
arr.reserve(value.size());
for (const auto& item : value)
arr.push_back(ToLSPAny(item));
return protocol::LSPAny(std::move(arr));
}
// map → LSPObject
else if constexpr (is_map_v<Type>)
{
protocol::LSPObject obj;
for (const auto& [key, val] : value)
obj[key] = ToLSPAny(val);
return protocol::LSPAny(std::move(obj));
}
// optional → LSPAny or null
else if constexpr (is_optional_v<Type>)
{
if (value.has_value())
return ToLSPAny(*value);
return protocol::LSPAny(nullptr);
}
// 用户结构体 → LSPAny (通过 JSON)
else if constexpr (is_user_struct_v<Type>)
{
return SerializeViaJson(value);
}
else
{
static_assert(!sizeof(Type), "Unsupported type for ToLSPAny");
}
}
// 直接解析为LSPAny
protocol::LSPAny result;
ec = glz::read_json(result, json);
if (ec)
{
throw ConversionError("Failed to parse JSON to LSPAny: " + std::string(glz::format_error(ec, json)));
}
// ==================== FromLSPAny 实现 ====================
template<typename T>
inline T LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any)
{
using Type = std::decay_t<T>;
// LSPAny 直接返回
if constexpr (std::is_same_v<Type, protocol::LSPAny>)
{
return any;
}
// LSPObject 提取
else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
{
if (!any.Is<protocol::LSPObject>())
throw ConversionError("LSPAny does not contain LSPObject");
return any.Get<protocol::LSPObject>();
}
// LSPArray 提取
else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
{
if (!any.Is<protocol::LSPArray>())
throw ConversionError("LSPAny does not contain LSPArray");
return any.Get<protocol::LSPArray>();
}
// boolean 提取
else if constexpr (std::is_same_v<Type, bool>)
{
if (!any.Is<protocol::boolean>())
throw ConversionError("LSPAny does not contain a boolean");
return any.Get<protocol::boolean>();
}
// string 提取
else if constexpr (std::is_same_v<Type, protocol::string> ||
std::is_same_v<Type, std::string>)
{
if (!any.Is<protocol::string>())
throw ConversionError("LSPAny does not contain a string");
return any.Get<protocol::string>();
}
// 数字类型提取
else if constexpr (std::is_arithmetic_v<Type> &&
!std::is_same_v<Type, bool>)
{
return ExtractNumber<Type>(any);
}
// vector 提取
else if constexpr (is_vector_v<Type>)
{
if (!any.Is<protocol::LSPArray>())
throw ConversionError("LSPAny does not contain an array");
const auto& arr = any.Get<protocol::LSPArray>();
Type result;
result.reserve(arr.size());
for (const auto& item : arr)
result.push_back(FromLSPAny<typename Type::value_type>(item));
return result;
}
catch (const std::exception& e)
// map 提取
else if constexpr (is_map_v<Type>)
{
throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what()));
if (!any.Is<protocol::LSPObject>())
throw ConversionError("LSPAny does not contain an object");
const auto& obj = any.Get<protocol::LSPObject>();
Type result;
for (const auto& [key, val] : obj)
result[key] = FromLSPAny<typename Type::mapped_type>(val);
return result;
}
// optional 提取
else if constexpr (is_optional_v<Type>)
{
if (any.Is<std::nullptr_t>())
return std::nullopt;
return FromLSPAny<typename Type::value_type>(any);
}
// 用户结构体提取(通过 JSON)
else if constexpr (is_user_struct_v<Type>)
{
return ConvertViaJson<Type>(any);
}
else
{
static_assert(!sizeof(Type), "Unsupported type for FromLSPAny");
}
}
// Fromprotocol::LSPAny 实现
// ==================== 辅助工具实现 ====================
template<typename T>
inline typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, protocol::boolean>::value, T>::type LSPAnyConverter::ToNumber(const protocol::LSPAny& any)
inline T LSPAnyConverter::ExtractNumber(const protocol::LSPAny& any)
{
if (!any.is<protocol::decimal>())
throw ConversionError("LSPAny does not contain a number");
return static_cast<T>(any.get<protocol::decimal>());
if (any.Is<protocol::integer>())
{
return static_cast<T>(any.Get<protocol::integer>());
}
else if (any.Is<protocol::uinteger>())
{
return static_cast<T>(any.Get<protocol::uinteger>());
}
else if (any.Is<protocol::decimal>())
{
return static_cast<T>(any.Get<protocol::decimal>());
}
else
{
throw ConversionError("LSPAny does not contain a number (integer/uinteger/decimal)");
}
}
template<typename T>
inline std::vector<T> LSPAnyConverter::ToVector(const protocol::LSPAny& any)
{
if (!any.is<protocol::LSPArray>())
throw ConversionError("LSPAny does not contain an array");
const auto& arr = any.get<protocol::LSPArray>();
std::vector<T> result;
result.reserve(arr.size());
for (const auto& item : arr)
result.push_back(FromLSPAny<T>(item));
return result;
}
template<typename T>
inline std::optional<T> LSPAnyConverter::ToOptional(const protocol::LSPAny& any)
{
if (any.is<std::nullptr_t>())
return std::nullopt;
return FromLSPAny<T>(any);
}
template<typename T>
inline typename std::enable_if<is_user_struct<T>::value, T>::type
LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any)
{
return FromLSPAnyImpl<T>(any);
}
// 处理 std::optional<T>
template<typename T, typename From>
inline std::optional<T> LSPAnyConverter::As(const std::optional<From>& opt)
{
if (opt.has_value())
return As<T>(*opt);
return std::nullopt;
}
// 处理 std::variant<Ts...>
template<typename T, typename... Ts>
inline T LSPAnyConverter::As(const std::variant<Ts...>& var)
{
return std::visit([](const auto& val) -> T {
return As<T>(val);
}, var);
}
// 处理 LSPObject
template<typename T>
inline T LSPAnyConverter::As(const protocol::LSPObject& obj)
{
protocol::LSPAny any(obj);
return FromLSPAny<T>(any);
}
// 处理 LSPArray
template<typename T>
inline T LSPAnyConverter::As(const protocol::LSPArray& arr)
{
protocol::LSPAny any(arr);
return FromLSPAny<T>(any);
}
// FromLSPAnyImpl 实现
template<typename T>
inline T LSPAnyConverter::FromLSPAnyImpl(const protocol::LSPAny& any)
inline T LSPAnyConverter::ConvertViaJson(const protocol::LSPAny& any)
{
try
{
// 序列化LSPAnyJSON
// 序列化 LSPAnyJSON
std::string json;
auto ec = glz::write_json(any.value, json);
if (ec)
throw ConversionError("Failed to serialize LSPAny to JSON: " + std::string(glz::format_error(ec, json)));
// 解析JSON到目标类型
// 解析 JSON 到目标类型
T result;
ec = glz::read_json(result, json);
if (ec)
@@ -256,4 +217,28 @@ namespace lsp::transform
}
}
template<typename T>
inline protocol::LSPAny LSPAnyConverter::SerializeViaJson(const T& obj)
{
try
{
// 使用 glaze 序列化为 JSON 字符串
std::string json;
auto ec = glz::write_json(obj, json);
if (ec)
throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json)));
// 直接解析为 LSPAny
protocol::LSPAny result;
ec = glz::read_json(result, json);
if (ec)
throw ConversionError("Failed to parse JSON to LSPAny: " + std::string(glz::format_error(ec, json)));
return result;
}
catch (const std::exception& e)
{
throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what()));
}
}
}