Files
tsl-devkit/lsp-server/src/provider/text_document/references.cpp
T
2025-09-27 22:23:04 +08:00

146 lines
4.9 KiB
C++

#include <spdlog/spdlog.h>
#include "./references.hpp"
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"
namespace lsp::provider::text_document
{
std::string References::GetMethod() const
{
return "textDocument/references";
}
std::string References::GetProviderName() const
{
return "TextDocumentReferences";
}
std::string References::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
{
spdlog::debug("TextDocumentReferencesProvider: Providing response for method {}", request.method);
if (!request.params.has_value())
{
spdlog::warn("{}: Missing params in request", GetProviderName());
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
}
protocol::ReferenceParams params =
transform::As<protocol::ReferenceParams>(request.params.value());
auto locations = BuildReferencesResponse(params, context);
protocol::ResponseMessage response;
response.id = request.id;
if (!locations.empty())
response.result = transform::LSPAny(locations);
else
response.result = transform::LSPAny(std::vector<protocol::Location>{});
std::optional<std::string> json = transform::Serialize(response);
if (!json.has_value())
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Failed to serialize response");
return json.value();
}
std::vector<protocol::Location> References::BuildReferencesResponse(const protocol::ReferenceParams& params, ExecutionContext& context)
{
spdlog::trace("{}: Processing references request for URI='{}', Position=({}, {})",
GetProviderName(),
params.textDocument.uri,
params.position.line,
params.position.character);
std::string identifier = GetIdentifierAtPosition(
params.textDocument.uri, params.position, context);
if (identifier.empty())
{
spdlog::info("{}: No identifier at position", GetProviderName());
return {};
}
spdlog::debug("{}: Looking for references of '{}'", GetProviderName(), identifier);
auto locations = FindReferences(params.textDocument.uri, identifier, params.context.includeDeclaration, context);
spdlog::info("{}: Found {} references", GetProviderName(), locations.size());
return locations;
}
std::vector<protocol::Location> References::FindReferences(const protocol::DocumentUri& uri, const std::string& identifier, bool include_declaration, ExecutionContext& context)
{
std::vector<protocol::Location> locations;
// 从容器获取文档服务
auto& document_service = context.GetService<service::Document>();
auto content = document_service.GetContent(uri);
auto tree = document_service.GetSyntaxTree(uri);
if (!content.has_value() || !tree)
{
spdlog::warn("{}: Document not found or no syntax tree: {}", GetProviderName(), uri);
return locations;
}
TSNode root = ts_tree_root_node(tree);
FindReferencesInNode(root, identifier, *content, uri, locations, include_declaration);
return locations;
}
std::string References::GetIdentifierAtPosition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context)
{
auto& document_service = context.GetService<service::Document>();
auto content = document_service.GetContent(uri);
auto tree = document_service.GetSyntaxTree(uri);
if (!content.has_value() || !tree)
return "";
size_t byte_offset = 0;
size_t current_line = 0;
size_t current_col = 0;
for (size_t i = 0; i < content->length(); i++)
{
if (current_line == position.line && current_col == position.character)
{
byte_offset = i;
break;
}
if ((*content)[i] == '\n')
{
current_line++;
current_col = 0;
}
else
{
current_col++;
}
}
TSNode root = ts_tree_root_node(tree);
TSNode node = ts_node_descendant_for_byte_range(root, byte_offset, byte_offset);
while (!ts_node_is_null(node))
{
const char* node_type = ts_node_type(node);
if (strcmp(node_type, kIdentifier) == 0)
{
uint32_t start = ts_node_start_byte(node);
uint32_t end = ts_node_end_byte(node);
return content->substr(start, end - start);
}
node = ts_node_parent(node);
}
return "";
}
}