feat: support concurrency

This commit is contained in:
csh
2025-07-03 18:52:04 +08:00
parent 07feb1c52c
commit 3cc1fccc81
57 changed files with 6743 additions and 6377 deletions
+9 -5
View File
@@ -59,24 +59,27 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib" ".so")
find_package(glaze CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(Taskflow REQUIRED)
if(NOT TARGET spdlog::spdlog_header_only)
message(WARNING "spdlog header-only target not found, using shared library")
message(WARNING "spdlog header-only target not found, using shared library")
endif()
if(NOT TARGET fmt::fmt-header-only)
message(WARNING "fmt header-only target not found, using shared library")
message(WARNING "fmt header-only target not found, using shared library")
endif()
if(UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
find_package(Threads REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SOURCES
src/main.cpp
src/utils/args_parser.cpp
src/language/tsl_keywords.cpp
src/lsp/dispacther.cpp
src/lsp/server.cpp
src/lsp/request_scheduler.cpp
src/provider/base/provider_registry.cpp
src/provider/base/provider_interface.cpp
src/provider/initialize/initialize_provider.cpp
@@ -84,6 +87,7 @@ set(SOURCES
src/provider/text_document/did_open_provider.cpp
src/provider/text_document/did_change_provider.cpp
src/provider/text_document/completion_provider.cpp
src/provider/shutdown/shutdown_provider.cpp
src/provider/trace/set_trace_provider.cpp)
add_executable(${PROJECT_NAME} ${SOURCES})
@@ -93,8 +97,8 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
FMT_HEADER_ONLY)
target_link_libraries(
${PROJECT_NAME} PRIVATE glaze::glaze spdlog::spdlog_header_only
fmt::fmt-header-only)
${PROJECT_NAME} PRIVATE glaze::glaze Taskflow::Taskflow
spdlog::spdlog_header_only fmt::fmt-header-only)
# Linux 需要链接 pthread
if(UNIX AND NOT APPLE)
+69 -31
View File
@@ -5,29 +5,51 @@
namespace lsp
{
void RequestDispatcher::RegisterProvider(const std::string& method, RequestProvider handler)
void RequestDispatcher::RegisterProvider(std::shared_ptr<providers::ILspProvider> provider)
{
std::unique_lock<std::shared_mutex> lock(providers_mutex_);
providers_[method] = std::move(handler);
std::string method = provider->GetMethod();
// 如果是生命周期感知的 Provider,设置回调
if (auto lifecycle_aware = std::dynamic_pointer_cast<providers::ILifecycleAwareProvider>(provider))
{
lifecycle_aware->SetLifecycleCallback(
[this](ServerLifecycleEvent event) {
NotifyAllLifecycleListeners(event);
});
spdlog::debug("Registered lifecycle-aware provider for method: {}", method);
}
else
{
spdlog::debug("Registered standard provider for method: {}", method);
}
providers_[method] = provider;
spdlog::debug("Registered provider for method: {}", method);
}
void RequestDispatcher::RegisterLifecycleCallback(LifecycleCallback callback)
{
std::lock_guard<std::mutex> lock(callbacks_mutex_);
lifecycle_callbacks_.push_back(std::move(callback));
spdlog::debug("Registered lifecycle callback, total callbacks: {}", lifecycle_callbacks_.size());
}
std::string RequestDispatcher::Dispatch(const protocol::RequestMessage& request)
{
std::shared_lock<std::shared_mutex> lock(providers_mutex_);
auto it = providers_.find(request.method);
if (it != providers_.end())
{
RequestProvider provider = it->second;
auto provider = it->second;
lock.unlock();
try
{
return provider(request);
return provider->ProvideResponse(request);
}
catch (const std::exception& e)
{
spdlog::error("Provider error for method {}: {}", request.method, e.what());
return HandleException(request, e.what());
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, e.what());
}
}
return HandleUnknownMethod(request);
@@ -51,36 +73,52 @@ namespace lsp
return methods;
}
std::string RequestDispatcher::HandleUnknownMethod(const protocol::RequestMessage& request)
void RequestDispatcher::NotifyAllLifecycleListeners(ServerLifecycleEvent event)
{
return BuildErrorResponse(request, protocol::ErrorCode::kMethodNotFound, "Method not found: " + request.method);
}
std::lock_guard<std::mutex> lock(callbacks_mutex_);
std::string RequestDispatcher::HandleException(const protocol::RequestMessage& request, const std::string& error_message)
{
return BuildErrorResponse(request, protocol::ErrorCode::kInternalError, "Internal error: " + error_message);
}
std::string RequestDispatcher::BuildErrorResponse(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
{
protocol::ResponseMessage response;
response.jsonrpc = "2.0";
response.id = request.id;
protocol::ResponseError error;
error.code = code;
error.message = message;
response.error = error;
std::string json;
auto ec = glz::write_json(response, json);
if (ec)
std::string event_name;
switch (event)
{
spdlog::error("Failed to serialize error response: {}", glz::format_error(ec, json));
// 返回一个硬编码的错误响应作为后备
return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})";
case ServerLifecycleEvent::kInitializing:
event_name = "Initializing";
break;
case ServerLifecycleEvent::kInitialized:
event_name = "Initialized";
break;
case ServerLifecycleEvent::kInitializeFailed:
event_name = "InitializeFailed";
break;
case ServerLifecycleEvent::kShuttingDown:
event_name = "ShuttingDown";
break;
case ServerLifecycleEvent::kShutdown:
event_name = "Shutdown";
break;
}
return json;
spdlog::info("Lifecycle event: {}", event_name);
for (const auto& callback : lifecycle_callbacks_)
{
try
{
callback(event);
}
catch (const std::exception& e)
{
spdlog::error("Lifecycle callback error: {}", e.what());
}
}
}
std::string RequestDispatcher::HandleUnknownMethod(const protocol::RequestMessage& request)
{
return BuildErrorResponseMessage(request, protocol::ErrorCode::kMethodNotFound, "Method not found: " + request.method);
}
std::string RequestDispatcher::BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
{
return providers::ILspProvider::BuildErrorResponseMessage(request, code, message);
}
}
+14 -8
View File
@@ -1,32 +1,38 @@
#pragma once
#include <functional>
#include <unordered_map>
#include <memory>
#include <vector>
#include <shared_mutex>
#include "../protocol/protocol.hpp"
#include "../provider/base/provider_interface.hpp"
namespace lsp
{
// 请求处理函数类型 - 返回序列化后的 JSON 字符串
using RequestProvider = std::function<std::string(const protocol::RequestMessage&)>;
using ServerLifecycleEvent = providers::ServerLifecycleEvent;
using LifecycleCallback = providers::LifecycleCallback;
class RequestDispatcher
{
public:
RequestDispatcher() = default;
void RegisterProvider(const std::string& method, RequestProvider provider);
void RegisterProvider(std::shared_ptr<providers::ILspProvider> provider);
void RegisterLifecycleCallback(LifecycleCallback callback);
std::string Dispatch(const protocol::RequestMessage& request);
bool SupportsMethod(const std::string& method) const;
std::vector<std::string> GetSupportedMethods() const;
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
private:
void NotifyAllLifecycleListeners(ServerLifecycleEvent event);
std::string HandleUnknownMethod(const protocol::RequestMessage& request);
std::string HandleException(const protocol::RequestMessage& request, const std::string& error_message);
std::string BuildErrorResponse(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
private:
mutable std::shared_mutex providers_mutex_;
std::unordered_map<std::string, RequestProvider> providers_;
std::unordered_map<std::string, std::shared_ptr<providers::ILspProvider>> providers_;
std::mutex callbacks_mutex_;
std::vector<LifecycleCallback> lifecycle_callbacks_;
};
}
+66 -21
View File
@@ -1,56 +1,101 @@
#include <mutex>
#include <spdlog/spdlog.h>
#include "./request_scheduler.hpp"
namespace lsp
{
RequestScheduler::RequestScheduler(size_t concurrency) :
executor_(concurrency)
{
spdlog::info("RequestScheduler initialized with {} threads", concurrency);
}
RequestScheduler::~RequestScheduler() = default;
void RequestScheduler::Sumbit(const std::string& request_id, TaskFunc task)
RequestScheduler::~RequestScheduler()
{
std::lock_guard<std::mutex> lock(task_mutex_);
auto future = executor_.silent_async([this, request_id, task = std::move(task)] {
WaitAll();
}
void RequestScheduler::Submit(const std::string& request_id, TaskFunc task)
{
auto context = std::make_shared<TaskContext>();
{
std::lock_guard<std::mutex> lock(mutex_);
// 取消旧任务
auto it = running_tasks_.find(request_id);
if (it != running_tasks_.end())
{
it->second->cancelled.store(true);
}
running_tasks_[request_id] = context;
}
executor_.async([this, request_id, task = std::move(task), context]() {
try
{
if (context->cancelled.load())
{
spdlog::debug("Task {} was cancelled", request_id);
return;
}
auto result = task();
if (result)
if (!context->cancelled.load() && result)
{
SendResponse(*result);
}
}
catch (const std::exception& e)
{
spdlog::error("Task {} failed: {}", request_id, e.what());
}
std::lock_guard<std::mutex> lock(cancel_mutex_);
running_tasks_.erase(request_id);
// 清理
{
std::lock_guard<std::mutex> lock(mutex_);
running_tasks_.erase(request_id);
}
});
running_tasks_[request_id] = std::move(future);
}
void RequestScheduler::Cancel(const std::string& request_id)
bool RequestScheduler::Cancel(const std::string& request_id)
{
std::lock_guard<std::mutex> lock(cancel_mutex_);
// Taskflow doesn't support preemptive cancel yet; you can set a flag here for cooperative cancel
spdlog::warn("Cancel not implemented for request_id = {} (requires cooperative cancel)", request_id);
std::lock_guard<std::mutex> lock(mutex_);
auto it = running_tasks_.find(request_id);
if (it != running_tasks_.end())
{
it->second->cancelled.store(true);
return true;
}
return false;
}
void RequestScheduler::SetOutputFallback(std::function<void(const std::string&)> callback)
void RequestScheduler::SetResponseCallback(ResponseCallback callback)
{
std::lock_guard<std::mutex> lock(output_mutex_);
send_response_ = std::move(callback);
std::lock_guard<std::mutex> lock(mutex_);
response_callback_ = std::move(callback);
}
void RequestScheduler::WaitAll()
{
executor_.wait_for_all();
}
void RequestScheduler::SendResponse(const std::string& response)
{
std::lock_guard<std::mutex> lock(output_mutex_);
if (send_response_)
send_response_(response);
ResponseCallback callback;
{
std::lock_guard<std::mutex> lock(mutex_);
callback = response_callback_;
}
if (callback)
callback(response);
else
spdlog::error("No response callback set! Unable to send: {}", response);
spdlog::error("No response callback set!");
}
}
+19 -12
View File
@@ -1,8 +1,10 @@
// request_scheduler.hpp
#pragma once
#include <mutex>
#include <atomic>
#include <functional>
#include <string>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <taskflow/taskflow.hpp>
@@ -12,23 +14,28 @@ namespace lsp
{
public:
using TaskFunc = std::function<std::optional<std::string>()>;
explicit RequestScheduler(size_t concurrency);
using ResponseCallback = std::function<void(const std::string&)>;
explicit RequestScheduler(size_t concurrency = std::thread::hardware_concurrency());
~RequestScheduler();
void Sumbit(const std::string& request_id, TaskFunc task);
void Cancel(const std::string& request_id);
void SetOutputFallback(std::function<void(const std::string&)> callback);
void Submit(const std::string& request_id, TaskFunc task);
bool Cancel(const std::string& request_id);
void SetResponseCallback(ResponseCallback callback);
void WaitAll();
private:
struct TaskContext
{
std::atomic<bool> cancelled{false};
};
void SendResponse(const std::string& response);
private:
tf::Executor executor_;
std::mutex task_mutex_;
std::mutex cancel_mutex_;
std::mutex output_mutex_;
std::unordered_map<std::string, tf::Future<void>> running_tasks_;
std::function<void(const std::string&)> send_response_;
mutable std::mutex mutex_;
std::unordered_map<std::string, std::shared_ptr<TaskContext>> running_tasks_;
ResponseCallback response_callback_;
};
}
+193 -62
View File
@@ -1,3 +1,4 @@
#include "request_scheduler.hpp"
#include <exception>
#include <iostream>
#include <spdlog/spdlog.h>
@@ -11,13 +12,29 @@
namespace lsp
{
LspServer::LspServer()
LspServer::LspServer(size_t concurrency) :
scheduler_(4)
{
spdlog::info("Initializing LSP server with {} worker threads", concurrency);
dispatcher_.RegisterLifecycleCallback(
[this](providers::ServerLifecycleEvent event) {
OnLifecycleEvent(event);
});
providers::RegisterAllProviders(dispatcher_);
scheduler_.SetResponseCallback([this](const std::string& response) {
SendResponse(response);
});
spdlog::debug("LSP server initialized with {} providers.", dispatcher_.GetSupportedMethods().size());
}
LspServer::~LspServer() = default;
LspServer::~LspServer()
{
is_shutting_down_ = true;
spdlog::info("LSP server shutting down...");
}
void LspServer::Run()
{
@@ -29,7 +46,7 @@ namespace lsp
_setmode(_fileno(stdin), _O_BINARY);
#endif
while (true)
while (!is_shutting_down_)
{
try
{
@@ -40,11 +57,7 @@ namespace lsp
continue;
}
std::string response = HandleMessage(*message);
if (!response.empty())
{
SendResponse(response);
}
HandleMessage(*message);
}
catch (const std::exception& e)
{
@@ -106,9 +119,7 @@ namespace lsp
if (std::cin.gcount() != static_cast<std::streamsize>(content_length))
{
spdlog::error("Read incomplete message body, expected: {}, got: {}",
content_length,
std::cin.gcount());
spdlog::error("Read incomplete message body, expected: {}, got: {}", content_length, std::cin.gcount());
return std::nullopt;
}
@@ -116,122 +127,242 @@ namespace lsp
return body;
}
std::string LspServer::HandleMessage(const std::string& raw_message)
void LspServer::HandleMessage(const std::string& raw_message)
{
try
{
// 首先尝试解析为通用的 JSON 判断消息类型
// 解析 JSON 判断消息类型
glz::json_t doc;
auto error = glz::read_json(doc, raw_message);
if (error)
{
spdlog::error("Failed to parse message as JSON: {}",
glz::format_error(error, raw_message));
return "";
spdlog::error("Failed to parse message as JSON: {}", glz::format_error(error, raw_message));
return;
}
auto& obj = doc.get<glz::json_t::object_t>();
// 判断消息类型
bool has_id = obj.contains("id");
bool has_method = obj.contains("method");
bool has_result = obj.contains("result");
bool has_error = obj.contains("error");
if (has_method && has_id)
if (has_method)
{
// Request
protocol::RequestMessage request;
error = glz::read_json(request, raw_message);
if (error)
bool has_id = obj.contains("id");
if (has_id)
{
spdlog::error("Failed to parse request: {}",
glz::format_error(error, raw_message));
return "";
// RequestMessage
protocol::RequestMessage request;
error = glz::read_json(request, raw_message);
if (error)
{
spdlog::error("Failed to parse request: {}", glz::format_error(error, raw_message));
return;
}
HandleRequest(request);
}
return HandleRequest(request);
}
else if (has_method && !has_id)
{
// Notification
protocol::NotificationMessage notification;
error = glz::read_json(notification, raw_message);
if (error)
else
{
spdlog::error("Failed to parse notification: {}",
glz::format_error(error, raw_message));
return "";
// NotificationMessage
protocol::NotificationMessage notification;
error = glz::read_json(notification, raw_message);
if (error)
{
spdlog::error("Failed to parse notification: {}", glz::format_error(error, raw_message));
return;
}
HandleNotification(notification);
}
return HandleNotification(notification);
}
else if (has_id && (has_result || has_error))
else if (obj.contains("id") && (obj.contains("result") || obj.contains("error")))
{
// Response
// ResponseMessage
protocol::ResponseMessage response;
error = glz::read_json(response, raw_message);
if (error)
{
spdlog::error("Failed to parse response: {}",
glz::format_error(error, raw_message));
return "";
glz::format_error(error, raw_message));
return;
}
HandleResponse(response);
return ""; // 响应不需要回复
}
else
{
spdlog::error("Unknown message type");
return "";
}
}
catch (const std::exception& e)
{
spdlog::error("Failed to handle message: {}", e.what());
return "";
}
}
std::string LspServer::HandleRequest(const protocol::RequestMessage& request)
void LspServer::HandleRequest(const protocol::RequestMessage& request)
{
spdlog::debug("Processing request method: {}", request.method);
std::string request_id = transform::debug::GetIdString(request.id);
spdlog::debug("Processing request - id: {}, method: {}", request_id, request.method);
// 特殊处理 initialize 请求
if (request.method == "initialize")
// 检查是否可以处理请求
if (!CanProcessRequest(request.method))
{
is_initialized_ = true;
protocol::ErrorCode error_code;
std::string message;
if (!is_initialized_)
{
error_code = protocol::ErrorCode::kServerNotInitialized;
message = "Server not initialized";
}
else if (is_shutting_down_)
{
error_code = protocol::ErrorCode::kInvalidRequest;
message = "Server is shutting down, only 'exit' is allowed";
}
else
{
error_code = protocol::ErrorCode::kInternalError;
message = "Request not allowed in current state";
}
SendResponse(dispatcher_.BuildErrorResponseMessage(request, error_code, message));
return;
}
return dispatcher_.Dispatch(request);
// 决定同步还是异步处理
if (RequiresSyncProcessing(request.method))
{
SendResponse(dispatcher_.Dispatch(request));
}
else
{
// 异步处理
scheduler_.Submit(request_id, [this, request]() -> std::optional<std::string> {
if (is_shutting_down_)
{
spdlog::debug("Skipping request {} due to shutdown", request.method);
return std::nullopt;
}
try
{
return dispatcher_.Dispatch(request);
}
catch (const std::exception& e)
{
spdlog::error("Request processing failed: {}", e.what());
return dispatcher_.BuildErrorResponseMessage( request, protocol::ErrorCode::kInternalError, e.what());
}
});
}
spdlog::debug("Processing request method: {}", request.method);
}
std::string LspServer::HandleNotification(const protocol::NotificationMessage& notification)
void LspServer::HandleNotification(const protocol::NotificationMessage& notification)
{
spdlog::debug("Processing notification - method: {}", notification.method);
// 特殊处理某些通知
// 处理 $/ 开头的通知
if (notification.method.starts_with("$/"))
{
if (notification.method == "$/cancelRequest")
{
HandleCancelRequest(notification);
}
else
{
spdlog::debug("Ignoring protocol-specific notification: {}", notification.method);
}
return;
}
// 处理标准通知
if (notification.method == "initialized")
{
spdlog::info("Client initialized");
spdlog::info("Client acknowledged initialization");
}
else if (notification.method == "exit")
{
spdlog::info("Exit notification received");
is_shutting_down_ = true;
// 给一点时间让任务完成
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::exit(0);
}
// 通知不需要响应
return "";
}
void LspServer::HandleResponse(const protocol::ResponseMessage& response)
{
std::string id_str = transform::debug::GetIdString(response.id);
spdlog::debug("Received response - id: {}", id_str);
}
void LspServer::OnLifecycleEvent(ServerLifecycleEvent event)
{
switch (event)
{
case ServerLifecycleEvent::kInitializing:
spdlog::info("Server initializing...");
break;
case ServerLifecycleEvent::kInitialized:
is_initialized_ = true;
spdlog::info("Server initialized successfully");
break;
case ServerLifecycleEvent::kInitializeFailed:
is_initialized_ = false;
spdlog::error("Server initialization failed");
break;
case ServerLifecycleEvent::kShuttingDown:
is_shutting_down_ = true;
spdlog::info("Server entering shutdown state");
break;
case ServerLifecycleEvent::kShutdown:
is_shutting_down_ = true;
spdlog::info("Server shutdown complete");
break;
}
}
bool LspServer::RequiresSyncProcessing(const std::string& method) const
{
static const std::unordered_set<std::string> sync_methods = {
"initialize", // 必须同步完成
"shutdown" // 必须同步完成
};
return sync_methods.count(method) > 0;
}
bool LspServer::CanProcessRequest(const std::string& method) const
{
// 未初始化状态
if (!is_initialized_)
{
return method == "initialize" || method == "exit";
}
// 关闭中状态
if (is_shutting_down_)
{
return method == "exit";
}
// 正常状态 - 接受所有请求
return true;
}
void LspServer::HandleCancelRequest(const protocol::NotificationMessage& notification)
{
spdlog::info("Handle cancel request - method: {}", notification.method);
}
void LspServer::SendResponse(const std::string& response)
{
size_t byte_length = response.length();
std::lock_guard<std::mutex> lock(output_mutex_);
// 构建完整消息
size_t byte_length = response.length();
std::string header = "Content-Length: " + std::to_string(byte_length) + "\r\n\r\n";
// 发送 header 和 body
+24 -5
View File
@@ -1,14 +1,17 @@
#pragma once
#include <atomic>
#include <optional>
#include <string>
#include "./dispacther.hpp"
#include "./request_scheduler.hpp"
#include "../provider/base/provider_registry.hpp"
namespace lsp
{
class LspServer
{
public:
LspServer();
LspServer(size_t concurrency = std::thread::hardware_concurrency());
~LspServer();
void Run();
@@ -17,18 +20,34 @@ namespace lsp
std::optional<std::string> ReadMessage();
// 处理LSP请求 - 返回序列化的响应或空字符串(对于通知)
std::string HandleMessage(const std::string& raw_message);
void HandleMessage(const std::string& raw_message);
// 发送LSP响应
void SendResponse(const std::string& response);
// 处理不同类型的消息
std::string HandleRequest(const protocol::RequestMessage& request);
std::string HandleNotification(const protocol::NotificationMessage& notification);
void HandleRequest(const protocol::RequestMessage& request);
void HandleNotification(const protocol::NotificationMessage& notification);
void HandleResponse(const protocol::ResponseMessage& response);
// 生命周期事件处理
void OnLifecycleEvent(providers::ServerLifecycleEvent event);
// 判断是否需要同步处理
bool RequiresSyncProcessing(const std::string& method) const;
// 检查是否可以处理请求
bool CanProcessRequest(const std::string& method) const;
// 处理取消请求
void HandleCancelRequest(const protocol::NotificationMessage& notification);
private:
RequestDispatcher dispatcher_;
bool is_initialized_ = false;
RequestScheduler scheduler_;
std::atomic<bool> is_initialized_ = false;
std::atomic<bool> is_shutting_down_ = false;
std::mutex output_mutex_;
};
}
+1 -1
View File
@@ -33,7 +33,7 @@ namespace lsp::protocol
struct WorkDoneProgressOptions
{
boolean workDoneProgress;
std::optional<boolean> workDoneProgress;
};
struct PartialResultParams
@@ -87,6 +87,16 @@ namespace lsp::transform
return "null";
return "unknown";
}
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);
}
}
}
@@ -4,20 +4,37 @@
namespace lsp::providers
{
std::string ILspProvider::BuildErrorMessageResponse(protocol::ErrorCode code, const std::string& message)
std::string ILspProvider::BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
{
protocol::ResponseMessage response;
response.id = request.id;
protocol::ResponseError error;
error.code = code;
error.message = message;
response.error = error;
std::string json;
auto ec = glz::write_json(error, json);
if (ec)
{
spdlog::error("{}: Error", GetProviderName());
std::string errmsg = "Failed to serialize [" + GetProviderName() + "] error response: " + glz::format_error(ec);
throw std::runtime_error(errmsg);
spdlog::error("Failed to serialize error response: {}", glz::format_error(ec, json));
return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})";
}
return json;
}
void ILifecycleAwareProvider::SetLifecycleCallback(LifecycleCallback callback)
{
lifecycle_callback_ = std::move(callback);
}
void ILifecycleAwareProvider::NotifyLifecycleEvent(ServerLifecycleEvent event)
{
if (lifecycle_callback_)
{
lifecycle_callback_(event);
spdlog::debug("Provider {} triggered event: {}", GetProviderName(), static_cast<int>(event));
}
}
}
@@ -4,6 +4,16 @@
namespace lsp::providers
{
enum class ServerLifecycleEvent
{
kInitializing,
kInitialized,
kInitializeFailed,
kShuttingDown,
kShutdown
};
using LifecycleCallback = std::function<void(ServerLifecycleEvent)>;
// LSP请求提供者接口基类
class ILspProvider
@@ -18,8 +28,24 @@ namespace lsp::providers
// 获取提供者名称(用于日志和调试)
virtual std::string GetProviderName() const = 0;
static std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
};
// 生命周期感知的 Provider 接口
class ILifecycleAwareProvider : public ILspProvider
{
public:
virtual ~ILifecycleAwareProvider() = default;
// 设置生命周期回调
void SetLifecycleCallback(LifecycleCallback callback);
protected:
std::string BuildErrorMessageResponse(protocol::ErrorCode code, const std::string& message);
// 触发生命周期事件
void NotifyLifecycleEvent(ServerLifecycleEvent event);
private:
LifecycleCallback lifecycle_callback_;
};
}
@@ -6,6 +6,7 @@
#include "../text_document/did_change_provider.hpp"
#include "../text_document/completion_provider.hpp"
#include "../trace/set_trace_provider.hpp"
#include "../shutdown/shutdown_provider.hpp"
namespace lsp::providers
{
@@ -20,6 +21,7 @@ namespace lsp::providers
RegisterProvider<text_document::DidChangeProvider>(dispatcher);
RegisterProvider<text_document::CompletionProvider>(dispatcher);
RegisterProvider<trace::SetTraceProvider>(dispatcher);
RegisterProvider<shutdown::ShutdownProvider>(dispatcher);
spdlog::info("Successfully registered {} LSP providers", dispatcher.GetSupportedMethods().size());
}
@@ -5,7 +5,6 @@
namespace lsp::providers
{
// 模板函数:注册provider
template<typename ProviderClass>
void RegisterProvider(RequestDispatcher& dispatcher)
@@ -14,14 +13,9 @@ namespace lsp::providers
"Provider must inherit from ILspProvider");
auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterProvider(provider);
spdlog::info("Registering {} for method: {}", provider->GetProviderName(), provider->GetMethod());
dispatcher.RegisterProvider(
provider->GetMethod(),
[provider](const protocol::RequestMessage& request) -> std::string {
return provider->ProvideResponse(request);
});
}
// 批量注册provider
@@ -12,7 +12,13 @@ namespace lsp::providers::initialize
response.result = transform::LSPAny(BuildInitializeResult());
std::string json;
auto ec = glz::write_json(response, json);
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
if (ec)
{
NotifyLifecycleEvent(ServerLifecycleEvent::kInitializeFailed);
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
}
NotifyLifecycleEvent(ServerLifecycleEvent::kInitialized);
return json;
}
std::string InitializeProvider::GetMethod() const
@@ -4,7 +4,7 @@
namespace lsp::providers::initialize
{
using namespace lsp;
class InitializeProvider : public ILspProvider
class InitializeProvider : public ILifecycleAwareProvider
{
public:
InitializeProvider() = default;
@@ -10,7 +10,7 @@ namespace lsp::providers::initialized
std::string json;
glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json);
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
}
std::string InitializedProvider::GetMethod() const
@@ -3,7 +3,7 @@
namespace lsp::providers::initialized
{
class InitializedProvider : public ILspProvider
class InitializedProvider : public ILifecycleAwareProvider
{
public:
InitializedProvider() = default;
@@ -0,0 +1,46 @@
#include <spdlog/spdlog.h>
#include "./shutdown_provider.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::shutdown
{
std::string ShutdownProvider::ProvideResponse(const protocol::RequestMessage& request)
{
spdlog::debug("ShutdownProvider: Providing response for method {}", request.method);
try
{
// 触发关闭事件
NotifyLifecycleEvent(ServerLifecycleEvent::kShuttingDown);
// 构建响应 - shutdown 返回 null
protocol::ResponseMessage response;
response.id = request.id;
std::string json;
auto ec = glz::write_json(response, json);
if (ec)
{
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Failed to serialize response");
}
spdlog::info("Shutdown request processed successfully");
return json;
}
catch (const std::exception& e)
{
spdlog::error("Shutdown request failed: {}", e.what());
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, e.what());
}
}
std::string ShutdownProvider::GetMethod() const
{
return "shutdown";
}
std::string ShutdownProvider::GetProviderName() const
{
return "ShutdownProvider";
}
}
@@ -0,0 +1,15 @@
#pragma once
#include "../base/provider_interface.hpp"
namespace lsp::providers::shutdown
{
class ShutdownProvider : public ILifecycleAwareProvider
{
public:
ShutdownProvider() = default;
std::string ProvideResponse(const protocol::RequestMessage& request) override;
std::string GetMethod() const override;
std::string GetProviderName() const override;
};
}
@@ -12,7 +12,7 @@ namespace lsp::providers::text_document
// 验证请求是否包含参数
if (!request.params.has_value()) {
spdlog::warn("{}: Missing params in request", GetProviderName());
return BuildErrorMessageResponse(protocol::ErrorCode::kInvalidParams, "Missing params");
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Missing params");
}
// 从 variant 中提取参数
@@ -28,17 +28,17 @@ namespace lsp::providers::text_document
auto ec = glz::write_json(response, json);
if (ec) {
spdlog::error("{}: Failed to serialize response: {}", GetProviderName(), glz::format_error(ec, json));
return BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Failed to serialize response");
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Failed to serialize response");
}
return json;
} catch (const transform::ConversionError& e) {
spdlog::error("{}: Failed to convert params: {}", GetProviderName(), e.what());
return BuildErrorMessageResponse(protocol::ErrorCode::kInvalidParams, "Invalid completion params");
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Invalid completion params");
} catch (const std::exception& e) {
spdlog::error("{}: Unexpected error: {}", GetProviderName(), e.what());
return BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error");
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
}
}
@@ -11,7 +11,7 @@ namespace lsp::providers::text_document
std::string json;
glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json);
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
}
std::string DidChangeProvider::GetMethod() const
@@ -9,7 +9,7 @@ namespace lsp::providers::text_document
std::string json;
glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json);
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
}
std::string DidOpenProvider::GetMethod() const
@@ -10,7 +10,7 @@ namespace lsp::providers::trace
std::string json;
glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json);
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
}
std::string SetTraceProvider::GetMethod() const