module; export module lsp.core.server; import spdlog; import tree_sitter; import std; import lsp.bridge.win32_stdio; import lsp.core.dispatcher; import lsp.protocol; import lsp.codec.facade; import lsp.language.ast; import lsp.manager.manager_hub; import lsp.manager.bootstrap; import lsp.manager.events; import lsp.scheduler.async_executor; import lsp.provider.base.interface; import lsp.provider.manifest; namespace transform = lsp::codec; export namespace lsp::core { class LspServer { public: explicit LspServer(std::size_t concurrency = std::thread::hardware_concurrency(), std::string interpreter_path = ""); ~LspServer(); void Run(); private: // 读取LSP消息 std::optional ReadMessage(); // 处理LSP请求 - 返回序列化的响应或空字符串(对于通知) void HandleMessage(const std::string& raw_message); // 发送LSP消息(响应/通知) void SendMessage(const std::string& message); // 处理不同类型的消息 void HandleRequest(const protocol::RequestMessage& request); void HandleNotification(const protocol::NotificationMessage& notification); void HandleResponse(const protocol::ResponseMessage& response); // 生命周期事件处理 void OnLifecycleEvent(provider::ServerLifecycleEvent event); // 判断是否需要同步处理 bool RequiresSyncProcessing(const std::string& method) const; // 检查是否可以处理请求 bool CanProcessRequest(const std::string& method) const; // 处理取消请求 void HandleCancelRequest(const protocol::NotificationMessage& notification); private: void InitializeManagerHub(); void RegisterProviders(); void RegisterDiagnosticsPublisher(); void PublishDiagnostics(const protocol::DocumentUri& uri, std::optional version, TSTree* tree, const protocol::string& content); void ClearDiagnostics(const protocol::DocumentUri& uri); // 错误处理 void SendError(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message); void SendStateError(const protocol::RequestMessage& request); private: RequestDispatcher dispatcher_; manager::ManagerHub manager_hub_; scheduler::AsyncExecutor async_executor_; std::string interpreter_path_; std::atomic is_initialized_ = false; std::atomic is_shutting_down_ = false; std::mutex output_mutex_; }; } namespace lsp::core { LspServer::LspServer(std::size_t concurrency, std::string interpreter_path) : manager_hub_(), async_executor_(concurrency), interpreter_path_(std::move(interpreter_path)) { spdlog::info("Initializing LSP server with {} worker threads", concurrency); InitializeManagerHub(); RegisterProviders(); if (provider::kEnableDiagnosticsPublisher) { RegisterDiagnosticsPublisher(); } else { spdlog::debug("Diagnostics publisher disabled (staged rollout)"); } spdlog::debug("LSP server initialized with {} providers.", dispatcher_.GetAllSupportedMethods().size()); } LspServer::~LspServer() { is_shutting_down_ = true; spdlog::info("LSP server shutting down..."); } void LspServer::Run() { spdlog::info("LSP server starting main loop..."); spdlog::info("Waiting for LSP messages on stdin..."); bridge::win32_stdio::SetStdioBinaryMode(); while (!is_shutting_down_) { try { std::optional message = ReadMessage(); if (!message) { if (std::cin.eof()) { spdlog::info("End of input stream, exiting main loop"); break; // EOF } spdlog::debug("No message received, continuing..."); std::this_thread::sleep_for(std::chrono::milliseconds(5)); continue; } HandleMessage(*message); } catch (const std::exception& e) { spdlog::error("Error in main loop: {}", e.what()); std::this_thread::sleep_for(std::chrono::milliseconds(5)); } } spdlog::info("LSP server main loop ended"); } std::optional LspServer::ReadMessage() { std::string line; std::size_t content_length = 0; // 读取 LSP Header while (std::getline(std::cin, line)) { // 去掉尾部 \\r if (!line.empty() && line.back() == '\r') { line.pop_back(); } if (line.empty()) { break; // 空行表示 header 结束 } if (line.rfind("Content-Length:", 0) == 0) { std::string length_str = line.substr(15); // 跳过 "Content-Length:" std::size_t start = length_str.find_first_not_of(' '); if (start != std::string::npos) { length_str = length_str.substr(start); try { content_length = std::stoul(length_str); spdlog::trace("Content-Length: {}", content_length); } catch (const std::exception& e) { spdlog::error("Failed to parse Content-Length: {}", e.what()); return std::nullopt; } } } } if (content_length == 0) { spdlog::debug("No Content-Length found in header"); return std::nullopt; } // 读取内容体 std::string body(content_length, '\0'); std::cin.read(&body[0], content_length); if (std::cin.gcount() != static_cast(content_length)) { spdlog::error("Failed to read expected content length: {} bytes, got {} bytes", content_length, std::cin.gcount()); return std::nullopt; } spdlog::trace("Received message: {}", body); return body; } void LspServer::HandleMessage(const std::string& raw_message) { auto any = transform::Deserialize(raw_message); if (!any || !any->Is()) { spdlog::warn("Failed to parse message: {}", raw_message); return; } const auto& obj = any->Get(); const bool has_id = obj.find("id") != obj.end(); const bool has_method = obj.find("method") != obj.end(); const bool has_result = obj.find("result") != obj.end(); const bool has_error = obj.find("error") != obj.end(); if (has_method && has_id) { if (auto request = transform::Deserialize(raw_message)) HandleRequest(*request); else spdlog::warn("Failed to parse request message"); return; } if (has_method) { if (auto notification = transform::Deserialize(raw_message)) HandleNotification(*notification); else spdlog::warn("Failed to parse notification message"); return; } if (has_id && (has_result || has_error)) { if (auto response = transform::Deserialize(raw_message)) HandleResponse(*response); else spdlog::warn("Failed to parse response message"); return; } spdlog::warn("Unrecognized message: {}", raw_message); } void LspServer::SendMessage(const std::string& message) { if (message.empty()) return; std::lock_guard lock(output_mutex_); std::cout << "Content-Length: " << message.size() << "\r\n\r\n" << message << std::flush; } void LspServer::HandleRequest(const protocol::RequestMessage& request) { spdlog::debug("Handling request: {}", request.method); if (request.method == "shutdown") { auto response = dispatcher_.Dispatch(request); SendMessage(response); is_shutting_down_ = true; return; } // 未初始化时的特殊处理 if (!is_initialized_ && request.method != "initialize") { SendStateError(request); return; } auto response = dispatcher_.Dispatch(request); SendMessage(response); } void LspServer::HandleNotification(const protocol::NotificationMessage& notification) { spdlog::debug("Handling notification: {}", notification.method); if (notification.method == "exit") { is_shutting_down_ = true; return; } // 处理取消请求 if (notification.method == "$/cancelRequest") { HandleCancelRequest(notification); return; } // 未初始化时只接受 initialized/exit if (!is_initialized_ && notification.method != "initialized" && notification.method != "exit") { spdlog::warn("Server not initialized; ignoring notification: {}", notification.method); return; } dispatcher_.Dispatch(notification); } void LspServer::HandleResponse(const protocol::ResponseMessage& response) { std::string id = ""; if (response.id.has_value()) id = transform::debug::GetIdString(response.id.value()); spdlog::debug("Received response: {}", id); // 当前服务器作为 client 的场景较少,这里暂时不处理 } void LspServer::OnLifecycleEvent(provider::ServerLifecycleEvent event) { switch (event) { case provider::ServerLifecycleEvent::kInitialized: is_initialized_ = true; spdlog::info("Server initialized"); break; case provider::ServerLifecycleEvent::kShutdown: is_shutting_down_ = true; spdlog::info("Server shutting down"); break; default: break; } } bool LspServer::RequiresSyncProcessing(const std::string& method) const { static const std::unordered_set kSyncMethods = { "initialize", "shutdown", "exit", "$/setTrace", }; return kSyncMethods.contains(method); } bool LspServer::CanProcessRequest(const std::string& method) const { if (is_shutting_down_) return false; // 初始化前,只处理 initialize 请求 if (!is_initialized_ && method != "initialize") return false; return true; } void LspServer::HandleCancelRequest(const protocol::NotificationMessage& notification) { if (!notification.params.has_value()) return; protocol::CancelParams params = transform::FromLSPAny.template operator()(notification.params.value()); const std::string id_string = std::visit([](const auto& value) -> std::string { if constexpr (std::is_same_v, int>) return std::to_string(value); else return value; }, params.id); spdlog::debug("Cancel request received for id: {}", id_string); // TODO: 实现请求取消逻辑 } void LspServer::InitializeManagerHub() { manager_hub_.Initialize(); if (!interpreter_path_.empty()) { std::filesystem::path base = interpreter_path_; std::filesystem::path funcext_path = base / "funcext"; if (std::filesystem::exists(funcext_path)) { manager::bootstrap::InitializeManagerHub( manager_hub_, async_executor_, { funcext_path.string() }); } else { spdlog::warn("Interpreter funcext path does not exist: {}", funcext_path.string()); } } } void LspServer::RegisterProviders() { dispatcher_.SetRequestScheduler(&async_executor_); dispatcher_.SetManagerHub(&manager_hub_); dispatcher_.RegisterLifecycleCallback([this](ServerLifecycleEvent event) { OnLifecycleEvent(event); }); spdlog::info("Registering LSP providers..."); provider::RegisterAllProviders(dispatcher_); spdlog::info("Registered {} LSP providers", dispatcher_.GetAllSupportedMethods().size()); } void LspServer::RegisterDiagnosticsPublisher() { auto& event_bus = manager_hub_.event_bus(); event_bus.Subscribe( [this](const manager::events::DocumentParsed& event) { PublishDiagnostics(event.item.uri, event.item.version, event.tree, event.item.text); }); event_bus.Subscribe( [this](const manager::events::DocumentReparsed& event) { PublishDiagnostics(event.item.uri, event.item.version, event.tree, event.item.text); }); event_bus.Subscribe( [this](const manager::events::DocumentClosed& event) { ClearDiagnostics(event.textDocument.uri); }); } void LspServer::PublishDiagnostics(const protocol::DocumentUri& uri, std::optional version, TSTree* tree, const protocol::string& content) { if (!tree) { spdlog::warn("Skip diagnostics publish: null syntax tree for {}", uri); return; } language::ast::Deserializer deserializer; auto errors = deserializer.DiagnoseSyntax(ts_tree_root_node(tree), content); std::vector diagnostics; diagnostics.reserve(errors.size()); for (const auto& error : errors) { protocol::Diagnostic diagnostic; diagnostic.range.start.line = error.location.start_line; diagnostic.range.start.character = error.location.start_column; diagnostic.range.end.line = error.location.end_line; diagnostic.range.end.character = error.location.end_column; switch (error.severity) { case language::ast::ErrorSeverity::Warning: diagnostic.severity = protocol::DiagnosticSeverity::Warning; break; case language::ast::ErrorSeverity::Fatal: case language::ast::ErrorSeverity::Error: default: diagnostic.severity = protocol::DiagnosticSeverity::Error; break; } diagnostic.source = "tsl"; diagnostic.message = error.message; diagnostics.push_back(std::move(diagnostic)); } protocol::PublishDiagnosticsParams params; params.uri = uri; params.version = version; params.diagnostics = std::move(diagnostics); protocol::NotificationMessage notification; notification.method = "textDocument/publishDiagnostics"; notification.params = transform::ToLSPAny(params); auto json = transform::Serialize(notification); if (!json) { spdlog::warn("Failed to serialize diagnostics notification for {}", uri); return; } SendMessage(*json); } void LspServer::ClearDiagnostics(const protocol::DocumentUri& uri) { protocol::PublishDiagnosticsParams params; params.uri = uri; params.version = std::nullopt; params.diagnostics = {}; protocol::NotificationMessage notification; notification.method = "textDocument/publishDiagnostics"; notification.params = transform::ToLSPAny(params); auto json = transform::Serialize(notification); if (!json) { spdlog::warn("Failed to serialize diagnostics clear notification for {}", uri); return; } SendMessage(*json); } void LspServer::SendError(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message) { protocol::ResponseMessage response; response.id = request.id; protocol::ResponseError error; error.code = static_cast(code); error.message = message; response.error = error; auto json = transform::Serialize(response); if (json) { SendMessage(*json); } } void LspServer::SendStateError(const protocol::RequestMessage& request) { SendError(request, protocol::ErrorCodes::ServerNotInitialized, "Server not initialized"); } }