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(glaze CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED) find_package(spdlog CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED)
find_package(Taskflow REQUIRED)
if(NOT TARGET spdlog::spdlog_header_only) 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() endif()
if(NOT TARGET fmt::fmt-header-only) 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() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
endif() endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SOURCES set(SOURCES
src/main.cpp src/main.cpp
src/utils/args_parser.cpp
src/language/tsl_keywords.cpp src/language/tsl_keywords.cpp
src/lsp/dispacther.cpp src/lsp/dispacther.cpp
src/lsp/server.cpp src/lsp/server.cpp
src/lsp/request_scheduler.cpp
src/provider/base/provider_registry.cpp src/provider/base/provider_registry.cpp
src/provider/base/provider_interface.cpp src/provider/base/provider_interface.cpp
src/provider/initialize/initialize_provider.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_open_provider.cpp
src/provider/text_document/did_change_provider.cpp src/provider/text_document/did_change_provider.cpp
src/provider/text_document/completion_provider.cpp src/provider/text_document/completion_provider.cpp
src/provider/shutdown/shutdown_provider.cpp
src/provider/trace/set_trace_provider.cpp) src/provider/trace/set_trace_provider.cpp)
add_executable(${PROJECT_NAME} ${SOURCES}) add_executable(${PROJECT_NAME} ${SOURCES})
@@ -93,8 +97,8 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
FMT_HEADER_ONLY) FMT_HEADER_ONLY)
target_link_libraries( target_link_libraries(
${PROJECT_NAME} PRIVATE glaze::glaze spdlog::spdlog_header_only ${PROJECT_NAME} PRIVATE glaze::glaze Taskflow::Taskflow
fmt::fmt-header-only) spdlog::spdlog_header_only fmt::fmt-header-only)
# Linux 需要链接 pthread # Linux 需要链接 pthread
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
+69 -31
View File
@@ -5,29 +5,51 @@
namespace lsp 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_); 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); 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::string RequestDispatcher::Dispatch(const protocol::RequestMessage& request)
{ {
std::shared_lock<std::shared_mutex> lock(providers_mutex_); std::shared_lock<std::shared_mutex> lock(providers_mutex_);
auto it = providers_.find(request.method); auto it = providers_.find(request.method);
if (it != providers_.end()) if (it != providers_.end())
{ {
RequestProvider provider = it->second; auto provider = it->second;
lock.unlock(); lock.unlock();
try try
{ {
return provider(request); return provider->ProvideResponse(request);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
spdlog::error("Provider error for method {}: {}", request.method, e.what()); 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); return HandleUnknownMethod(request);
@@ -51,36 +73,52 @@ namespace lsp
return methods; 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) std::string event_name;
{ switch (event)
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)
{ {
spdlog::error("Failed to serialize error response: {}", glz::format_error(ec, json)); case ServerLifecycleEvent::kInitializing:
// 返回一个硬编码的错误响应作为后备 event_name = "Initializing";
return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})"; 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 #pragma once
#include <functional> #include <memory>
#include <unordered_map>
#include <vector> #include <vector>
#include <shared_mutex> #include <shared_mutex>
#include "../protocol/protocol.hpp" #include "../protocol/protocol.hpp"
#include "../provider/base/provider_interface.hpp"
namespace lsp namespace lsp
{ {
// 请求处理函数类型 - 返回序列化后的 JSON 字符串
using RequestProvider = std::function<std::string(const protocol::RequestMessage&)>; using ServerLifecycleEvent = providers::ServerLifecycleEvent;
using LifecycleCallback = providers::LifecycleCallback;
class RequestDispatcher class RequestDispatcher
{ {
public: public:
RequestDispatcher() = default; 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); std::string Dispatch(const protocol::RequestMessage& request);
bool SupportsMethod(const std::string& method) const; bool SupportsMethod(const std::string& method) const;
std::vector<std::string> GetSupportedMethods() const; std::vector<std::string> GetSupportedMethods() const;
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
private: private:
void NotifyAllLifecycleListeners(ServerLifecycleEvent event);
std::string HandleUnknownMethod(const protocol::RequestMessage& request); 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: private:
mutable std::shared_mutex providers_mutex_; 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 <spdlog/spdlog.h>
#include "./request_scheduler.hpp" #include "./request_scheduler.hpp"
namespace lsp namespace lsp
{ {
RequestScheduler::RequestScheduler(size_t concurrency) : RequestScheduler::RequestScheduler(size_t concurrency) :
executor_(concurrency) executor_(concurrency)
{ {
spdlog::info("RequestScheduler initialized with {} threads", 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_); WaitAll();
auto future = executor_.silent_async([this, request_id, task = std::move(task)] { }
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 try
{ {
if (context->cancelled.load())
{
spdlog::debug("Task {} was cancelled", request_id);
return;
}
auto result = task(); auto result = task();
if (result)
if (!context->cancelled.load() && result)
{
SendResponse(*result); SendResponse(*result);
}
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
spdlog::error("Task {} failed: {}", request_id, e.what()); 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_); std::lock_guard<std::mutex> lock(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); 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_); std::lock_guard<std::mutex> lock(mutex_);
send_response_ = std::move(callback); response_callback_ = std::move(callback);
}
void RequestScheduler::WaitAll()
{
executor_.wait_for_all();
} }
void RequestScheduler::SendResponse(const std::string& response) void RequestScheduler::SendResponse(const std::string& response)
{ {
std::lock_guard<std::mutex> lock(output_mutex_); ResponseCallback callback;
if (send_response_) {
send_response_(response); std::lock_guard<std::mutex> lock(mutex_);
callback = response_callback_;
}
if (callback)
callback(response);
else 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 #pragma once
#include <mutex> #include <atomic>
#include <functional> #include <functional>
#include <string> #include <mutex>
#include <optional> #include <optional>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <taskflow/taskflow.hpp> #include <taskflow/taskflow.hpp>
@@ -12,23 +14,28 @@ namespace lsp
{ {
public: public:
using TaskFunc = std::function<std::optional<std::string>()>; 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(); ~RequestScheduler();
void Sumbit(const std::string& request_id, TaskFunc task); void Submit(const std::string& request_id, TaskFunc task);
void Cancel(const std::string& request_id); bool Cancel(const std::string& request_id);
void SetOutputFallback(std::function<void(const std::string&)> callback); void SetResponseCallback(ResponseCallback callback);
void WaitAll();
private: private:
struct TaskContext
{
std::atomic<bool> cancelled{false};
};
void SendResponse(const std::string& response); void SendResponse(const std::string& response);
private: private:
tf::Executor executor_; tf::Executor executor_;
std::mutex task_mutex_; mutable std::mutex mutex_;
std::mutex cancel_mutex_; std::unordered_map<std::string, std::shared_ptr<TaskContext>> running_tasks_;
std::mutex output_mutex_; ResponseCallback response_callback_;
std::unordered_map<std::string, tf::Future<void>> running_tasks_;
std::function<void(const std::string&)> send_response_;
}; };
} }
+193 -62
View File
@@ -1,3 +1,4 @@
#include "request_scheduler.hpp"
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
@@ -11,13 +12,29 @@
namespace lsp 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_); providers::RegisterAllProviders(dispatcher_);
scheduler_.SetResponseCallback([this](const std::string& response) {
SendResponse(response);
});
spdlog::debug("LSP server initialized with {} providers.", dispatcher_.GetSupportedMethods().size()); 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() void LspServer::Run()
{ {
@@ -29,7 +46,7 @@ namespace lsp
_setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdin), _O_BINARY);
#endif #endif
while (true) while (!is_shutting_down_)
{ {
try try
{ {
@@ -40,11 +57,7 @@ namespace lsp
continue; continue;
} }
std::string response = HandleMessage(*message); HandleMessage(*message);
if (!response.empty())
{
SendResponse(response);
}
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@@ -106,9 +119,7 @@ namespace lsp
if (std::cin.gcount() != static_cast<std::streamsize>(content_length)) if (std::cin.gcount() != static_cast<std::streamsize>(content_length))
{ {
spdlog::error("Read incomplete message body, expected: {}, got: {}", spdlog::error("Read incomplete message body, expected: {}, got: {}", content_length, std::cin.gcount());
content_length,
std::cin.gcount());
return std::nullopt; return std::nullopt;
} }
@@ -116,122 +127,242 @@ namespace lsp
return body; return body;
} }
std::string LspServer::HandleMessage(const std::string& raw_message) void LspServer::HandleMessage(const std::string& raw_message)
{ {
try try
{ {
// 首先尝试解析为通用的 JSON 判断消息类型 // 解析 JSON 判断消息类型
glz::json_t doc; glz::json_t doc;
auto error = glz::read_json(doc, raw_message); auto error = glz::read_json(doc, raw_message);
if (error) if (error)
{ {
spdlog::error("Failed to parse message as JSON: {}", spdlog::error("Failed to parse message as JSON: {}", glz::format_error(error, raw_message));
glz::format_error(error, raw_message)); return;
return "";
} }
auto& obj = doc.get<glz::json_t::object_t>(); auto& obj = doc.get<glz::json_t::object_t>();
// 判断消息类型
bool has_id = obj.contains("id");
bool has_method = obj.contains("method"); 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 bool has_id = obj.contains("id");
protocol::RequestMessage request;
error = glz::read_json(request, raw_message); if (has_id)
if (error)
{ {
spdlog::error("Failed to parse request: {}", // RequestMessage
glz::format_error(error, raw_message)); protocol::RequestMessage request;
return ""; 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
}
else if (has_method && !has_id)
{
// Notification
protocol::NotificationMessage notification;
error = glz::read_json(notification, raw_message);
if (error)
{ {
spdlog::error("Failed to parse notification: {}", // NotificationMessage
glz::format_error(error, raw_message)); protocol::NotificationMessage notification;
return ""; 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; protocol::ResponseMessage response;
error = glz::read_json(response, raw_message); error = glz::read_json(response, raw_message);
if (error) if (error)
{ {
spdlog::error("Failed to parse response: {}", spdlog::error("Failed to parse response: {}",
glz::format_error(error, raw_message)); glz::format_error(error, raw_message));
return ""; return;
} }
HandleResponse(response); HandleResponse(response);
return ""; // 响应不需要回复
} }
else else
{ {
spdlog::error("Unknown message type"); spdlog::error("Unknown message type");
return "";
} }
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
spdlog::error("Failed to handle message: {}", e.what()); 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); 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") if (notification.method == "initialized")
{ {
spdlog::info("Client initialized"); spdlog::info("Client acknowledged initialization");
} }
else if (notification.method == "exit") else if (notification.method == "exit")
{ {
spdlog::info("Exit notification received"); spdlog::info("Exit notification received");
is_shutting_down_ = true;
// 给一点时间让任务完成
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::exit(0); std::exit(0);
} }
// 通知不需要响应
return "";
} }
void LspServer::HandleResponse(const protocol::ResponseMessage& response) 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) 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"; std::string header = "Content-Length: " + std::to_string(byte_length) + "\r\n\r\n";
// 发送 header 和 body // 发送 header 和 body
+24 -5
View File
@@ -1,14 +1,17 @@
#pragma once #pragma once
#include <atomic>
#include <optional> #include <optional>
#include <string> #include <string>
#include "./dispacther.hpp" #include "./dispacther.hpp"
#include "./request_scheduler.hpp"
#include "../provider/base/provider_registry.hpp"
namespace lsp namespace lsp
{ {
class LspServer class LspServer
{ {
public: public:
LspServer(); LspServer(size_t concurrency = std::thread::hardware_concurrency());
~LspServer(); ~LspServer();
void Run(); void Run();
@@ -17,18 +20,34 @@ namespace lsp
std::optional<std::string> ReadMessage(); std::optional<std::string> ReadMessage();
// 处理LSP请求 - 返回序列化的响应或空字符串(对于通知) // 处理LSP请求 - 返回序列化的响应或空字符串(对于通知)
std::string HandleMessage(const std::string& raw_message); void HandleMessage(const std::string& raw_message);
// 发送LSP响应 // 发送LSP响应
void SendResponse(const std::string& response); void SendResponse(const std::string& response);
// 处理不同类型的消息 // 处理不同类型的消息
std::string HandleRequest(const protocol::RequestMessage& request); void HandleRequest(const protocol::RequestMessage& request);
std::string HandleNotification(const protocol::NotificationMessage& notification); void HandleNotification(const protocol::NotificationMessage& notification);
void HandleResponse(const protocol::ResponseMessage& response); 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: private:
RequestDispatcher dispatcher_; 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 struct WorkDoneProgressOptions
{ {
boolean workDoneProgress; std::optional<boolean> workDoneProgress;
}; };
struct PartialResultParams struct PartialResultParams
@@ -87,6 +87,16 @@ namespace lsp::transform
return "null"; return "null";
return "unknown"; 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 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; protocol::ResponseError error;
error.code = code; error.code = code;
error.message = message; error.message = message;
response.error = error;
std::string json; std::string json;
auto ec = glz::write_json(error, json); auto ec = glz::write_json(error, json);
if (ec) if (ec)
{ {
spdlog::error("{}: Error", GetProviderName()); spdlog::error("Failed to serialize error response: {}", glz::format_error(ec, json));
std::string errmsg = "Failed to serialize [" + GetProviderName() + "] error response: " + glz::format_error(ec); return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})";
throw std::runtime_error(errmsg);
} }
return json; 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 namespace lsp::providers
{ {
enum class ServerLifecycleEvent
{
kInitializing,
kInitialized,
kInitializeFailed,
kShuttingDown,
kShutdown
};
using LifecycleCallback = std::function<void(ServerLifecycleEvent)>;
// LSP请求提供者接口基类 // LSP请求提供者接口基类
class ILspProvider class ILspProvider
@@ -18,8 +28,24 @@ namespace lsp::providers
// 获取提供者名称(用于日志和调试) // 获取提供者名称(用于日志和调试)
virtual std::string GetProviderName() const = 0; 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: 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/did_change_provider.hpp"
#include "../text_document/completion_provider.hpp" #include "../text_document/completion_provider.hpp"
#include "../trace/set_trace_provider.hpp" #include "../trace/set_trace_provider.hpp"
#include "../shutdown/shutdown_provider.hpp"
namespace lsp::providers namespace lsp::providers
{ {
@@ -20,6 +21,7 @@ namespace lsp::providers
RegisterProvider<text_document::DidChangeProvider>(dispatcher); RegisterProvider<text_document::DidChangeProvider>(dispatcher);
RegisterProvider<text_document::CompletionProvider>(dispatcher); RegisterProvider<text_document::CompletionProvider>(dispatcher);
RegisterProvider<trace::SetTraceProvider>(dispatcher); RegisterProvider<trace::SetTraceProvider>(dispatcher);
RegisterProvider<shutdown::ShutdownProvider>(dispatcher);
spdlog::info("Successfully registered {} LSP providers", dispatcher.GetSupportedMethods().size()); spdlog::info("Successfully registered {} LSP providers", dispatcher.GetSupportedMethods().size());
} }
@@ -5,7 +5,6 @@
namespace lsp::providers namespace lsp::providers
{ {
// 模板函数:注册provider // 模板函数:注册provider
template<typename ProviderClass> template<typename ProviderClass>
void RegisterProvider(RequestDispatcher& dispatcher) void RegisterProvider(RequestDispatcher& dispatcher)
@@ -14,14 +13,9 @@ namespace lsp::providers
"Provider must inherit from ILspProvider"); "Provider must inherit from ILspProvider");
auto provider = std::make_shared<ProviderClass>(); auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterProvider(provider);
spdlog::info("Registering {} for method: {}", provider->GetProviderName(), provider->GetMethod()); 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 // 批量注册provider
@@ -12,7 +12,13 @@ namespace lsp::providers::initialize
response.result = transform::LSPAny(BuildInitializeResult()); response.result = transform::LSPAny(BuildInitializeResult());
std::string json; std::string json;
auto ec = glz::write_json(response, 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 std::string InitializeProvider::GetMethod() const
@@ -4,7 +4,7 @@
namespace lsp::providers::initialize namespace lsp::providers::initialize
{ {
using namespace lsp; using namespace lsp;
class InitializeProvider : public ILspProvider class InitializeProvider : public ILifecycleAwareProvider
{ {
public: public:
InitializeProvider() = default; InitializeProvider() = default;
@@ -10,7 +10,7 @@ namespace lsp::providers::initialized
std::string json; std::string json;
glz::obj empty_obj{}; // glaze的对象类型 glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json); 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 std::string InitializedProvider::GetMethod() const
@@ -3,7 +3,7 @@
namespace lsp::providers::initialized namespace lsp::providers::initialized
{ {
class InitializedProvider : public ILspProvider class InitializedProvider : public ILifecycleAwareProvider
{ {
public: public:
InitializedProvider() = default; 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()) { if (!request.params.has_value()) {
spdlog::warn("{}: Missing params in request", GetProviderName()); spdlog::warn("{}: Missing params in request", GetProviderName());
return BuildErrorMessageResponse(protocol::ErrorCode::kInvalidParams, "Missing params"); return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Missing params");
} }
// 从 variant 中提取参数 // 从 variant 中提取参数
@@ -28,17 +28,17 @@ namespace lsp::providers::text_document
auto ec = glz::write_json(response, json); auto ec = glz::write_json(response, json);
if (ec) { if (ec) {
spdlog::error("{}: Failed to serialize response: {}", GetProviderName(), glz::format_error(ec, json)); 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; return json;
} catch (const transform::ConversionError& e) { } catch (const transform::ConversionError& e) {
spdlog::error("{}: Failed to convert params: {}", GetProviderName(), e.what()); 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) { } catch (const std::exception& e) {
spdlog::error("{}: Unexpected error: {}", GetProviderName(), e.what()); 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; std::string json;
glz::obj empty_obj{}; // glaze的对象类型 glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json); 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 std::string DidChangeProvider::GetMethod() const
@@ -9,7 +9,7 @@ namespace lsp::providers::text_document
std::string json; std::string json;
glz::obj empty_obj{}; // glaze的对象类型 glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json); 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 std::string DidOpenProvider::GetMethod() const
@@ -10,7 +10,7 @@ namespace lsp::providers::trace
std::string json; std::string json;
glz::obj empty_obj{}; // glaze的对象类型 glz::obj empty_obj{}; // glaze的对象类型
auto ec = glz::write_json(empty_obj, json); 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 std::string SetTraceProvider::GetMethod() const