tsl-devkit/lsp-server/src/provider/text_document/completion_provider.cpp

160 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
}