♻️ 重构优化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

View File

@ -1,8 +1,10 @@
#pragma once
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <map>
#include <type_traits>
#include <variant>
#include <vector>
@ -16,6 +18,7 @@ namespace lsp::protocol
using string = std::string;
// LSPAny 这样设计是为了glaz序列化
// export type LSPAny = LSPObject | LSPArray | string | integer | uinteger | decimal | boolean | null;
struct LSPAny;
using LSPObject = std::map<string, LSPAny>;
using LSPArray = std::vector<LSPAny>;
@ -26,7 +29,9 @@ namespace lsp::protocol
LSPObject,
LSPArray,
string,
decimal, // 放在前面,优先匹配数字
integer,
uinteger,
decimal,
boolean,
std::nullptr_t>;
@ -34,69 +39,74 @@ namespace lsp::protocol
// 默认构造函数
LSPAny();
// 拷贝和移动构造函数
LSPAny(const LSPAny& other);
LSPAny(LSPAny&& other) noexcept;
// 针对每种支持的类型的构造函数
LSPAny(const std::map<string, LSPAny>& val);
LSPAny(std::map<string, LSPAny>&& val);
LSPAny(const std::vector<LSPAny>& val);
LSPAny(std::vector<LSPAny>&& val);
// 容器类型的构造函数
LSPAny(const LSPObject& val);
LSPAny(LSPObject&& val);
LSPAny(const LSPArray& val);
LSPAny(LSPArray&& val);
// 字符串类型的构造函数
LSPAny(const string& val);
LSPAny(string&& val);
LSPAny(const char* val);
// 所有数字类型都转换为 decimal
LSPAny(int val);
LSPAny(long val);
LSPAny(long long val);
LSPAny(unsigned int val);
LSPAny(unsigned long val);
LSPAny(unsigned long long val);
// 浮点类型的构造函数 -- decimal
LSPAny(float val);
LSPAny(double val);
LSPAny(long double val);
// 布尔和空值
LSPAny(boolean val);
LSPAny(std::nullptr_t);
// 单个模板处理所有整数类型
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
LSPAny(T val);
// 赋值操作符
LSPAny& operator=(const LSPAny& other);
LSPAny& operator=(LSPAny&& other) noexcept;
LSPAny& operator=(const std::map<string, LSPAny>& val);
LSPAny& operator=(std::map<string, LSPAny>&& val);
LSPAny& operator=(const std::vector<LSPAny>& val);
LSPAny& operator=(std::vector<LSPAny>&& val);
LSPAny& operator=(const LSPObject& val);
LSPAny& operator=(LSPObject&& val);
LSPAny& operator=(const LSPArray& val);
LSPAny& operator=(LSPArray&& val);
LSPAny& operator=(const string& val);
LSPAny& operator=(string&& val);
LSPAny& operator=(const char* val);
LSPAny& operator=(int val);
LSPAny& operator=(long val);
LSPAny& operator=(long long val);
LSPAny& operator=(unsigned int val);
LSPAny& operator=(unsigned long val);
LSPAny& operator=(unsigned long long val);
LSPAny& operator=(float val);
LSPAny& operator=(double val);
LSPAny& operator=(long double val);
LSPAny& operator=(boolean val);
LSPAny& operator=(std::nullptr_t);
// 整数类型赋值 - 使用模板避免类型冲突
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
LSPAny& operator=(T val);
// 类型检查辅助函数
template<typename T>
bool is() const;
bool Is() const;
template<typename T>
T& get();
T& Get();
template<typename T>
const T& get() const;
const T& Get() const;
// 访问操作符
template<typename Visitor>
auto visit(Visitor&& visitor) const;
auto Visit(Visitor&& visitor) const;
template<typename Visitor>
auto visit(Visitor&& visitor);
auto Visit(Visitor&& visitor);
};
using ProgressToken = std::variant<integer, string>;
@ -227,33 +237,75 @@ namespace lsp::protocol
};
// LSP模板方法
template<typename T, typename>
LSPAny::LSPAny(T val)
{
if constexpr (std::is_signed_v<T>)
{
// 有符号整数
if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
value = static_cast<integer>(val);
else
value = static_cast<decimal>(val); // 超出 int32 范围,转为 decimal可能丢失精度
}
else
{
// 无符号整数
if (val <= std::numeric_limits<uinteger>::max())
value = static_cast<uinteger>(val);
else
value = static_cast<decimal>(val); // 超出 uint32 范围,转为 decimal可能丢失精度
}
}
template<typename T, typename>
LSPAny& LSPAny::operator=(T val)
{
if constexpr (std::is_signed_v<T>)
{
// 有符号整数
if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
value = static_cast<integer>(val);
else
value = static_cast<decimal>(val);
}
else
{
if (val <= std::numeric_limits<uinteger>::max())
value = static_cast<uinteger>(val);
else
value = static_cast<decimal>(val);
}
return *this;
}
template<typename T>
bool LSPAny::is() const
bool LSPAny::Is() const
{
return std::holds_alternative<T>(value);
}
template<typename T>
T& LSPAny::get()
T& LSPAny::Get()
{
return std::get<T>(value);
}
template<typename T>
const T& LSPAny::get() const
const T& LSPAny::Get() const
{
return std::get<T>(value);
}
// 访问操作符
template<typename Visitor>
auto LSPAny::visit(Visitor&& visitor) const
auto LSPAny::Visit(Visitor&& visitor) const
{
return std::visit(std::forward<Visitor>(visitor), value);
}
template<typename Visitor>
auto LSPAny::visit(Visitor&& visitor)
auto LSPAny::Visit(Visitor&& visitor)
{
return std::visit(std::forward<Visitor>(visitor), value);
}

