feat: support concurrency
This commit is contained in:
@@ -1,23 +1,40 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
std::string ILspProvider::BuildErrorMessageResponse(protocol::ErrorCode code, const std::string& message)
|
||||
{
|
||||
protocol::ResponseError error;
|
||||
error.code = code;
|
||||
error.message = message;
|
||||
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);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
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("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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +1,51 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "../../protocol/protocol.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
// LSP请求提供者接口基类
|
||||
class ILspProvider
|
||||
{
|
||||
public:
|
||||
virtual ~ILspProvider() = default;
|
||||
|
||||
// 处理LSP请求
|
||||
virtual std::string ProvideResponse(const protocol::RequestMessage& request) = 0;
|
||||
// 获取支持的LSP方法名
|
||||
virtual std::string GetMethod() const = 0;
|
||||
// 获取提供者名称(用于日志和调试)
|
||||
virtual std::string GetProviderName() const = 0;
|
||||
|
||||
protected:
|
||||
std::string BuildErrorMessageResponse(protocol::ErrorCode code, const std::string& message);
|
||||
};
|
||||
|
||||
}
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "../../protocol/protocol.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
enum class ServerLifecycleEvent
|
||||
{
|
||||
kInitializing,
|
||||
kInitialized,
|
||||
kInitializeFailed,
|
||||
kShuttingDown,
|
||||
kShutdown
|
||||
};
|
||||
|
||||
using LifecycleCallback = std::function<void(ServerLifecycleEvent)>;
|
||||
|
||||
// LSP请求提供者接口基类
|
||||
class ILspProvider
|
||||
{
|
||||
public:
|
||||
virtual ~ILspProvider() = default;
|
||||
|
||||
// 处理LSP请求
|
||||
virtual std::string ProvideResponse(const protocol::RequestMessage& request) = 0;
|
||||
// 获取支持的LSP方法名
|
||||
virtual std::string GetMethod() 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:
|
||||
// 触发生命周期事件
|
||||
void NotifyLifecycleEvent(ServerLifecycleEvent event);
|
||||
|
||||
private:
|
||||
LifecycleCallback lifecycle_callback_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./provider_registry.hpp"
|
||||
#include "../initialize/initialize_provider.hpp"
|
||||
#include "../initialized/initialized_provider.hpp"
|
||||
#include "../text_document/did_open_provider.hpp"
|
||||
#include "../text_document/did_change_provider.hpp"
|
||||
#include "../text_document/completion_provider.hpp"
|
||||
#include "../trace/set_trace_provider.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
void RegisterAllProviders(RequestDispatcher& dispatcher)
|
||||
{
|
||||
spdlog::info("Registering LSP providers...");
|
||||
|
||||
RegisterProvider<initialize::InitializeProvider>(dispatcher);
|
||||
RegisterProvider<initialized::InitializedProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidOpenProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidChangeProvider>(dispatcher);
|
||||
RegisterProvider<text_document::CompletionProvider>(dispatcher);
|
||||
RegisterProvider<trace::SetTraceProvider>(dispatcher);
|
||||
|
||||
spdlog::info("Successfully registered {} LSP providers", dispatcher.GetSupportedMethods().size());
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./provider_registry.hpp"
|
||||
#include "../initialize/initialize_provider.hpp"
|
||||
#include "../initialized/initialized_provider.hpp"
|
||||
#include "../text_document/did_open_provider.hpp"
|
||||
#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
|
||||
{
|
||||
|
||||
void RegisterAllProviders(RequestDispatcher& dispatcher)
|
||||
{
|
||||
spdlog::info("Registering LSP providers...");
|
||||
|
||||
RegisterProvider<initialize::InitializeProvider>(dispatcher);
|
||||
RegisterProvider<initialized::InitializedProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidOpenProvider>(dispatcher);
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
#pragma once
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../../lsp/dispacther.hpp"
|
||||
#include "./provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
// 模板函数:注册provider
|
||||
template<typename ProviderClass>
|
||||
void RegisterProvider(RequestDispatcher& dispatcher)
|
||||
{
|
||||
static_assert(std::is_base_of_v<ILspProvider, ProviderClass>,
|
||||
"Provider must inherit from ILspProvider");
|
||||
|
||||
auto provider = std::make_shared<ProviderClass>();
|
||||
|
||||
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
|
||||
void RegisterAllProviders(RequestDispatcher& dispatcher);
|
||||
|
||||
}
|
||||
#pragma once
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../../lsp/dispacther.hpp"
|
||||
#include "./provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
// 模板函数:注册provider
|
||||
template<typename ProviderClass>
|
||||
void RegisterProvider(RequestDispatcher& dispatcher)
|
||||
{
|
||||
static_assert(std::is_base_of_v<ILspProvider, ProviderClass>,
|
||||
"Provider must inherit from ILspProvider");
|
||||
|
||||
auto provider = std::make_shared<ProviderClass>();
|
||||
dispatcher.RegisterProvider(provider);
|
||||
|
||||
spdlog::info("Registering {} for method: {}", provider->GetProviderName(), provider->GetMethod());
|
||||
}
|
||||
|
||||
// 批量注册provider
|
||||
void RegisterAllProviders(RequestDispatcher& dispatcher);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +1,50 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./initialize_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
{
|
||||
std::string InitializeProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(BuildInitializeResult());
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
return ec ? BuildErrorMessageResponse(protocol::ErrorCode::kInternalError, "Internal error") : json;
|
||||
}
|
||||
|
||||
std::string InitializeProvider::GetMethod() const
|
||||
{
|
||||
return "initialize";
|
||||
}
|
||||
|
||||
std::string InitializeProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializeProvider";
|
||||
}
|
||||
|
||||
protocol::InitializeResult InitializeProvider::BuildInitializeResult()
|
||||
{
|
||||
protocol::InitializeResult result;
|
||||
result.serverInfo.name = "TSL Language Server";
|
||||
result.serverInfo.version = "1.0.0";
|
||||
protocol::TextDocumentSyncOptions opts;
|
||||
opts.openClose = true;
|
||||
opts.change = protocol::TextDocumentSyncKind::kIncremental;
|
||||
protocol::CompletionOptions completion_provider;
|
||||
completion_provider.resolveProvider = false;
|
||||
|
||||
result.capabilities.textDocumentSync = opts;
|
||||
result.capabilities.completionProvider = completion_provider;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./initialize_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
{
|
||||
std::string InitializeProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(BuildInitializeResult());
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
if (ec)
|
||||
{
|
||||
NotifyLifecycleEvent(ServerLifecycleEvent::kInitializeFailed);
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
|
||||
}
|
||||
NotifyLifecycleEvent(ServerLifecycleEvent::kInitialized);
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string InitializeProvider::GetMethod() const
|
||||
{
|
||||
return "initialize";
|
||||
}
|
||||
|
||||
std::string InitializeProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializeProvider";
|
||||
}
|
||||
|
||||
protocol::InitializeResult InitializeProvider::BuildInitializeResult()
|
||||
{
|
||||
protocol::InitializeResult result;
|
||||
result.serverInfo.name = "TSL Language Server";
|
||||
result.serverInfo.version = "1.0.0";
|
||||
protocol::TextDocumentSyncOptions opts;
|
||||
opts.openClose = true;
|
||||
opts.change = protocol::TextDocumentSyncKind::kIncremental;
|
||||
protocol::CompletionOptions completion_provider;
|
||||
completion_provider.resolveProvider = false;
|
||||
|
||||
result.capabilities.textDocumentSync = opts;
|
||||
result.capabilities.completionProvider = completion_provider;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
{
|
||||
using namespace lsp;
|
||||
class InitializeProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
InitializeProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
||||
private:
|
||||
protocol::InitializeResult BuildInitializeResult();
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
{
|
||||
using namespace lsp;
|
||||
class InitializeProvider : public ILifecycleAwareProvider
|
||||
{
|
||||
public:
|
||||
InitializeProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
||||
private:
|
||||
protocol::InitializeResult BuildInitializeResult();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./initialized_provider.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
|
||||
std::string InitializedProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
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;
|
||||
}
|
||||
|
||||
std::string InitializedProvider::GetMethod() const
|
||||
{
|
||||
return "initialized";
|
||||
}
|
||||
|
||||
std::string InitializedProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializedProvider";
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./initialized_provider.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
|
||||
std::string InitializedProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
std::string json;
|
||||
glz::obj empty_obj{}; // glaze的对象类型
|
||||
auto ec = glz::write_json(empty_obj, json);
|
||||
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
|
||||
}
|
||||
|
||||
std::string InitializedProvider::GetMethod() const
|
||||
{
|
||||
return "initialized";
|
||||
}
|
||||
|
||||
std::string InitializedProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializedProvider";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
class InitializedProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
InitializedProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
class InitializedProvider : public ILifecycleAwareProvider
|
||||
{
|
||||
public:
|
||||
InitializedProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -1,159 +1,159 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./completion_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string CompletionProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("CompletionProvider: Providing response for method {}", request.method);
|
||||
|
||||
try {
|
||||
// 验证请求是否包含参数
|
||||
if (!request.params.has_value()) {
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorMessageResponse(protocol::ErrorCode::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
// 从 variant 中提取参数
|
||||
protocol::CompletionParams completion_params = transform::As<protocol::CompletionParams>(request.params.value());
|
||||
protocol::CompletionList completion_list = BuildCompletionResponse(completion_params);
|
||||
|
||||
// 构建响应消息
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(completion_list);
|
||||
|
||||
std::string json;
|
||||
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 json;
|
||||
|
||||
} catch (const transform::ConversionError& e) {
|
||||
spdlog::error("{}: Failed to convert params: {}", GetProviderName(), e.what());
|
||||
return BuildErrorMessageResponse(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");
|
||||
}
|
||||
}
|
||||
|
||||
std::string CompletionProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/completion";
|
||||
}
|
||||
|
||||
std::string CompletionProvider::GetProviderName() const
|
||||
{
|
||||
return "CompletionProvider";
|
||||
}
|
||||
|
||||
protocol::CompletionList CompletionProvider::BuildCompletionResponse(const protocol::CompletionParams& params)
|
||||
{
|
||||
spdlog::trace("{}: Processing completion request for URI='{}', Position=({}, {})",
|
||||
GetProviderName(),
|
||||
params.textDocument.uri,
|
||||
params.position.line,
|
||||
params.position.character);
|
||||
|
||||
// 获取补全前缀
|
||||
std::string prefix = ExtractPrefix(params.textDocument, params.position);
|
||||
|
||||
// 如果提供了 context,可以使用其中的信息
|
||||
if (params.context.has_value())
|
||||
{
|
||||
spdlog::trace("{}: Trigger kind: {}", GetProviderName(), static_cast<int>(params.context->triggerKind));
|
||||
if (params.context->triggerCharacter.has_value())
|
||||
spdlog::trace("{}: Trigger character: '{}'", GetProviderName(), params.context->triggerCharacter.value());
|
||||
}
|
||||
|
||||
// 收集所有补全项
|
||||
std::vector<protocol::CompletionItem> allItems;
|
||||
|
||||
// 添加关键字补全
|
||||
auto keywordItems = ProvideKeywordCompletions(prefix);
|
||||
allItems.insert(allItems.end(), keywordItems.begin(), keywordItems.end());
|
||||
|
||||
// 添加上下文相关补全
|
||||
auto contextualItems = ProvideContextualCompletions(params.textDocument, params.position, prefix);
|
||||
allItems.insert(allItems.end(), contextualItems.begin(), contextualItems.end());
|
||||
|
||||
// 构建补全列表
|
||||
protocol::CompletionList result;
|
||||
result.isIncomplete = false; // 表示这是完整的补全列表
|
||||
result.items = std::move(allItems);
|
||||
|
||||
spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CompletionProvider::ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position)
|
||||
{
|
||||
// TODO: 实现从文档内容和位置计算前缀
|
||||
// 这需要访问文档管理器来获取文档内容
|
||||
// 现在返回空字符串
|
||||
spdlog::trace("{}: ExtractPrefix not implemented, returning empty string", GetProviderName());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideKeywordCompletions(const std::string& prefix)
|
||||
{
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// 从 tsl_keywords_ 获取补全项
|
||||
auto tslItems = tsl_keywords_.GetCompletionItems(prefix);
|
||||
|
||||
for (const auto& tslItem : tslItems) {
|
||||
protocol::CompletionItem item;
|
||||
item.label = tslItem.label;
|
||||
item.kind = protocol::CompletionItemKind::kKeyword;
|
||||
item.detail = "TSL Keyword";
|
||||
|
||||
// 创建文档内容
|
||||
protocol::MarkupContent documentation;
|
||||
documentation.kind = protocol::MarkupKindLiterals::PlainText;
|
||||
documentation.value = "TSL language keyword";
|
||||
item.documentation = documentation;
|
||||
|
||||
item.insertText = tslItem.label;
|
||||
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
|
||||
{
|
||||
spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);
|
||||
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// TODO: 基于上下文提供补全
|
||||
// 示例:添加一个变量补全
|
||||
if (!prefix.empty() && prefix[0] == '$')
|
||||
{
|
||||
protocol::CompletionItem varItem;
|
||||
varItem.label = "$myVariable";
|
||||
varItem.kind = protocol::CompletionItemKind::kVariable;
|
||||
varItem.detail = "Local variable";
|
||||
varItem.insertText = "$myVariable";
|
||||
|
||||
protocol::MarkupContent doc;
|
||||
doc.kind = protocol::MarkupKindLiterals::Markdown;
|
||||
doc.value = "Example variable completion";
|
||||
varItem.documentation = doc;
|
||||
|
||||
items.push_back(varItem);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./completion_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string CompletionProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("CompletionProvider: Providing response for method {}", request.method);
|
||||
|
||||
try {
|
||||
// 验证请求是否包含参数
|
||||
if (!request.params.has_value()) {
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
// 从 variant 中提取参数
|
||||
protocol::CompletionParams completion_params = transform::As<protocol::CompletionParams>(request.params.value());
|
||||
protocol::CompletionList completion_list = BuildCompletionResponse(completion_params);
|
||||
|
||||
// 构建响应消息
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(completion_list);
|
||||
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
if (ec) {
|
||||
spdlog::error("{}: Failed to serialize response: {}", GetProviderName(), glz::format_error(ec, json));
|
||||
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 BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Invalid completion params");
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("{}: Unexpected error: {}", GetProviderName(), e.what());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
|
||||
}
|
||||
}
|
||||
|
||||
std::string CompletionProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/completion";
|
||||
}
|
||||
|
||||
std::string CompletionProvider::GetProviderName() const
|
||||
{
|
||||
return "CompletionProvider";
|
||||
}
|
||||
|
||||
protocol::CompletionList CompletionProvider::BuildCompletionResponse(const protocol::CompletionParams& params)
|
||||
{
|
||||
spdlog::trace("{}: Processing completion request for URI='{}', Position=({}, {})",
|
||||
GetProviderName(),
|
||||
params.textDocument.uri,
|
||||
params.position.line,
|
||||
params.position.character);
|
||||
|
||||
// 获取补全前缀
|
||||
std::string prefix = ExtractPrefix(params.textDocument, params.position);
|
||||
|
||||
// 如果提供了 context,可以使用其中的信息
|
||||
if (params.context.has_value())
|
||||
{
|
||||
spdlog::trace("{}: Trigger kind: {}", GetProviderName(), static_cast<int>(params.context->triggerKind));
|
||||
if (params.context->triggerCharacter.has_value())
|
||||
spdlog::trace("{}: Trigger character: '{}'", GetProviderName(), params.context->triggerCharacter.value());
|
||||
}
|
||||
|
||||
// 收集所有补全项
|
||||
std::vector<protocol::CompletionItem> allItems;
|
||||
|
||||
// 添加关键字补全
|
||||
auto keywordItems = ProvideKeywordCompletions(prefix);
|
||||
allItems.insert(allItems.end(), keywordItems.begin(), keywordItems.end());
|
||||
|
||||
// 添加上下文相关补全
|
||||
auto contextualItems = ProvideContextualCompletions(params.textDocument, params.position, prefix);
|
||||
allItems.insert(allItems.end(), contextualItems.begin(), contextualItems.end());
|
||||
|
||||
// 构建补全列表
|
||||
protocol::CompletionList result;
|
||||
result.isIncomplete = false; // 表示这是完整的补全列表
|
||||
result.items = std::move(allItems);
|
||||
|
||||
spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CompletionProvider::ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position)
|
||||
{
|
||||
// TODO: 实现从文档内容和位置计算前缀
|
||||
// 这需要访问文档管理器来获取文档内容
|
||||
// 现在返回空字符串
|
||||
spdlog::trace("{}: ExtractPrefix not implemented, returning empty string", GetProviderName());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideKeywordCompletions(const std::string& prefix)
|
||||
{
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// 从 tsl_keywords_ 获取补全项
|
||||
auto tslItems = tsl_keywords_.GetCompletionItems(prefix);
|
||||
|
||||
for (const auto& tslItem : tslItems) {
|
||||
protocol::CompletionItem item;
|
||||
item.label = tslItem.label;
|
||||
item.kind = protocol::CompletionItemKind::kKeyword;
|
||||
item.detail = "TSL Keyword";
|
||||
|
||||
// 创建文档内容
|
||||
protocol::MarkupContent documentation;
|
||||
documentation.kind = protocol::MarkupKindLiterals::PlainText;
|
||||
documentation.value = "TSL language keyword";
|
||||
item.documentation = documentation;
|
||||
|
||||
item.insertText = tslItem.label;
|
||||
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
|
||||
{
|
||||
spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);
|
||||
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// TODO: 基于上下文提供补全
|
||||
// 示例:添加一个变量补全
|
||||
if (!prefix.empty() && prefix[0] == '$')
|
||||
{
|
||||
protocol::CompletionItem varItem;
|
||||
varItem.label = "$myVariable";
|
||||
varItem.kind = protocol::CompletionItemKind::kVariable;
|
||||
varItem.detail = "Local variable";
|
||||
varItem.insertText = "$myVariable";
|
||||
|
||||
protocol::MarkupContent doc;
|
||||
doc.kind = protocol::MarkupKindLiterals::Markdown;
|
||||
doc.value = "Example variable completion";
|
||||
varItem.documentation = doc;
|
||||
|
||||
items.push_back(varItem);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../language/tsl_keywords.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class CompletionProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
CompletionProvider() = default;
|
||||
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
||||
private:
|
||||
// 构建完整的补全响应
|
||||
protocol::CompletionList BuildCompletionResponse(const protocol::CompletionParams& params);
|
||||
|
||||
// 获取补全前缀(从文档内容和位置计算)
|
||||
std::string ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position);
|
||||
|
||||
// 提供不同类型的补全
|
||||
std::vector<protocol::CompletionItem> ProvideKeywordCompletions(const std::string& prefix);
|
||||
std::vector<protocol::CompletionItem> ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix);
|
||||
|
||||
private:
|
||||
tsl::TslKeywords tsl_keywords_;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../language/tsl_keywords.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class CompletionProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
CompletionProvider() = default;
|
||||
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
||||
private:
|
||||
// 构建完整的补全响应
|
||||
protocol::CompletionList BuildCompletionResponse(const protocol::CompletionParams& params);
|
||||
|
||||
// 获取补全前缀(从文档内容和位置计算)
|
||||
std::string ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position);
|
||||
|
||||
// 提供不同类型的补全
|
||||
std::vector<protocol::CompletionItem> ProvideKeywordCompletions(const std::string& prefix);
|
||||
std::vector<protocol::CompletionItem> ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix);
|
||||
|
||||
private:
|
||||
tsl::TslKeywords tsl_keywords_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./did_change_provider.hpp"
|
||||
#include "./did_open_provider.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidChangeProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("DidChangeProvider: Providing response for method {}", request.method);
|
||||
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;
|
||||
}
|
||||
|
||||
std::string DidChangeProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didChange";
|
||||
}
|
||||
|
||||
std::string DidChangeProvider::GetProviderName() const
|
||||
{
|
||||
return "DidChangeProvider";
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./did_change_provider.hpp"
|
||||
#include "./did_open_provider.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidChangeProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("DidChangeProvider: Providing response for method {}", request.method);
|
||||
std::string json;
|
||||
glz::obj empty_obj{}; // glaze的对象类型
|
||||
auto ec = glz::write_json(empty_obj, json);
|
||||
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
|
||||
}
|
||||
|
||||
std::string DidChangeProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didChange";
|
||||
}
|
||||
|
||||
std::string DidChangeProvider::GetProviderName() const
|
||||
{
|
||||
return "DidChangeProvider";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidChangeProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
DidChangeProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidChangeProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
DidChangeProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./did_open_provider.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DidOpenProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("DidOpenProvider: Providing response for method {}", request.method);
|
||||
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;
|
||||
}
|
||||
|
||||
std::string DidOpenProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didOpen";
|
||||
}
|
||||
|
||||
std::string DidOpenProvider::GetProviderName() const
|
||||
{
|
||||
return "DidOpenProvider";
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./did_open_provider.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DidOpenProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("DidOpenProvider: Providing response for method {}", request.method);
|
||||
std::string json;
|
||||
glz::obj empty_obj{}; // glaze的对象类型
|
||||
auto ec = glz::write_json(empty_obj, json);
|
||||
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
|
||||
}
|
||||
|
||||
std::string DidOpenProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didOpen";
|
||||
}
|
||||
|
||||
std::string DidOpenProvider::GetProviderName() const
|
||||
{
|
||||
return "DidOpenProvider";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidOpenProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
DidOpenProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidOpenProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
DidOpenProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./set_trace_provider.hpp"
|
||||
|
||||
namespace lsp::providers::trace
|
||||
{
|
||||
|
||||
std::string SetTraceProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("SetTraceProvider: Providing response for method {}", request.method);
|
||||
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;
|
||||
}
|
||||
|
||||
std::string SetTraceProvider::GetMethod() const
|
||||
{
|
||||
return "$/setTrace";
|
||||
}
|
||||
|
||||
std::string SetTraceProvider::GetProviderName() const
|
||||
{
|
||||
return "SetTraceProvider";
|
||||
}
|
||||
|
||||
}
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "./set_trace_provider.hpp"
|
||||
|
||||
namespace lsp::providers::trace
|
||||
{
|
||||
|
||||
std::string SetTraceProvider::ProvideResponse(const protocol::RequestMessage& request)
|
||||
{
|
||||
spdlog::debug("SetTraceProvider: Providing response for method {}", request.method);
|
||||
std::string json;
|
||||
glz::obj empty_obj{}; // glaze的对象类型
|
||||
auto ec = glz::write_json(empty_obj, json);
|
||||
return ec ? BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error") : json;
|
||||
}
|
||||
|
||||
std::string SetTraceProvider::GetMethod() const
|
||||
{
|
||||
return "$/setTrace";
|
||||
}
|
||||
|
||||
std::string SetTraceProvider::GetProviderName() const
|
||||
{
|
||||
return "SetTraceProvider";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::trace
|
||||
{
|
||||
class SetTraceProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
SetTraceProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::trace
|
||||
{
|
||||
class SetTraceProvider : public ILspProvider
|
||||
{
|
||||
public:
|
||||
SetTraceProvider() = default;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user