♻️ 重构优化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 #pragma once
#include <cstdint> #include <cstdint>
#include <limits>
#include <optional> #include <optional>
#include <string> #include <string>
#include <map> #include <map>
#include <type_traits>
#include <variant> #include <variant>
#include <vector> #include <vector>
@ -16,6 +18,7 @@ namespace lsp::protocol
using string = std::string; using string = std::string;
// LSPAny 这样设计是为了glaz序列化 // LSPAny 这样设计是为了glaz序列化
// export type LSPAny = LSPObject | LSPArray | string | integer | uinteger | decimal | boolean | null;
struct LSPAny; struct LSPAny;
using LSPObject = std::map<string, LSPAny>; using LSPObject = std::map<string, LSPAny>;
using LSPArray = std::vector<LSPAny>; using LSPArray = std::vector<LSPAny>;
@ -26,7 +29,9 @@ namespace lsp::protocol
LSPObject, LSPObject,
LSPArray, LSPArray,
string, string,
decimal, // 放在前面,优先匹配数字 integer,
uinteger,
decimal,
boolean, boolean,
std::nullptr_t>; std::nullptr_t>;
@ -34,69 +39,74 @@ namespace lsp::protocol
// 默认构造函数 // 默认构造函数
LSPAny(); LSPAny();
// 拷贝和移动构造函数 // 拷贝和移动构造函数
LSPAny(const LSPAny& other); LSPAny(const LSPAny& other);
LSPAny(LSPAny&& other) noexcept; LSPAny(LSPAny&& other) noexcept;
// 针对每种支持的类型的构造函数
LSPAny(const std::map<string, LSPAny>& val); // 容器类型的构造函数
LSPAny(std::map<string, LSPAny>&& val); LSPAny(const LSPObject& val);
LSPAny(const std::vector<LSPAny>& val); LSPAny(LSPObject&& val);
LSPAny(std::vector<LSPAny>&& val); LSPAny(const LSPArray& val);
LSPAny(LSPArray&& val);
// 字符串类型的构造函数
LSPAny(const string& val); LSPAny(const string& val);
LSPAny(string&& val); LSPAny(string&& val);
LSPAny(const char* val); LSPAny(const char* val);
// 所有数字类型都转换为 decimal // 浮点类型的构造函数 -- decimal
LSPAny(int val);
LSPAny(long val);
LSPAny(long long val);
LSPAny(unsigned int val);
LSPAny(unsigned long val);
LSPAny(unsigned long long val);
LSPAny(float val); LSPAny(float val);
LSPAny(double val); LSPAny(double val);
LSPAny(long double val); LSPAny(long double val);
// 布尔和空值
LSPAny(boolean val); LSPAny(boolean val);
LSPAny(std::nullptr_t); 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=(const LSPAny& other);
LSPAny& operator=(LSPAny&& other) noexcept; LSPAny& operator=(LSPAny&& other) noexcept;
LSPAny& operator=(const std::map<string, LSPAny>& val); LSPAny& operator=(const LSPObject& val);
LSPAny& operator=(std::map<string, LSPAny>&& val); LSPAny& operator=(LSPObject&& val);
LSPAny& operator=(const std::vector<LSPAny>& val); LSPAny& operator=(const LSPArray& val);
LSPAny& operator=(std::vector<LSPAny>&& val); LSPAny& operator=(LSPArray&& val);
LSPAny& operator=(const string& val); LSPAny& operator=(const string& val);
LSPAny& operator=(string&& val); LSPAny& operator=(string&& val);
LSPAny& operator=(const char* 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=(float val);
LSPAny& operator=(double val); LSPAny& operator=(double val);
LSPAny& operator=(long double val); LSPAny& operator=(long double val);
LSPAny& operator=(boolean val); LSPAny& operator=(boolean val);
LSPAny& operator=(std::nullptr_t); 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> template<typename T>
bool is() const; bool Is() const;
template<typename T> template<typename T>
T& get(); T& Get();
template<typename T> template<typename T>
const T& get() const; const T& Get() const;
// 访问操作符 // 访问操作符
template<typename Visitor> template<typename Visitor>
auto visit(Visitor&& visitor) const; auto Visit(Visitor&& visitor) const;
template<typename Visitor> template<typename Visitor>
auto visit(Visitor&& visitor); auto Visit(Visitor&& visitor);
}; };
using ProgressToken = std::variant<integer, string>; using ProgressToken = std::variant<integer, string>;
@ -227,33 +237,75 @@ namespace lsp::protocol
}; };
// LSP模板方法 // 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> template<typename T>
bool LSPAny::is() const bool LSPAny::Is() const
{ {
return std::holds_alternative<T>(value); return std::holds_alternative<T>(value);
} }
template<typename T> template<typename T>
T& LSPAny::get() T& LSPAny::Get()
{ {
return std::get<T>(value); return std::get<T>(value);
} }
template<typename T> template<typename T>
const T& LSPAny::get() const const T& LSPAny::Get() const
{ {
return std::get<T>(value); return std::get<T>(value);
} }
// 访问操作符 // 访问操作符
template<typename Visitor> template<typename Visitor>
auto LSPAny::visit(Visitor&& visitor) const auto LSPAny::Visit(Visitor&& visitor) const
{ {
return std::visit(std::forward<Visitor>(visitor), value); return std::visit(std::forward<Visitor>(visitor), value);
} }
template<typename Visitor> template<typename Visitor>
auto LSPAny::visit(Visitor&& visitor) auto LSPAny::Visit(Visitor&& visitor)
{ {
return std::visit(std::forward<Visitor>(visitor), value); return std::visit(std::forward<Visitor>(visitor), value);
} }

