重构语法树/符号表
This commit is contained in:
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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user