diff --git a/lsp-server/src/protocol/detail/basic_types.hpp b/lsp-server/src/protocol/detail/basic_types.hpp index 3024328..7f1bbfd 100644 --- a/lsp-server/src/protocol/detail/basic_types.hpp +++ b/lsp-server/src/protocol/detail/basic_types.hpp @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include #include +#include #include #include @@ -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; using LSPArray = std::vector; @@ -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& val); - LSPAny(std::map&& val); - LSPAny(const std::vector& val); - LSPAny(std::vector&& 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 && !std::is_same_v && !std::is_same_v, char>>> + LSPAny(T val); + // 赋值操作符 LSPAny& operator=(const LSPAny& other); LSPAny& operator=(LSPAny&& other) noexcept; - LSPAny& operator=(const std::map& val); - LSPAny& operator=(std::map&& val); - LSPAny& operator=(const std::vector& val); - LSPAny& operator=(std::vector&& 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 && !std::is_same_v && !std::is_same_v, char>>> + LSPAny& operator=(T val); + // 类型检查辅助函数 template - bool is() const; + bool Is() const; template - T& get(); + T& Get(); template - const T& get() const; + const T& Get() const; // 访问操作符 template - auto visit(Visitor&& visitor) const; + auto Visit(Visitor&& visitor) const; template - auto visit(Visitor&& visitor); + auto Visit(Visitor&& visitor); }; using ProgressToken = std::variant; @@ -227,33 +237,75 @@ namespace lsp::protocol }; // LSP模板方法 + template + LSPAny::LSPAny(T val) + { + if constexpr (std::is_signed_v) + { + // 有符号整数 + if (val >= std::numeric_limits::min() && val <= std::numeric_limits::max()) + value = static_cast(val); + else + value = static_cast(val); // 超出 int32 范围,转为 decimal(可能丢失精度) + } + else + { + // 无符号整数 + if (val <= std::numeric_limits::max()) + value = static_cast(val); + else + value = static_cast(val); // 超出 uint32 范围,转为 decimal(可能丢失精度) + } + } + + template + LSPAny& LSPAny::operator=(T val) + { + if constexpr (std::is_signed_v) + { + // 有符号整数 + if (val >= std::numeric_limits::min() && val <= std::numeric_limits::max()) + value = static_cast(val); + else + value = static_cast(val); + } + else + { + if (val <= std::numeric_limits::max()) + value = static_cast(val); + else + value = static_cast(val); + } + return *this; + } + template - bool LSPAny::is() const + bool LSPAny::Is() const { return std::holds_alternative(value); } template - T& LSPAny::get() + T& LSPAny::Get() { return std::get(value); } template - const T& LSPAny::get() const + const T& LSPAny::Get() const { return std::get(value); } // 访问操作符 template - auto LSPAny::visit(Visitor&& visitor) const + auto LSPAny::Visit(Visitor&& visitor) const { return std::visit(std::forward(visitor), value); } template - auto LSPAny::visit(Visitor&& visitor) + auto LSPAny::Visit(Visitor&& visitor) { return std::visit(std::forward(visitor), value); } diff --git a/lsp-server/src/protocol/detail/lsp_any.inl b/lsp-server/src/protocol/detail/lsp_any.inl index 1b010b0..88e4740 100644 --- a/lsp-server/src/protocol/detail/lsp_any.inl +++ b/lsp-server/src/protocol/detail/lsp_any.inl @@ -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& val) : + inline LSPAny::LSPAny(const LSPObject& val) : value(val) {} - inline LSPAny::LSPAny(std::map&& val) : + inline LSPAny::LSPAny(LSPObject&& val) : value(std::move(val)) {} - inline LSPAny::LSPAny(const std::vector& val) : + inline LSPAny::LSPAny(const LSPArray& val) : value(val) {} - inline LSPAny::LSPAny(std::vector&& 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(val)) {} - - inline LSPAny::LSPAny(long val) : - value(static_cast(val)) {} - - inline LSPAny::LSPAny(long long val) : - value(static_cast(val)) {} - - inline LSPAny::LSPAny(unsigned int val) : - value(static_cast(val)) {} - - inline LSPAny::LSPAny(unsigned long val) : - value(static_cast(val)) {} - - inline LSPAny::LSPAny(unsigned long long val) : - value(static_cast(val)) {} - inline LSPAny::LSPAny(float val) : value(static_cast(val)) {} @@ -80,26 +62,25 @@ namespace lsp::protocol return *this; } - // 针对每种支持的类型的赋值操作符 - inline LSPAny& LSPAny::operator=(const std::map& val) + inline LSPAny& LSPAny::operator=(const LSPObject& val) { value = val; return *this; } - inline LSPAny& LSPAny::operator=(std::map&& val) + inline LSPAny& LSPAny::operator=(LSPObject&& val) { value = std::move(val); return *this; } - inline LSPAny& LSPAny::operator=(const std::vector& val) + inline LSPAny& LSPAny::operator=(const LSPArray& val) { value = val; return *this; } - inline LSPAny& LSPAny::operator=(std::vector&& 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(val); - return *this; - } - - inline LSPAny& LSPAny::operator=(long val) - { - value = static_cast(val); - return *this; - } - - inline LSPAny& LSPAny::operator=(long long val) - { - value = static_cast(val); - return *this; - } - - inline LSPAny& LSPAny::operator=(unsigned int val) - { - value = static_cast(val); - return *this; - } - - inline LSPAny& LSPAny::operator=(unsigned long val) - { - value = static_cast(val); - return *this; - } - - inline LSPAny& LSPAny::operator=(unsigned long long val) - { - value = static_cast(val); - return *this; - } - inline LSPAny& LSPAny::operator=(float val) { value = static_cast(val); diff --git a/lsp-server/src/protocol/transform/common.hpp b/lsp-server/src/protocol/transform/common.hpp index b7f37af..b190824 100644 --- a/lsp-server/src/protocol/transform/common.hpp +++ b/lsp-server/src/protocol/transform/common.hpp @@ -1,40 +1,105 @@ #pragma once #include #include +#include +#include +#include +#include #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 + inline constexpr bool is_lsp_basic_type_v = + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v; + + /// 类型特征:LSP 容器类型判断 + template + inline constexpr bool is_lsp_container_type_v = + std::is_same_v || + std::is_same_v || + std::is_same_v; + + /// 类型特征:检测 vector + template + struct is_vector : std::false_type + { }; template - struct is_lsp_basic_type: std::false_type {}; - - template<> struct is_lsp_basic_type : std::true_type {}; - template<> struct is_lsp_basic_type : std::true_type {}; - template<> struct is_lsp_basic_type : std::true_type {}; - template<> struct is_lsp_basic_type : std::true_type {}; + struct is_vector> : std::true_type + { + }; template - struct is_lsp_container_type : std::false_type {}; + inline constexpr bool is_vector_v = is_vector::value; - template<> struct is_lsp_container_type : std::true_type {}; - template<> struct is_lsp_container_type : std::true_type {}; - template<> struct is_lsp_container_type : std::true_type {}; - - // struct类型判断 + /// 类型特征:检测 map template - struct is_user_struct : std::integral_constant::value && - !std::is_same::value && - !std::is_same::value && - !std::is_same::value && - !is_lsp_basic_type::value && - !is_lsp_container_type::value> {}; + struct is_map : std::false_type + { + }; + + template + struct is_map> : std::true_type + { + }; + + template + inline constexpr bool is_map_v = is_map::value; + + /// 类型特征:检测 optional + template + struct is_optional : std::false_type + { + }; + + template + struct is_optional> : std::true_type + { + }; + + template + inline constexpr bool is_optional_v = is_optional::value; + + /// 类型特征:检测 variant + template + struct is_variant : std::false_type + { + }; + + template + struct is_variant> : std::true_type + { + }; + + template + inline constexpr bool is_variant_v = is_variant::value; + + /// 类型特征:用户自定义 struct 判断 + template + inline constexpr bool is_user_struct_v = + std::is_class_v && + !std::is_pointer_v && + !std::is_same_v && + !std::is_same_v && + !is_lsp_basic_type_v && + !is_lsp_container_type_v && + !is_vector_v && + !is_map_v && + !is_optional_v && + !is_variant_v; } diff --git a/lsp-server/src/protocol/transform/facade.hpp b/lsp-server/src/protocol/transform/facade.hpp index ceda7f7..e31a094 100644 --- a/lsp-server/src/protocol/transform/facade.hpp +++ b/lsp-server/src/protocol/transform/facade.hpp @@ -3,106 +3,68 @@ namespace lsp::transform { + // ==================== JSON 序列化/反序列化 ==================== - // ===== 全局便利函数 ===== template std::optional Deserialize(const std::string& json); template std::optional Serialize(const T& obj); - // 基本类型 - template - protocol::LSPAny LSPAny(const T& obj); + // ==================== 转换为 LSPAny ==================== - // // struct 类型 - // template - // typename std::enable_if::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 - protocol::LSPAny LSPAny(const std::vector& vec); + /// LSPAny 转换为指定类型 + /// + /// 支持的类型: + /// - 基本类型:bool, int, double, string + /// - 容器类型:vector, optional + /// - LSP 类型:LSPObject, LSPArray + /// - 用户结构体(需要 glaze 支持) + inline constexpr auto FromLSPAny = [](const protocol::LSPAny& any) -> T { + return LSPAnyConverter::FromLSPAny(any); + }; - template - protocol::LSPAny LSPAny(const std::map& map); - - template - protocol::LSPAny LSPAny(const std::optional& opt); - - template - T As(const protocol::LSPAny& any); - - template - std::optional As(const std::optional& opt); - - template - T As(const std::variant& var); - - template - T As(const protocol::LSPObject& obj); - - template - T As(const protocol::LSPArray& arr); - - template - T Number(const protocol::LSPAny& any); - - template - std::vector Vector(const protocol::LSPAny& any); - - template - std::optional Optional(const protocol::LSPAny& any); - - template - protocol::LSPObject LSPObject(const T& obj); - - template - 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(); } - inline bool IsArray(const protocol::LSPAny& any) { return any.is(); } - inline bool IsString(const protocol::LSPAny& any) { return any.is(); } - inline bool IsNumber(const protocol::LSPAny& any) { return any.is(); } - inline bool IsBool(const protocol::LSPAny& any) { return any.is(); } - inline bool IsNull(const protocol::LSPAny& any) { return any.is(); } + /// 检查是否为 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()) - return "LSPObject"; - if (any.is()) - return "LSPArray"; - if (any.is()) - return "string"; - if (any.is()) - return "decimal"; - if (any.is()) - return "boolean"; - if (any.is()) - return "null"; - return "unknown"; - } + /// 获取 LSPAny 的类型名称字符串 + std::string GetTypeName(const protocol::LSPAny& any); - inline std::string GetIdString(const std::variant& id) - { - return std::visit([](const auto& value) -> std::string { - if constexpr (std::is_same_v, int>) - return std::to_string(value); - else - return value; - }, id); - } + /// 将 variant 转换为字符串(用于 ID) + std::string GetIdString(const std::variant& id); } } diff --git a/lsp-server/src/protocol/transform/facade.inl b/lsp-server/src/protocol/transform/facade.inl index 32a931d..ae48070 100644 --- a/lsp-server/src/protocol/transform/facade.inl +++ b/lsp-server/src/protocol/transform/facade.inl @@ -1,8 +1,10 @@ #pragma once -#include "./facade.hpp" +// #include "./facade.hpp" namespace lsp::transform { + // ==================== JSON 序列化/反序列化 ==================== + template inline std::optional Deserialize(const std::string& json) { @@ -25,118 +27,77 @@ namespace lsp::transform return json; } - template - inline protocol::LSPAny LSPAny(const T& obj) - { - return LSPAnyConverter::ToLSPAny(obj); - } + // ==================== 类型检查 ==================== - template - inline protocol::LSPAny LSPAny(const std::vector& vec) + namespace check { - return LSPAnyConverter::ToLSPAny(vec); - } - - template - inline protocol::LSPAny LSPAny(const std::map& map) - { - return LSPAnyConverter::ToLSPAny(map); - } - - template - inline protocol::LSPAny LSPAny(const std::optional& opt) - { - return LSPAnyConverter::ToLSPAny(opt); - } - - template - inline T As(const protocol::LSPAny& any) - { - return LSPAnyConverter::FromLSPAny(any); - } - - template - inline std::optional As(const std::optional& opt) - { - return LSPAnyConverter::As(opt); - } - - template - inline T As(const std::variant& var) - { - return LSPAnyConverter::As(var); - } - - template - inline T As(const protocol::LSPObject& obj) - { - return LSPAnyConverter::As(obj); - } - - template - inline T As(const protocol::LSPArray& arr) - { - return LSPAnyConverter::As(arr); - } - - template - inline T Number(const protocol::LSPAny& any) - { - return LSPAnyConverter::ToNumber(any); - } - - template - inline std::vector Vector(const protocol::LSPAny& any) - { - return LSPAnyConverter::ToVector(any); - } - - template - inline std::optional Optional(const protocol::LSPAny& any) - { - return LSPAnyConverter::ToOptional(any); - } - - template - inline protocol::LSPObject LSPObject(const T& obj) - { - // 如果已经是 LSPAny,直接获取其中的 LSPObject - if constexpr (std::is_same_v) + inline bool IsObject(const protocol::LSPAny& any) { - return LSPAnyConverter::ToLSPObject(obj); + return any.Is(); } - else + + inline bool IsArray(const protocol::LSPAny& any) { - // 否则先转换为 LSPAny,再获取 LSPObject - protocol::LSPAny any = LSPAnyConverter::ToLSPAny(obj); - return LSPAnyConverter::ToLSPObject(any); + return any.Is(); + } + + inline bool IsString(const protocol::LSPAny& any) + { + return any.Is(); + } + + inline bool IsNumber(const protocol::LSPAny& any) + { + return any.Is() || + any.Is() || + any.Is(); + } + + inline bool IsBool(const protocol::LSPAny& any) + { + return any.Is(); + } + + inline bool IsNull(const protocol::LSPAny& any) + { + return any.Is(); } } - template - inline protocol::LSPArray LSPArray(const T& container) + // ==================== 调试工具 ==================== + + namespace debug { - // 如果已经是 LSPAny,直接获取其中的 LSPArray - if constexpr (std::is_same_v) + inline std::string GetTypeName(const protocol::LSPAny& any) { - return LSPAnyConverter::ToLSPArray(container); + if (any.Is()) + return "LSPObject"; + if (any.Is()) + return "LSPArray"; + if (any.Is()) + return "string"; + if (any.Is()) + return "integer"; + if (any.Is()) + return "uinteger"; + if (any.Is()) + return "decimal"; + if (any.Is()) + return "boolean"; + if (any.Is()) + return "null"; + return "unknown"; } - else + + inline std::string GetIdString(const std::variant& 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, 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); - } - } diff --git a/lsp-server/src/protocol/transform/transformer.hpp b/lsp-server/src/protocol/transform/transformer.hpp index 02e822f..02f978d 100644 --- a/lsp-server/src/protocol/transform/transformer.hpp +++ b/lsp-server/src/protocol/transform/transformer.hpp @@ -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 到基本类型的转换 === - 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 ==================== + + /// 通用转换入口:任意类型 → LSPAny + /// 根据类型特征自动分派到具体实现 template - static protocol::LSPAny ToLSPAny(const std::vector& vec); + static protocol::LSPAny ToLSPAny(const T& value); + // ==================== LSPAny → 任意类型 ==================== + + /// 通用转换入口:LSPAny → 任意类型 + /// 根据类型特征自动分派到具体实现 template - static protocol::LSPAny ToLSPAny(const std::map& map); - - template - static protocol::LSPAny ToLSPAny(const std::optional& opt); - - // === Struct 到 LSPAny 的转换 === - template - static typename std::enable_if::value, protocol::LSPAny>::type ToLSPAny(const T& obj); - - template - static typename std::enable_if::value && !std::is_same::value, T>::type ToNumber(const protocol::LSPAny& any); - - // === LSPAny 到容器类型的转换 === - template - static std::vector ToVector(const protocol::LSPAny& any); - - template - static std::optional ToOptional(const protocol::LSPAny& any); - - template - static typename std::enable_if::value, T>::type FromLSPAny(const protocol::LSPAny& any); - - // 处理 std::optional - template - static std::optional As(const std::optional& opt); - - // 处理 std::variant - template - static T As(const std::variant& var); - - // 处理 LSPObject 和 LSPArray - template - static T As(const protocol::LSPObject& obj); - - template - static T As(const protocol::LSPArray& arr); - + static T FromLSPAny(const protocol::LSPAny& any); private: + // ==================== 辅助工具 ==================== + + /// 提取数字(支持三种数字类型) template - static T FromLSPAnyImpl(const protocol::LSPAny& any); - }; + static T ExtractNumber(const protocol::LSPAny& any); + /// 通过 JSON 转换用户结构体 + template + static T ConvertViaJson(const protocol::LSPAny& any); + + /// 将用户结构体序列化为 LSPAny + template + static protocol::LSPAny SerializeViaJson(const T& obj); + }; } #include "./transformer.inl" diff --git a/lsp-server/src/protocol/transform/transformer.inl b/lsp-server/src/protocol/transform/transformer.inl index 5c038cb..8ad7df9 100644 --- a/lsp-server/src/protocol/transform/transformer.inl +++ b/lsp-server/src/protocol/transform/transformer.inl @@ -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()) - throw ConversionError("LSPAny does not contain a boolean"); - return any.get(); - } - - inline protocol::string LSPAnyConverter::ToString(const protocol::LSPAny& any) - { - if (!any.is()) - throw ConversionError("LSPAny does not contain a string"); - return any.get(); - } - - inline protocol::LSPObject LSPAnyConverter::ToLSPObject(const protocol::LSPAny& any) - { - if (!any.is()) - throw ConversionError("LSPAny does not contain LSPObject"); - return any.get(); - } - - inline protocol::LSPArray LSPAnyConverter::ToLSPArray(const protocol::LSPAny& any) - { - if (!any.is()) - throw ConversionError("LSPAny does not contain LSPArray"); - return any.get(); - } - - // 模板实现 - template - inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::vector& 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 - inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::map& 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; - template - inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::optional& opt) - { - if (opt.has_value()) - return ToLSPAny(*opt); - return protocol::LSPAny(nullptr); - } - - template - inline typename std::enable_if::value, protocol::LSPAny>::type - LSPAnyConverter::ToLSPAny(const T& obj) - { - try + // LSPAny 直接返回 + if constexpr (std::is_same_v) { - // 使用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) + { + return protocol::LSPAny(value); + } + // LSPArray 直接返回 + else if constexpr (std::is_same_v) + { + return protocol::LSPAny(value); + } + else if constexpr (std::is_same_v || + std::is_same_v) + { + return protocol::LSPAny(protocol::string(value)); + } + // LSP 基本类型(boolean, string, decimal, nullptr) + else if constexpr (is_lsp_basic_type_v) + { + return protocol::LSPAny(value); + } + // 整数类型(依赖 LSPAny 模板构造函数) + else if constexpr (std::is_integral_v && + !std::is_same_v) + { + return protocol::LSPAny(value); + } + // 浮点类型 + else if constexpr (std::is_floating_point_v) + { + return protocol::LSPAny(value); + } + // vector → LSPArray + else if constexpr (is_vector_v) + { + 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) + { + 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) + { + if (value.has_value()) + return ToLSPAny(*value); + return protocol::LSPAny(nullptr); + } + // 用户结构体 → LSPAny (通过 JSON) + else if constexpr (is_user_struct_v) + { + 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 + inline T LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any) + { + using Type = std::decay_t; + + // LSPAny 直接返回 + if constexpr (std::is_same_v) + { + return any; + } + // LSPObject 提取 + else if constexpr (std::is_same_v) + { + if (!any.Is()) + throw ConversionError("LSPAny does not contain LSPObject"); + return any.Get(); + } + // LSPArray 提取 + else if constexpr (std::is_same_v) + { + if (!any.Is()) + throw ConversionError("LSPAny does not contain LSPArray"); + return any.Get(); + } + // boolean 提取 + else if constexpr (std::is_same_v) + { + if (!any.Is()) + throw ConversionError("LSPAny does not contain a boolean"); + return any.Get(); + } + // string 提取 + else if constexpr (std::is_same_v || + std::is_same_v) + { + if (!any.Is()) + throw ConversionError("LSPAny does not contain a string"); + return any.Get(); + } + // 数字类型提取 + else if constexpr (std::is_arithmetic_v && + !std::is_same_v) + { + return ExtractNumber(any); + } + // vector 提取 + else if constexpr (is_vector_v) + { + if (!any.Is()) + throw ConversionError("LSPAny does not contain an array"); + + const auto& arr = any.Get(); + Type result; + result.reserve(arr.size()); + for (const auto& item : arr) + result.push_back(FromLSPAny(item)); return result; } - catch (const std::exception& e) + // map 提取 + else if constexpr (is_map_v) { - throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what())); + if (!any.Is()) + throw ConversionError("LSPAny does not contain an object"); + + const auto& obj = any.Get(); + Type result; + for (const auto& [key, val] : obj) + result[key] = FromLSPAny(val); + return result; + } + // optional 提取 + else if constexpr (is_optional_v) + { + if (any.Is()) + return std::nullopt; + return FromLSPAny(any); + } + // 用户结构体提取(通过 JSON) + else if constexpr (is_user_struct_v) + { + return ConvertViaJson(any); + } + else + { + static_assert(!sizeof(Type), "Unsupported type for FromLSPAny"); } } - // Fromprotocol::LSPAny 实现 + // ==================== 辅助工具实现 ==================== + template - inline typename std::enable_if::value && !std::is_same::value, T>::type LSPAnyConverter::ToNumber(const protocol::LSPAny& any) + inline T LSPAnyConverter::ExtractNumber(const protocol::LSPAny& any) { - if (!any.is()) - throw ConversionError("LSPAny does not contain a number"); - return static_cast(any.get()); + if (any.Is()) + { + return static_cast(any.Get()); + } + else if (any.Is()) + { + return static_cast(any.Get()); + } + else if (any.Is()) + { + return static_cast(any.Get()); + } + else + { + throw ConversionError("LSPAny does not contain a number (integer/uinteger/decimal)"); + } } template - inline std::vector LSPAnyConverter::ToVector(const protocol::LSPAny& any) - { - if (!any.is()) - throw ConversionError("LSPAny does not contain an array"); - - const auto& arr = any.get(); - std::vector result; - result.reserve(arr.size()); - for (const auto& item : arr) - result.push_back(FromLSPAny(item)); - return result; - } - - template - inline std::optional LSPAnyConverter::ToOptional(const protocol::LSPAny& any) - { - if (any.is()) - return std::nullopt; - return FromLSPAny(any); - } - - template - inline typename std::enable_if::value, T>::type - LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any) - { - return FromLSPAnyImpl(any); - } - - // 处理 std::optional - template - inline std::optional LSPAnyConverter::As(const std::optional& opt) - { - if (opt.has_value()) - return As(*opt); - return std::nullopt; - } - - // 处理 std::variant - template - inline T LSPAnyConverter::As(const std::variant& var) - { - return std::visit([](const auto& val) -> T { - return As(val); - }, var); - } - - // 处理 LSPObject - template - inline T LSPAnyConverter::As(const protocol::LSPObject& obj) - { - protocol::LSPAny any(obj); - return FromLSPAny(any); - } - - // 处理 LSPArray - template - inline T LSPAnyConverter::As(const protocol::LSPArray& arr) - { - protocol::LSPAny any(arr); - return FromLSPAny(any); - } - - // FromLSPAnyImpl 实现 - template - 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 + 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())); + } + } }