View File

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

View File

@ -1,40 +1,105 @@
#pragma once #pragma once
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
#include <vector>
#include <map>
#include <optional>
#include <variant>
#include "../detail/basic_types.hpp" #include "../detail/basic_types.hpp"
namespace lsp::transform namespace lsp::transform
{ {
// 通用错误 /// 转换错误异常
class ConversionError : public std::runtime_error class ConversionError : public std::runtime_error
{ {
public: public:
explicit ConversionError(const std::string& message) explicit ConversionError(const std::string& message) : std::runtime_error("LSP Conversion Error: " + 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> template<typename T>
struct is_lsp_basic_type: std::false_type {}; struct is_vector<std::vector<T>> : std::true_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 {};
template<typename T> 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 {}; /// 类型特征:检测 map
template<> struct is_lsp_container_type<protocol::LSPArray> : std::true_type {};
template<> struct is_lsp_container_type<protocol::LSPAny> : std::true_type {};
// struct类型判断
template<typename T> template<typename T>
struct is_user_struct : std::integral_constant<bool, struct is_map : std::false_type
!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 && template<typename K, typename V>
!is_lsp_basic_type<T>::value && struct is_map<std::map<K, V>> : std::true_type
!is_lsp_container_type<T>::value> {}; {
};
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 namespace lsp::transform
{ {
// ==================== JSON 序列化/反序列化 ====================
// ===== 全局便利函数 =====
template<typename T> template<typename T>
std::optional<T> Deserialize(const std::string& json); std::optional<T> Deserialize(const std::string& json);
template<typename T> template<typename T>
std::optional<std::string> Serialize(const T& obj); std::optional<std::string> Serialize(const T& obj);
// 基本类型 // ==================== 转换为 LSPAny ====================
template<typename T>
protocol::LSPAny LSPAny(const T& obj);
// // struct 类型 /// 任意类型转换为 LSPAny
// template<typename T> ///
// typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type LSPAny(const T& value); /// 支持的类型:
/// - 基本类型bool, int, double, string, nullptr
/// - 容器类型vector, map, optional
/// - LSP 类型LSPObject, LSPArray, LSPAny
/// - 用户结构体(需要 glaze 支持)
inline constexpr auto ToLSPAny = [](const auto& value) {
return LSPAnyConverter::ToLSPAny(value);
};
// 容器类型 /// LSPAny 转换为指定类型
template<typename T> ///
protocol::LSPAny LSPAny(const std::vector<T>& vec); /// 支持的类型:
/// - 基本类型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 namespace check
{ {
inline bool IsObject(const protocol::LSPAny& any) { return any.is<protocol::LSPObject>(); } /// 检查是否为 LSPObject
inline bool IsArray(const protocol::LSPAny& any) { return any.is<protocol::LSPArray>(); } bool IsObject(const protocol::LSPAny& any);
inline bool IsString(const protocol::LSPAny& any) { return any.is<protocol::string>(); }
inline bool IsNumber(const protocol::LSPAny& any) { return any.is<protocol::decimal>(); } /// 检查是否为 LSPArray
inline bool IsBool(const protocol::LSPAny& any) { return any.is<protocol::boolean>(); } bool IsArray(const protocol::LSPAny& any);
inline bool IsNull(const protocol::LSPAny& any) { return any.is<std::nullptr_t>(); }
/// 检查是否为字符串
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 namespace debug
{ {
inline std::string GetTypeName(const protocol::LSPAny& any) /// 获取 LSPAny 的类型名称字符串
{ 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";
}
inline std::string GetIdString(const std::variant<int, std::string>& id) /// 将 variant<int, string> 转换为字符串(用于 ID
{ 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);
}
} }
} }

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "./facade.hpp" // #include "./facade.hpp"
namespace lsp::transform namespace lsp::transform
{ {
// ==================== JSON 序列化/反序列化 ====================
template<typename T> template<typename T>
inline std::optional<T> Deserialize(const std::string& json) inline std::optional<T> Deserialize(const std::string& json)
{ {
@ -25,118 +27,77 @@ namespace lsp::transform
return json; return json;
} }
template<typename T> // ==================== 类型检查 ====================
inline protocol::LSPAny LSPAny(const T& obj)
{
return LSPAnyConverter::ToLSPAny(obj);
}
template<typename T> namespace check
inline protocol::LSPAny LSPAny(const std::vector<T>& vec)
{ {
return LSPAnyConverter::ToLSPAny(vec); inline bool IsObject(const protocol::LSPAny& any)
}
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>)
{ {
return LSPAnyConverter::ToLSPObject(obj); return any.Is<protocol::LSPObject>();
} }
else
inline bool IsArray(const protocol::LSPAny& any)
{ {
// 否则先转换为 LSPAny再获取 LSPObject return any.Is<protocol::LSPArray>();
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(obj); }
return LSPAnyConverter::ToLSPObject(any);
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 inline std::string GetTypeName(const protocol::LSPAny& any)
if constexpr (std::is_same_v<T, protocol::LSPAny>)
{ {
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 return std::visit([](const auto& value) -> std::string {
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(container); if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
return LSPAnyConverter::ToLSPArray(any); 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 namespace lsp::transform
{ {
// LSPAny 序列化/反序列化工具类 /// LSPAny 转换核心类
/// 提供所有类型的双向转换
class LSPAnyConverter class LSPAnyConverter
{ {
public: public:
// === 基本类型的转换 === // ==================== 任意类型 → LSPAny ====================
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);
// === 容器类型的转换 ===
template<typename T> template<typename T>
static protocol::LSPAny ToLSPAny(const std::vector<T>& vec); static protocol::LSPAny ToLSPAny(const T& value);
// ==================== LSPAny → 任意类型 ====================
/// 通用转换入口LSPAny → 任意类型
/// 根据类型特征自动分派到具体实现
template<typename T> template<typename T>
static protocol::LSPAny ToLSPAny(const std::map<protocol::string, T>& map); static T FromLSPAny(const protocol::LSPAny& any);
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);
private: 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" #include "./transformer.inl"

View File

@ -1,249 +1,210 @@
#pragma once #pragma once
#include "./transformer.hpp"
namespace lsp::transform namespace lsp::transform
{ {
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(protocol::boolean value) // ==================== ToLSPAny 实现 ====================
{
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));
}
template<typename T> 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; using Type = std::decay_t<T>;
for (const auto& [key, value] : map)
obj[key] = ToLSPAny(value);
return protocol::LSPAny(std::move(obj));
}
template<typename T> // LSPAny 直接返回
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::optional<T>& opt) if constexpr (std::is_same_v<Type, protocol::LSPAny>)
{
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
{ {
// 使用glaze序列化为JSON字符串 return value;
std::string json; }
auto ec = glz::write_json(obj, json); // LSPObject 直接返回
if (ec) else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
{ {
throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json))); 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 // ==================== FromLSPAny 实现 ====================
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)));
}
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; 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> 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>()) if (any.Is<protocol::integer>())
throw ConversionError("LSPAny does not contain a number"); {
return static_cast<T>(any.get<protocol::decimal>()); 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> template<typename T>
inline std::vector<T> LSPAnyConverter::ToVector(const protocol::LSPAny& any) inline T LSPAnyConverter::ConvertViaJson(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)
{ {
try try
{ {
// 序列化LSPAny为JSON // 序列化 LSPAny 为 JSON
std::string json; std::string json;
auto ec = glz::write_json(any.value, json); auto ec = glz::write_json(any.value, json);
if (ec) if (ec)
throw ConversionError("Failed to serialize LSPAny to JSON: " + std::string(glz::format_error(ec, json))); throw ConversionError("Failed to serialize LSPAny to JSON: " + std::string(glz::format_error(ec, json)));
// 解析JSON到目标类型 // 解析 JSON 到目标类型
T result; T result;
ec = glz::read_json(result, json); ec = glz::read_json(result, json);
if (ec) 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()));
}
}
} }