View File

@ -1,5 +1,5 @@
#pragma once
#include "./basic_types.hpp"
// #include "./basic_types.hpp"
namespace lsp::protocol
{
@ -13,16 +13,16 @@ namespace lsp::protocol
inline LSPAny::LSPAny(LSPAny&& other) noexcept :
value(std::move(other.value)) {}
inline LSPAny::LSPAny(const std::map<string, LSPAny>& val) :
inline LSPAny::LSPAny(const LSPObject& val) :
value(val) {}
inline LSPAny::LSPAny(std::map<string, LSPAny>&& val) :
inline LSPAny::LSPAny(LSPObject&& val) :
value(std::move(val)) {}
inline LSPAny::LSPAny(const std::vector<LSPAny>& val) :
inline LSPAny::LSPAny(const LSPArray& val) :
value(val) {}
inline LSPAny::LSPAny(std::vector<LSPAny>&& val) :
inline LSPAny::LSPAny(LSPArray&& val) :
value(std::move(val)) {}
inline LSPAny::LSPAny(const string& val) :
@ -34,24 +34,6 @@ namespace lsp::protocol
inline LSPAny::LSPAny(const char* val) :
value(string(val)) {}
inline LSPAny::LSPAny(int val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(long val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(long long val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(unsigned int val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(unsigned long val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(unsigned long long val) :
value(static_cast<decimal>(val)) {}
inline LSPAny::LSPAny(float val) :
value(static_cast<decimal>(val)) {}
@ -80,26 +62,25 @@ namespace lsp::protocol
return *this;
}
// 针对每种支持的类型的赋值操作符
inline LSPAny& LSPAny::operator=(const std::map<string, LSPAny>& val)
inline LSPAny& LSPAny::operator=(const LSPObject& val)
{
value = val;
return *this;
}
inline LSPAny& LSPAny::operator=(std::map<string, LSPAny>&& val)
inline LSPAny& LSPAny::operator=(LSPObject&& val)
{
value = std::move(val);
return *this;
}
inline LSPAny& LSPAny::operator=(const std::vector<LSPAny>& val)
inline LSPAny& LSPAny::operator=(const LSPArray& val)
{
value = val;
return *this;
}
inline LSPAny& LSPAny::operator=(std::vector<LSPAny>&& val)
inline LSPAny& LSPAny::operator=(LSPArray&& val)
{
value = std::move(val);
return *this;
@ -123,43 +104,6 @@ namespace lsp::protocol
return *this;
}
// 所有数字类型都转换为 decimal
inline LSPAny& LSPAny::operator=(int val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(long val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(long long val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(unsigned int val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(unsigned long val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(unsigned long long val)
{
value = static_cast<decimal>(val);
return *this;
}
inline LSPAny& LSPAny::operator=(float val)
{
value = static_cast<decimal>(val);

View File

@ -1,40 +1,105 @@
#pragma once
#include <type_traits>
#include <stdexcept>
#include <vector>
#include <map>
#include <optional>
#include <variant>
#include "../detail/basic_types.hpp"
namespace lsp::transform
{
// 通用错误
/// 转换错误异常
class ConversionError : public std::runtime_error
{
public:
explicit ConversionError(const std::string& message)
: std::runtime_error("LSP Conversion Error: " + message) {}
explicit ConversionError(const std::string& message) : std::runtime_error("LSP Conversion Error: " + message) {}
};
/// 类型特征LSP 基本类型判断
template<typename T>
inline constexpr bool is_lsp_basic_type_v =
std::is_same_v<T, protocol::integer> ||
std::is_same_v<T, protocol::uinteger> ||
std::is_same_v<T, protocol::decimal> ||
std::is_same_v<T, protocol::boolean> ||
std::is_same_v<T, protocol::string> ||
std::is_same_v<T, std::nullptr_t>;
/// 类型特征LSP 容器类型判断
template<typename T>
inline constexpr bool is_lsp_container_type_v =
std::is_same_v<T, protocol::LSPObject> ||
std::is_same_v<T, protocol::LSPArray> ||
std::is_same_v<T, protocol::LSPAny>;
/// 类型特征:检测 vector
template<typename T>
struct is_vector : std::false_type
{
};
template<typename T>
struct is_lsp_basic_type: std::false_type {};
template<> struct is_lsp_basic_type<protocol::boolean> : std::true_type {};
template<> struct is_lsp_basic_type<protocol::string> : std::true_type {};
template<> struct is_lsp_basic_type<protocol::decimal> : std::true_type {};
template<> struct is_lsp_basic_type<std::nullptr_t> : std::true_type {};
struct is_vector<std::vector<T>> : std::true_type
{
};
template<typename T>
struct is_lsp_container_type : std::false_type {};
inline constexpr bool is_vector_v = is_vector<T>::value;
template<> struct is_lsp_container_type<protocol::LSPObject> : std::true_type {};
template<> struct is_lsp_container_type<protocol::LSPArray> : std::true_type {};
template<> struct is_lsp_container_type<protocol::LSPAny> : std::true_type {};
// struct类型判断
/// 类型特征:检测 map
template<typename T>
struct is_user_struct : std::integral_constant<bool,
!std::is_arithmetic<T>::value &&
!std::is_same<T, protocol::string>::value &&
!std::is_same<T, const char*>::value &&
!std::is_same<T, std::nullptr_t>::value &&
!is_lsp_basic_type<T>::value &&
!is_lsp_container_type<T>::value> {};
struct is_map : std::false_type
{
};
template<typename K, typename V>
struct is_map<std::map<K, V>> : std::true_type
{
};
template<typename T>
inline constexpr bool is_map_v = is_map<T>::value;
/// 类型特征:检测 optional
template<typename T>
struct is_optional : std::false_type
{
};
template<typename T>
struct is_optional<std::optional<T>> : std::true_type
{
};
template<typename T>
inline constexpr bool is_optional_v = is_optional<T>::value;
/// 类型特征:检测 variant
template<typename T>
struct is_variant : std::false_type
{
};
template<typename... Ts>
struct is_variant<std::variant<Ts...>> : std::true_type
{
};
template<typename T>
inline constexpr bool is_variant_v = is_variant<T>::value;
/// 类型特征:用户自定义 struct 判断
template<typename T>
inline constexpr bool is_user_struct_v =
std::is_class_v<T> &&
!std::is_pointer_v<T> &&
!std::is_same_v<T, protocol::string> &&
!std::is_same_v<T, std::string> &&
!is_lsp_basic_type_v<T> &&
!is_lsp_container_type_v<T> &&
!is_vector_v<T> &&
!is_map_v<T> &&
!is_optional_v<T> &&
!is_variant_v<T>;
}

View File

@ -3,106 +3,68 @@
namespace lsp::transform
{
// ==================== JSON 序列化/反序列化 ====================
// ===== 全局便利函数 =====
template<typename T>
std::optional<T> Deserialize(const std::string& json);
template<typename T>
std::optional<std::string> Serialize(const T& obj);
// 基本类型
template<typename T>
protocol::LSPAny LSPAny(const T& obj);
// ==================== 转换为 LSPAny ====================
// // struct 类型
// template<typename T>
// typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type LSPAny(const T& value);
/// 任意类型转换为 LSPAny
///
/// 支持的类型:
/// - 基本类型bool, int, double, string, nullptr
/// - 容器类型vector, map, optional
/// - LSP 类型LSPObject, LSPArray, LSPAny
/// - 用户结构体(需要 glaze 支持)
inline constexpr auto ToLSPAny = [](const auto& value) {
return LSPAnyConverter::ToLSPAny(value);
};
// 容器类型
template<typename T>
protocol::LSPAny LSPAny(const std::vector<T>& vec);
/// LSPAny 转换为指定类型
///
/// 支持的类型:
/// - 基本类型bool, int, double, string
/// - 容器类型vector<T>, optional<T>
/// - LSP 类型LSPObject, LSPArray
/// - 用户结构体(需要 glaze 支持)
inline constexpr auto FromLSPAny = []<typename T>(const protocol::LSPAny& any) -> T {
return LSPAnyConverter::FromLSPAny<T>(any);
};
template<typename T>
protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map);
template<typename T>
protocol::LSPAny LSPAny(const std::optional<T>& opt);
template<typename T>
T As(const protocol::LSPAny& any);
template<typename T, typename From>
std::optional<T> As(const std::optional<From>& opt);
template<typename T, typename... Ts>
T As(const std::variant<Ts...>& var);
template<typename T>
T As(const protocol::LSPObject& obj);
template<typename T>
T As(const protocol::LSPArray& arr);
template<typename T>
T Number(const protocol::LSPAny& any);
template<typename T>
std::vector<T> Vector(const protocol::LSPAny& any);
template<typename T>
std::optional<T> Optional(const protocol::LSPAny& any);
template<typename T>
protocol::LSPObject LSPObject(const T& obj);
template<typename T>
protocol::LSPArray LSPArray(const T& vec);
protocol::string String(const protocol::LSPAny& any);
protocol::boolean Bool(const protocol::LSPAny& any);
// === 外观接口:类型检查 ===
namespace check
{
inline bool IsObject(const protocol::LSPAny& any) { return any.is<protocol::LSPObject>(); }
inline bool IsArray(const protocol::LSPAny& any) { return any.is<protocol::LSPArray>(); }
inline bool IsString(const protocol::LSPAny& any) { return any.is<protocol::string>(); }
inline bool IsNumber(const protocol::LSPAny& any) { return any.is<protocol::decimal>(); }
inline bool IsBool(const protocol::LSPAny& any) { return any.is<protocol::boolean>(); }
inline bool IsNull(const protocol::LSPAny& any) { return any.is<std::nullptr_t>(); }
/// 检查是否为 LSPObject
bool IsObject(const protocol::LSPAny& any);
/// 检查是否为 LSPArray
bool IsArray(const protocol::LSPAny& any);
/// 检查是否为字符串
bool IsString(const protocol::LSPAny& any);
/// 检查是否为数字integer/uinteger/decimal
bool IsNumber(const protocol::LSPAny& any);
/// 检查是否为布尔值
bool IsBool(const protocol::LSPAny& any);
/// 检查是否为 null
bool IsNull(const protocol::LSPAny& any);
}
// === 外观接口:调试功能 ===
// ==================== 调试工具 ====================
namespace debug
{
inline std::string GetTypeName(const protocol::LSPAny& any)
{
if (any.is<protocol::LSPObject>())
return "LSPObject";
if (any.is<protocol::LSPArray>())
return "LSPArray";
if (any.is<protocol::string>())
return "string";
if (any.is<protocol::decimal>())
return "decimal";
if (any.is<protocol::boolean>())
return "boolean";
if (any.is<std::nullptr_t>())
return "null";
return "unknown";
}
/// 获取 LSPAny 的类型名称字符串
std::string GetTypeName(const protocol::LSPAny& any);
inline std::string GetIdString(const std::variant<int, std::string>& id)
{
return std::visit([](const auto& value) -> std::string {
if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
return std::to_string(value);
else
return value;
}, id);
}
/// 将 variant<int, string> 转换为字符串(用于 ID
std::string GetIdString(const std::variant<int, std::string>& id);
}
}

View File

@ -1,8 +1,10 @@
#pragma once
#include "./facade.hpp"
// #include "./facade.hpp"
namespace lsp::transform
{
// ==================== JSON 序列化/反序列化 ====================
template<typename T>
inline std::optional<T> Deserialize(const std::string& json)
{
@ -25,118 +27,77 @@ namespace lsp::transform
return json;
}
template<typename T>
inline protocol::LSPAny LSPAny(const T& obj)
{
return LSPAnyConverter::ToLSPAny(obj);
}
// ==================== 类型检查 ====================
template<typename T>
inline protocol::LSPAny LSPAny(const std::vector<T>& vec)
namespace check
{
return LSPAnyConverter::ToLSPAny(vec);
}
template<typename T>
inline protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map)
{
return LSPAnyConverter::ToLSPAny(map);
}
template<typename T>
inline protocol::LSPAny LSPAny(const std::optional<T>& opt)
{
return LSPAnyConverter::ToLSPAny(opt);
}
template<typename T>
inline T As(const protocol::LSPAny& any)
{
return LSPAnyConverter::FromLSPAny<T>(any);
}
template<typename T, typename From>
inline std::optional<T> As(const std::optional<From>& opt)
{
return LSPAnyConverter::As<T>(opt);
}
template<typename T, typename... Ts>
inline T As(const std::variant<Ts...>& var)
{
return LSPAnyConverter::As<T>(var);
}
template<typename T>
inline T As(const protocol::LSPObject& obj)
{
return LSPAnyConverter::As<T>(obj);
}
template<typename T>
inline T As(const protocol::LSPArray& arr)
{
return LSPAnyConverter::As<T>(arr);
}
template<typename T>
inline T Number(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToNumber<T>(any);
}
template<typename T>
inline std::vector<T> Vector(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToVector<T>(any);
}
template<typename T>
inline std::optional<T> Optional(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToOptional<T>(any);
}
template<typename T>
inline protocol::LSPObject LSPObject(const T& obj)
{
// 如果已经是 LSPAny直接获取其中的 LSPObject
if constexpr (std::is_same_v<T, protocol::LSPAny>)
inline bool IsObject(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToLSPObject(obj);
return any.Is<protocol::LSPObject>();
}
else
inline bool IsArray(const protocol::LSPAny& any)
{
// 否则先转换为 LSPAny再获取 LSPObject
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(obj);
return LSPAnyConverter::ToLSPObject(any);
return any.Is<protocol::LSPArray>();
}
inline bool IsString(const protocol::LSPAny& any)
{
return any.Is<protocol::string>();
}
inline bool IsNumber(const protocol::LSPAny& any)
{
return any.Is<protocol::integer>() ||
any.Is<protocol::uinteger>() ||
any.Is<protocol::decimal>();
}
inline bool IsBool(const protocol::LSPAny& any)
{
return any.Is<protocol::boolean>();
}
inline bool IsNull(const protocol::LSPAny& any)
{
return any.Is<std::nullptr_t>();
}
}
template<typename T>
inline protocol::LSPArray LSPArray(const T& container)
// ==================== 调试工具 ====================
namespace debug
{
// 如果已经是 LSPAny直接获取其中的 LSPArray
if constexpr (std::is_same_v<T, protocol::LSPAny>)
inline std::string GetTypeName(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToLSPArray(container);
if (any.Is<protocol::LSPObject>())
return "LSPObject";
if (any.Is<protocol::LSPArray>())
return "LSPArray";
if (any.Is<protocol::string>())
return "string";
if (any.Is<protocol::integer>())
return "integer";
if (any.Is<protocol::uinteger>())
return "uinteger";
if (any.Is<protocol::decimal>())
return "decimal";
if (any.Is<protocol::boolean>())
return "boolean";
if (any.Is<std::nullptr_t>())
return "null";
return "unknown";
}
else
inline std::string GetIdString(const std::variant<int, std::string>& id)
{
// 否则转换为 LSPAny
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(container);
return LSPAnyConverter::ToLSPArray(any);
return std::visit([](const auto& value) -> std::string {
if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
return std::to_string(value);
else
return value;
},
id);
}
}
inline protocol::string String(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToString(any);
}
inline protocol::boolean Bool(const protocol::LSPAny& any)
{
return LSPAnyConverter::ToBool(any);
}
}

View File

@ -4,82 +4,40 @@
namespace lsp::transform
{
// LSPAny 序列化/反序列化工具类
/// LSPAny 转换核心类
/// 提供所有类型的双向转换
class LSPAnyConverter
{
public:
// === 基本类型的转换 ===
static protocol::LSPAny ToLSPAny(protocol::boolean value);
static protocol::LSPAny ToLSPAny(int value);
static protocol::LSPAny ToLSPAny(long value);
static protocol::LSPAny ToLSPAny(long long value);
static protocol::LSPAny ToLSPAny(unsigned int value);
static protocol::LSPAny ToLSPAny(unsigned long value);
static protocol::LSPAny ToLSPAny(unsigned long long value);
static protocol::LSPAny ToLSPAny(float value);
static protocol::LSPAny ToLSPAny(double value);
static protocol::LSPAny ToLSPAny(long double value);
static protocol::LSPAny ToLSPAny(const protocol::string& str);
static protocol::LSPAny ToLSPAny(const char* str);
static protocol::LSPAny ToLSPAny(std::nullptr_t);
static protocol::LSPAny ToLSPAny(const protocol::LSPAny& any);
// ==================== 任意类型 → LSPAny ====================
// === LSPAny 到基本类型的转换 ===
static protocol::boolean ToBool(const protocol::LSPAny& any);
static protocol::string ToString(const protocol::LSPAny& any);
// 其他转换
static protocol::LSPObject ToLSPObject(const protocol::LSPAny& any);
static protocol::LSPArray ToLSPArray(const protocol::LSPAny& any);
// === 容器类型的转换 ===
/// 通用转换入口:任意类型 → LSPAny
/// 根据类型特征自动分派到具体实现
template<typename T>
static protocol::LSPAny ToLSPAny(const std::vector<T>& vec);
static protocol::LSPAny ToLSPAny(const T& value);
// ==================== LSPAny → 任意类型 ====================
/// 通用转换入口LSPAny → 任意类型
/// 根据类型特征自动分派到具体实现
template<typename T>
static protocol::LSPAny ToLSPAny(const std::map<protocol::string, T>& map);
template<typename T>
static protocol::LSPAny ToLSPAny(const std::optional<T>& opt);
// === Struct 到 LSPAny 的转换 ===
template<typename T>
static typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type ToLSPAny(const T& obj);
template<typename T>
static typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, protocol::boolean>::value, T>::type ToNumber(const protocol::LSPAny& any);
// === LSPAny 到容器类型的转换 ===
template<typename T>
static std::vector<T> ToVector(const protocol::LSPAny& any);
template<typename T>
static std::optional<T> ToOptional(const protocol::LSPAny& any);
template<typename T>
static typename std::enable_if<is_user_struct<T>::value, T>::type FromLSPAny(const protocol::LSPAny& any);
// 处理 std::optional<T>
template<typename T, typename From>
static std::optional<T> As(const std::optional<From>& opt);
// 处理 std::variant<Ts...>
template<typename T, typename... Ts>
static T As(const std::variant<Ts...>& var);
// 处理 LSPObject 和 LSPArray
template<typename T>
static T As(const protocol::LSPObject& obj);
template<typename T>
static T As(const protocol::LSPArray& arr);
static T FromLSPAny(const protocol::LSPAny& any);
private:
template<typename T>
static T FromLSPAnyImpl(const protocol::LSPAny& any);
};
// ==================== 辅助工具 ====================
/// 提取数字(支持三种数字类型)
template<typename T>
static T ExtractNumber(const protocol::LSPAny& any);
/// 通过 JSON 转换用户结构体
template<typename T>
static T ConvertViaJson(const protocol::LSPAny& any);
/// 将用户结构体序列化为 LSPAny
template<typename T>
static protocol::LSPAny SerializeViaJson(const T& obj);
};
}
#include "./transformer.inl"

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
{
// 序列化LSPAny为JSON
// 序列化 LSPAny 为 JSON
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()));
}
}
}