重构语法树/符号表

This commit is contained in:
csh
2025-10-15 20:31:00 +08:00
parent f52768e385
commit 1f7045140e
113 changed files with 229450 additions and 221041 deletions
File diff suppressed because it is too large Load Diff
@@ -2,43 +2,75 @@
#include <string>
#include <vector>
#include "../base/interface.hpp"
#include "../../service/detail/symbol/symbol_types.hpp"
#include "../../service/detail/symbol/types.hpp"
#include "../../language/symbol/core/symbol.hpp"
#include "../../service/symbol.hpp"
namespace lsp::provider::text_document
{
struct CompletionContext
{
protocol::DocumentUri uri;
protocol::Position position;
std::string prefix;
std::string line_content;
std::string object_name;
bool is_member_access = false;
bool is_constructor = false;
};
enum class CompletionSource
{
kEditing, // 当前编辑文档
kWorkspace, // 工作区符号
kSystem, // 系统库符号
kKeyword // 关键字
};
struct SourcedCompletionItem
{
protocol::CompletionItem item;
CompletionSource source;
};
namespace context_analyzer
{
CompletionContext Analyze(const protocol::CompletionParams& params, const std::optional<std::string>& document_content);
bool IsConstructorContext(const std::string& line);
bool IsMemberAccess(const std::string& line);
std::string ExtractPrefix(size_t cursor_pos, size_t line_start, const std::string& content);
std::string ExtractMemberPrefix(const std::string& line);
std::string ExtractConstructorPrefix(const std::string& line);
std::string ExtractObjectName(const std::string& line);
}
class Completion : public IRequestProvider
{
public:
std::string GetMethod() const override;
std::string GetProviderName() const override;
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& execution_context) override;
private:
struct CompletionContext
{
protocol::DocumentUri uri;
protocol::Position position;
std::string prefix;
std::string line_context;
std::string object_name;
bool is_member_access = false;
bool is_constructor_context = false;
};
protocol::CompletionList BuildCompletionList(const protocol::CompletionParams& params, ExecutionContext& execution_context);
protocol::CompletionList BuildCompletionResponse(const protocol::CompletionParams& params, ExecutionContext& context);
std::vector<protocol::CompletionItem> ProvideKeywordCompletions(const std::string& prefix);
std::vector<protocol::CompletionItem> ProvideFunctionCompletions(const CompletionContext& context, ExecutionContext& exec_context);
// 符号收集
std::vector<SourcedCompletionItem> CollectKeywords(const std::string& prefix);
std::vector<SourcedCompletionItem> CollectEditingSymbols(const CompletionContext& comp_context, const service::Symbol& symbol_service);
std::vector<SourcedCompletionItem> CollectWorkspaceFunctions(const CompletionContext& comp_context, const service::Symbol& symbol_service);
std::vector<SourcedCompletionItem> CollectSystemFunctions(const CompletionContext& comp_context, const service::Symbol& symbol_service);
std::vector<SourcedCompletionItem> CollectMemberSymbols(const CompletionContext& comp_context, const service::Symbol& symbol_service);
std::vector<SourcedCompletionItem> CollectClassNames(const CompletionContext& comp_context, const service::Symbol& symbol_service);
CompletionContext ExtractCompletionContext(const protocol::CompletionParams& params, ExecutionContext& context);
std::string ExtractPrefix(size_t cursor_pos, size_t line_start, const std::string& content);
std::string ExtractMemberPrefix(const std::string& line);
std::string ExtractConstructorPrefix(const std::string& line);
std::string ExtractObjectName(const std::string& line);
bool DetectConstructorContext(const std::string& line);
bool DetectMemberAccess(const std::string& line);
void AppendCompletions(std::vector<protocol::CompletionItem>& target, const std::vector<protocol::CompletionItem>& source);
std::vector<protocol::CompletionItem> FilterAndSortCompletions(const std::vector<protocol::CompletionItem>& items, const std::string& prefix);
// 过滤和排序
std::vector<protocol::CompletionItem> FilterAndSort(const std::vector<SourcedCompletionItem>& items, const std::string& prefix);
static int GetMatchScore(const std::string& label, const std::string& prefix);
static std::string BuildFunctionSignature(const service::SymbolInfo& symbol);
// 格式化辅助
static protocol::CompletionItemKind ToCompletionItemKind(const language::symbol::Symbol* symbol);
static protocol::CompletionItemKind ToCompletionItemKind(service::SymbolKind kind);
static std::string FormatSymbolSignature(const language::symbol::Symbol* symbol);
static std::string FormatSignature(const service::SymbolSignature& sig);
};
}
@@ -50,230 +50,6 @@ namespace lsp::provider::text_document
std::optional<protocol::Location> Definition::BuildDefinitionResponse(const protocol::DefinitionParams& params, ExecutionContext& context)
{
spdlog::trace("{}: Processing definition request for URI='{}', Position=({}, {})", GetProviderName(), params.textDocument.uri, params.position.line, params.position.character);
auto location = FindLocalDefinition(params.textDocument.uri, params.position, context);
if (!location.has_value())
{
std::string identifier = GetIdentifierAtPosition(
params.textDocument.uri, params.position, context);
if (!identifier.empty())
{
// TODO: 在外部文档查找(通过uses语句导入的unit)
spdlog::debug("{}: Looking for '{}' in imported units", GetProviderName(), identifier);
}
}
if (location.has_value())
{
spdlog::info("{}: Found definition at {}:{}:{}", GetProviderName(), location->uri, location->range.start.line, location->range.start.character);
}
else
{
spdlog::info("{}: No definition found", GetProviderName());
}
return location;
}
std::optional<protocol::Location> Definition::FindLocalDefinition(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)
{
spdlog::warn("{}: Document not found or no syntax tree: {}", GetProviderName(), uri);
return std::nullopt;
}
std::string identifier = GetIdentifierAtPosition(uri, position, context);
if (identifier.empty())
{
spdlog::debug("{}: No identifier at position", GetProviderName());
return std::nullopt;
}
spdlog::debug("{}: Looking for definition of '{}'", GetProviderName(), identifier);
TSNode root = ts_tree_root_node(tree);
// 如果是unit,需要特殊处理
const char* root_type = ts_node_type(root);
if (strcmp(root_type, kUnit) == 0)
{
// 优先在interface section查找(公开声明)
TSNode interface_node = ts_node_child_by_field_name(root, "interface", 9);
if (!ts_node_is_null(interface_node))
{
TSNode definition_node = FindDefinitionNode(interface_node, identifier, *content);
if (!ts_node_is_null(definition_node))
{
TSPoint start = ts_node_start_point(definition_node);
TSPoint end = ts_node_end_point(definition_node);
protocol::Location location;
location.uri = uri;
location.range.start.line = start.row;
location.range.start.character = start.column;
location.range.end.line = end.row;
location.range.end.character = end.column;
return location;
}
}
// 然后在implementation section查找
TSNode impl_node = ts_node_child_by_field_name(root, "implementation", 14);
if (!ts_node_is_null(impl_node))
{
TSNode definition_node = FindDefinitionNode(impl_node, identifier, *content);
if (!ts_node_is_null(definition_node))
{
TSPoint start = ts_node_start_point(definition_node);
TSPoint end = ts_node_end_point(definition_node);
protocol::Location location;
location.uri = uri;
location.range.start.line = start.row;
location.range.start.character = start.column;
location.range.end.line = end.row;
location.range.end.character = end.column;
return location;
}
}
}
else
{
// 普通文档,直接查找
TSNode definition_node = FindDefinitionNode(root, identifier, *content);
if (!ts_node_is_null(definition_node))
{
TSPoint start = ts_node_start_point(definition_node);
TSPoint end = ts_node_end_point(definition_node);
protocol::Location location;
location.uri = uri;
location.range.start.line = start.row;
location.range.start.character = start.column;
location.range.end.line = end.row;
location.range.end.character = end.column;
return location;
}
}
return std::nullopt;
}
std::string Definition::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 "";
}
TSNode Definition::FindDefinitionNode(TSNode node, const std::string& identifier, const std::string& content)
{
const char* node_type = ts_node_type(node);
// 检查是否是定义节点
if (strcmp(node_type, kFunctionDefinition) == 0 ||
strcmp(node_type, kFunctionDeclaration) == 0 ||
strcmp(node_type, kClassDefinition) == 0 ||
strcmp(node_type, kMethodWithImplementation) == 0)
{
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
if (!ts_node_is_null(name_node))
{
uint32_t start = ts_node_start_byte(name_node);
uint32_t end = ts_node_end_byte(name_node);
std::string name = content.substr(start, end - start);
if (name == identifier)
{
return name_node;
}
}
}
else if (strcmp(node_type, kVarStatement) == 0 || strcmp(node_type, kConstStatement) == 0)
{
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
if (!ts_node_is_null(name_node))
{
uint32_t start = ts_node_start_byte(name_node);
uint32_t end = ts_node_end_byte(name_node);
std::string name = content.substr(start, end - start);
if (name == identifier)
{
return name_node;
}
}
}
// 递归查找子节点
uint32_t child_count = ts_node_child_count(node);
for (uint32_t i = 0; i < child_count; i++)
{
TSNode child = ts_node_child(node, i);
TSNode result = FindDefinitionNode(child, identifier, content);
if (!ts_node_is_null(result))
{
return result;
}
}
return TSNode{};
}
}
@@ -22,8 +22,8 @@ namespace lsp::provider::text_document
protocol::DidChangeTextDocumentParams params = transform::As<protocol::DidChangeTextDocumentParams>(notification.params.value());
service::Document& document_service = context.GetService<service::Document>();
document_service.UpdateDocument(params);
auto document_service = context.GetService<service::Document>();
document_service->UpdateDocument(params);
spdlog::info("Document updated: {}", params.textDocument.uri);
}
@@ -20,12 +20,12 @@ namespace lsp::provider::text_document
{
spdlog::debug("TextDocumentDidCloseProvider: Providing response for method {}", notification.method);
protocol::DidCloseTextDocumentParams did_close_text_document_params = transform::As<protocol::DidCloseTextDocumentParams>(notification.params.value());
protocol::DidCloseTextDocumentParams params = transform::As<protocol::DidCloseTextDocumentParams>(notification.params.value());
service::Document& document_service = context.GetService<service::Document>();
document_service.CloseDocument(did_close_text_document_params);
auto document_service = context.GetService<service::Document>();
document_service->CloseDocument(params);
spdlog::info("Document closed: {}", did_close_text_document_params.textDocument.uri);
spdlog::info("Document closed: {}", params.textDocument.uri);
}
}
@@ -19,10 +19,10 @@ namespace lsp::provider::text_document
{
spdlog::debug("TextDocumentDidOpenProvider: Providing response for method {}", notification.method);
protocol::DidOpenTextDocumentParams did_open_text_document_params = transform::As<protocol::DidOpenTextDocumentParams>(notification.params.value());
protocol::DidOpenTextDocumentParams params = transform::As<protocol::DidOpenTextDocumentParams>(notification.params.value());
service::Document& document_service = context.GetService<service::Document>();
document_service.OpenDocument(did_open_text_document_params);
auto document_service = context.GetService<service::Document>();
document_service->OpenDocument(params);
/*
if (auto* symbolService = context.TryGetService<SymbolService>()) {
@@ -34,7 +34,7 @@ namespace lsp::provider::text_document
diagnosticService->diagnose(uri);
}
*/
spdlog::info("Document opened: {}", did_open_text_document_params.textDocument.uri);
spdlog::info("Document opened: {}", params.textDocument.uri);
}
}
@@ -17,12 +17,12 @@ namespace lsp::provider::text_document
std::string DocumentSymbol::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
{
spdlog::debug("TextDocumentDocumentSymbolProvider: Providing response for method {}", request.method);
// TODO: Implement the actual request handling logic
// 1. Parse request parameters
// 2. Process the request using appropriate services
// 3. Return formatted response
return "{}"; // Placeholder response
}
}