支持全局函数补全

This commit is contained in:
csh
2025-09-27 22:23:04 +08:00
parent aac12137cb
commit dc713e6893
220 changed files with 195514 additions and 195869 deletions
@@ -1,39 +1,42 @@
#include <spdlog/spdlog.h>
#include "./provider_registry.hpp"
#include "../initialize/initialize.hpp"
#include "../initialized/initialized.hpp"
#include "../text_document/did_open.hpp"
#include "../text_document/did_change.hpp"
#include "../text_document/did_close.hpp"
#include "../text_document/completion.hpp"
#include "../text_document/semantic_tokens.hpp"
#include "../trace/set_trace.hpp"
#include "../shutdown/shutdown.hpp"
#include "../cancel_request/cancel_request.hpp"
#include "../exit/exit.hpp"
namespace lsp::providers
{
void RegisterAllProviders(core::RequestDispatcher& dispatcher)
{
spdlog::info("Registering LSP providers...");
RegisterProvider<Initialize>(dispatcher);
RegisterProvider<Initialized>(dispatcher);
RegisterProvider<text_document::DidOpen>(dispatcher);
RegisterProvider<text_document::DidChange>(dispatcher);
RegisterProvider<text_document::DidClose>(dispatcher);
RegisterProvider<text_document::Completion>(dispatcher);
RegisterProvider<text_document::SemanticTokensRange>(dispatcher);
RegisterProvider<text_document::SemanticTokensFull>(dispatcher);
RegisterProvider<text_document::SemanticTokensFullDelta>(dispatcher);
RegisterProvider<SetTrace>(dispatcher);
RegisterProvider<Shutdown>(dispatcher);
RegisterProvider<CancelRequest>(dispatcher);
RegisterProvider<Exit>(dispatcher);
spdlog::info("Successfully registered {} LSP providers", dispatcher.GetAllSupportedMethods().size());
}
}
#include <spdlog/spdlog.h>
#include "../initialize/initialize.hpp"
#include "../initialized/initialized.hpp"
#include "../text_document/did_open.hpp"
#include "../text_document/did_change.hpp"
#include "../text_document/did_close.hpp"
#include "../text_document/completion.hpp"
// #include "../text_document/semantic_tokens.hpp"
#include "../trace/set_trace.hpp"
#include "../shutdown/shutdown.hpp"
#include "../cancel_request/cancel_request.hpp"
#include "../exit/exit.hpp"
#include "../completion_item/resolve.hpp"
#include "./registry.hpp"
#include "./bootstrap.hpp"
namespace lsp::provider
{
void RegisterAllProviders(core::RequestDispatcher& dispatcher)
{
spdlog::info("Registering LSP providers...");
RegisterProvider<Initialize>(dispatcher);
RegisterProvider<Initialized>(dispatcher);
RegisterProvider<text_document::DidOpen>(dispatcher);
RegisterProvider<text_document::DidChange>(dispatcher);
RegisterProvider<text_document::DidClose>(dispatcher);
RegisterProvider<text_document::Completion>(dispatcher);
// RegisterProvider<text_document::SemanticTokensRange>(dispatcher);
// RegisterProvider<text_document::SemanticTokensFull>(dispatcher);
// RegisterProvider<text_document::SemanticTokensFullDelta>(dispatcher);
RegisterProvider<completion_item::Resolve>(dispatcher);
RegisterProvider<SetTrace>(dispatcher);
RegisterProvider<Shutdown>(dispatcher);
RegisterProvider<CancelRequest>(dispatcher);
RegisterProvider<Exit>(dispatcher);
spdlog::info("Successfully registered {} LSP providers", dispatcher.GetAllSupportedMethods().size());
}
}
@@ -0,0 +1,9 @@
#pragma once
#include <spdlog/spdlog.h>
#include "../../core/dispacther.hpp"
namespace lsp::provider
{
// 批量注册provider
void RegisterAllProviders(core::RequestDispatcher& dispatcher);
}
@@ -1,22 +1,22 @@
#include "./provider_interface.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers
{
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCodes 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::optional<std::string> json = transform::Serialize(response);
if (json.has_value())
return json.value();
spdlog::error("Failed to serialize error response.");
return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})";
}
}
#include "./interface.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::provider
{
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCodes 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::optional<std::string> json = transform::Serialize(response);
if (json.has_value())
return json.value();
spdlog::error("Failed to serialize error response.");
return R"({"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"Failed to serialize error response"}})";
}
}
@@ -1,80 +1,80 @@
#pragma once
#include <string>
#include <spdlog/spdlog.h>
#include "../../scheduler/request.hpp"
#include "../../service/base/container.hpp"
#include "../../protocol/protocol.hpp"
namespace lsp::providers
{
enum class ServerLifecycleEvent
{
kInitializing,
kInitialized,
kInitializeFailed,
kShuttingDown,
kShutdown
};
using LifecycleCallback = std::function<void(ServerLifecycleEvent)>;
class ExecutionContext
{
public:
ExecutionContext(LifecycleCallback lifecycle_callback, scheduler::Request& scheduler, service::Container& container) :
lifecycle_callback_(lifecycle_callback), request_scheduler_(scheduler), service_container_(container) {}
scheduler::Request& GetScheduler() const { return request_scheduler_; }
template<typename T>
T& GetService() const
{
return service_container_.GetService<T>();
}
void TriggerLifecycleEvent(ServerLifecycleEvent event) const
{
if (lifecycle_callback_)
lifecycle_callback_(event);
}
private:
LifecycleCallback lifecycle_callback_;
scheduler::Request& request_scheduler_;
service::Container& service_container_;
};
// LSP请求提供者接口基类
class IProvider
{
public:
virtual ~IProvider() = default;
// 获取支持的LSP方法名
virtual std::string GetMethod() const = 0;
// 获取提供者名称(用于日志和调试)
virtual std::string GetProviderName() const = 0;
};
// LSP 请求处理器接口
class IRequestProvider : public IProvider
{
public:
virtual ~IRequestProvider() = default;
// 处理LSP请求
virtual std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) = 0;
};
// LSP 通知处理器接口
class INotificationProvider : public IProvider
{
public:
virtual ~INotificationProvider() = default;
// 处理LSP通知
virtual void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) = 0;
};
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message);
}
#pragma once
#include <string>
#include <spdlog/spdlog.h>
#include "../../scheduler/request.hpp"
#include "../../service/base/registry.hpp"
#include "../../protocol/protocol.hpp"
namespace lsp::provider
{
enum class ServerLifecycleEvent
{
kInitializing,
kInitialized,
kInitializeFailed,
kShuttingDown,
kShutdown
};
using LifecycleCallback = std::function<void(ServerLifecycleEvent)>;
class ExecutionContext
{
public:
ExecutionContext(LifecycleCallback lifecycle_callback, scheduler::Request& scheduler, service::Registry& registry) :
lifecycle_callback_(lifecycle_callback), request_scheduler_(scheduler), service_registry_(registry) {}
scheduler::Request& GetScheduler() const { return request_scheduler_; }
template<typename T>
T& GetService() const
{
return service_registry_.GetService<T>();
}
void TriggerLifecycleEvent(ServerLifecycleEvent event) const
{
if (lifecycle_callback_)
lifecycle_callback_(event);
}
private:
LifecycleCallback lifecycle_callback_;
scheduler::Request& request_scheduler_;
service::Registry& service_registry_;
};
// LSP请求提供者接口基类
class IProvider
{
public:
virtual ~IProvider() = default;
// 获取支持的LSP方法名
virtual std::string GetMethod() const = 0;
// 获取提供者名称(用于日志和调试)
virtual std::string GetProviderName() const = 0;
};
// LSP 请求处理器接口
class IRequestProvider : public IProvider
{
public:
virtual ~IRequestProvider() = default;
// 处理LSP请求
virtual std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) = 0;
};
// LSP 通知处理器接口
class INotificationProvider : public IProvider
{
public:
virtual ~INotificationProvider() = default;
// 处理LSP通知
virtual void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) = 0;
};
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message);
}
@@ -1,32 +1,29 @@
#pragma once
#include <spdlog/spdlog.h>
#include <type_traits>
#include "../../core/dispacther.hpp"
#include "./provider_interface.hpp"
namespace lsp::providers
{
// 注册请求处理器的模板函数
template<typename ProviderClass>
typename std::enable_if_t<std::is_base_of_v<IRequestProvider, ProviderClass>>
RegisterProvider(core::RequestDispatcher& dispatcher)
{
auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterRequestProvider(provider);
spdlog::info("Registered request provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
}
// 注册通知处理器的模板函数
template<typename ProviderClass>
typename std::enable_if_t<std::is_base_of_v<INotificationProvider, ProviderClass>>
RegisterProvider(core::RequestDispatcher& dispatcher)
{
auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterNotificationProvider(provider);
spdlog::info("Registered notification provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
}
// 批量注册provider
void RegisterAllProviders(core::RequestDispatcher& dispatcher);
}
#pragma once
#include <spdlog/spdlog.h>
#include <type_traits>
#include "../../core/dispacther.hpp"
#include "./interface.hpp"
namespace lsp::provider
{
// 注册请求处理器的模板函数
template<typename ProviderClass>
typename std::enable_if_t<std::is_base_of_v<IRequestProvider, ProviderClass>>
RegisterProvider(core::RequestDispatcher& dispatcher)
{
auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterRequestProvider(provider);
spdlog::info("Registered request provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
}
// 注册通知处理器的模板函数
template<typename ProviderClass>
typename std::enable_if_t<std::is_base_of_v<INotificationProvider, ProviderClass>>
RegisterProvider(core::RequestDispatcher& dispatcher)
{
auto provider = std::make_shared<ProviderClass>();
dispatcher.RegisterNotificationProvider(provider);
spdlog::info("Registered notification provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
}
}
@@ -2,7 +2,7 @@
#include "./incoming_calls.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::call_hierarchy
namespace lsp::provider::call_hierarchy
{
std::string IncomingCalls::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::call_hierarchy
namespace lsp::provider::call_hierarchy
{
class IncomingCalls : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./outgoing_calls.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::call_hierarchy
namespace lsp::provider::call_hierarchy
{
std::string OutgoingCalls::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::call_hierarchy
namespace lsp::provider::call_hierarchy
{
class OutgoingCalls : public IRequestProvider
{
@@ -1,6 +1,6 @@
#include "./cancel_request.hpp"
namespace lsp::providers
namespace lsp::provider
{
std::string CancelRequest::GetMethod() const
{
@@ -1,9 +1,9 @@
#pragma once
#include <spdlog/spdlog.h>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers
namespace lsp::provider
{
class CancelRequest : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./register_capability.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::client
namespace lsp::provider::client
{
std::string RegisterCapability::GetMethod() const
{
@@ -1,9 +1,9 @@
#pragma once
#include <string>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
#include "../../protocol/protocol.hpp"
namespace lsp::providers::client
namespace lsp::provider::client
{
class RegisterCapability : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./unregister_capability.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::client
namespace lsp::provider::client
{
std::string UnregisterCapability::GetMethod() const
{
@@ -1,9 +1,9 @@
#pragma once
#include <string>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
#include "../../protocol/protocol.hpp"
namespace lsp::providers::client
namespace lsp::provider::client
{
class UnregisterCapability : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./resolve.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::code_action
namespace lsp::provider::code_action
{
std::string Resolve::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::code_action
namespace lsp::provider::code_action
{
class Resolve : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./resolve.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::code_lens
namespace lsp::provider::code_lens
{
std::string Resolve::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::code_lens
namespace lsp::provider::code_lens
{
class Resolve : public IRequestProvider
{
@@ -1,10 +1,10 @@
#include <spdlog/spdlog.h>
#include "./resolve.hpp"
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
#include "../../language/keyword_manager.hpp"
#include "../../service/symbol.hpp"
#include "../../protocol/transform/facade.hpp"
#include "./resolve.hpp"
namespace lsp::providers::completion_item
namespace lsp::provider::completion_item
{
std::string Resolve::GetMethod() const
{
@@ -26,13 +26,9 @@ namespace lsp::providers::completion_item
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
}
// 解析补全项参数
protocol::CompletionItem item = transform::As<protocol::CompletionItem>(request.params.value());
// 解析补全项,添加详细信息
protocol::CompletionItem resolved_item = ResolveCompletionItem(item, context);
// 构建响应
protocol::ResponseMessage response;
response.id = request.id;
response.result = transform::LSPAny(resolved_item);
@@ -43,279 +39,93 @@ namespace lsp::providers::completion_item
return json.value();
}
protocol::CompletionItem Resolve::ResolveCompletionItem(
const protocol::CompletionItem& item,
ExecutionContext& context)
protocol::CompletionItem Resolve::ResolveCompletionItem(const protocol::CompletionItem& item, ExecutionContext& context)
{
spdlog::trace("{}: Resolving completion item '{}'", GetProviderName(), item.label);
// 复制原始项
protocol::CompletionItem resolved = item;
// 如果已经有详细信息,直接返回
if (resolved.documentation.has_value() && resolved.detail.has_value())
if (auto keyword_info = tsl::KeywordManager::GetInstance().GetKeywordInfo(item.label))
{
spdlog::debug("{}: Item '{}' already resolved", GetProviderName(), item.label);
return resolved;
protocol::MarkupContent content;
content.kind = protocol::MarkupKindLiterals::Markdown;
content.value = keyword_info->description;
resolved.documentation = content;
}
// 根据补全项类型添加详细信息
if (!resolved.detail.has_value())
else if (auto symbol_info = context.GetService<service::Symbol>().GetGlobalFunction(item.label))
{
resolved.detail = GetDetailedSignature(item.label,
item.kind.value_or(protocol::CompletionItemKind::kText),
context);
protocol::MarkupContent content;
content.kind = protocol::MarkupKindLiterals::Markdown;
std::stringstream ss;
ss << "#### from\n\n";
ss << symbol_info->file_path << "\n\n";
ss << "---\n\n";
content.value = ss.str() + GeneratorFunctionMarkdown(symbol_info->symbols[0]);
resolved.documentation = content;
resolved.insertText = GenerateFunctionSnippet(symbol_info->symbols[0]);
resolved.insertTextFormat = protocol::InsertTextFormat::kSnippet;
}
// 添加文档
if (!resolved.documentation.has_value())
{
std::string doc = GetDocumentationForItem(resolved, context);
if (!doc.empty())
{
protocol::MarkupContent markup;
markup.kind = protocol::MarkupKindLiterals::Markdown;
markup.value = doc;
resolved.documentation = markup;
}
}
// 添加额外的编辑信息(如自动导入)
if (item.kind == protocol::CompletionItemKind::kClass ||
item.kind == protocol::CompletionItemKind::kFunction)
{
// TODO: 检查是否需要添加 uses 语句
// 如果符号来自其他单元,可能需要自动添加导入
}
spdlog::info("{}: Resolved item '{}' with {} documentation",
GetProviderName(),
item.label,
resolved.documentation.has_value() ? "added" : "no");
return resolved;
}
std::string Resolve::GetDocumentationForItem(
const protocol::CompletionItem& item,
ExecutionContext& context)
protocol::string Resolve::GeneratorFunctionMarkdown(const service::SymbolInfo& symbol_info)
{
std::stringstream doc;
doc << "#### function\n\n";
doc << "`" << symbol_info.name << "`";
doc << "\n\n";
// 根据类型获取文档
if (item.kind == protocol::CompletionItemKind::kKeyword)
// 参数
if (symbol_info.callable && !symbol_info.callable->parameters.empty())
{
// 关键字文档
std::string keyword_doc = GetKeywordDocumentation(item.label);
if (!keyword_doc.empty())
doc << "##### parameters:\n";
for (const auto& param : symbol_info.callable->parameters)
{
doc << keyword_doc;
}
}
else if (item.kind == protocol::CompletionItemKind::kFunction ||
item.kind == protocol::CompletionItemKind::kMethod)
{
// 函数/方法文档
auto builtin_it = kBuiltinFunctions.find(item.label);
if (builtin_it != kBuiltinFunctions.end())
{
doc << builtin_it->second;
}
else
{
// 查找用户定义的函数
auto symbol = FindSymbolDetails(item.label, context);
if (symbol.has_value())
{
doc << "**" << item.label << "**\n\n";
if (symbol->detail.has_value())
{
doc << "Signature: `" << symbol->detail.value() << "`\n\n";
}
doc << "User-defined function";
}
doc << "- `" << param.name << "`";
// 添加代码示例
std::string example = GenerateCodeExample(item.label, *item.kind);
if (!example.empty())
{
doc << "\n\n**Example:**\n```tsf\n"
<< example << "\n```";
}
// 类型
if (param.typed && !param.typed->type_name.empty())
doc << ": `" << param.typed->type_name << "`";
doc << "\n";
}
doc << "\n";
}
else if (item.kind == protocol::CompletionItemKind::kClass)
{
// 类文档
auto symbol = FindSymbolDetails(item.label, context);
if (symbol.has_value())
{
doc << "**" << item.label << "** (class)\n\n";
// 列出公共成员
if (!symbol->children.value().empty())
{
doc << "**Members:**\n";
for (const auto& child : symbol->children.value())
{
if (child.kind == protocol::SymbolKind::kMethod ||
child.kind == protocol::SymbolKind::kProperty ||
child.kind == protocol::SymbolKind::kField)
{
doc << "- " << child.name;
if (child.detail.has_value())
{
doc << ": " << child.detail.value();
}
doc << "\n";
}
}
}
}
}
else if (item.kind == protocol::CompletionItemKind::kVariable ||
item.kind == protocol::CompletionItemKind::kConstant)
// 返回值
if (symbol_info.callable && symbol_info.callable->return_type)
{
// 变量/常量文档
auto symbol = FindSymbolDetails(item.label, context);
if (symbol.has_value())
{
doc << "**" << item.label << "**";
if (item.kind == protocol::CompletionItemKind::kConstant)
{
doc << " (constant)";
}
else
{
doc << " (variable)";
}
doc << "\n\n";
if (symbol->detail.has_value())
{
doc << "Type: `" << symbol->detail.value() << "`";
}
}
}
else if (item.kind == protocol::CompletionItemKind::kSnippet)
{
// 代码片段文档
doc << "**Code Snippet**\n\n";
doc << "Inserts a " << item.label << " code structure.\n\n";
doc << "Tab through the placeholders to fill in the values.";
doc << "##### return\n\n";
doc << "`" << *symbol_info.callable->return_type << "`\n\n";
}
return doc.str();
}
std::string Resolve::GetDetailedSignature(const std::string& name, protocol::CompletionItemKind kind, ExecutionContext& context)
protocol::string Resolve::GenerateFunctionSnippet(const service::SymbolInfo& symbol_info)
{
// 尝试从符号服务获取签名
auto symbol = FindSymbolDetails(name, context);
if (symbol.has_value() && symbol->detail.has_value())
std::stringstream snippet;
snippet << symbol_info.name << "(";
if (symbol_info.callable && !symbol_info.callable->parameters.empty())
{
return symbol->detail.value();
}
// 根据类型生成默认签名
switch (kind)
{
case protocol::CompletionItemKind::kFunction:
return name + "(params): ReturnType";
case protocol::CompletionItemKind::kMethod:
return name + "(params): ReturnType";
case protocol::CompletionItemKind::kClass:
return "class " + name;
case protocol::CompletionItemKind::kVariable:
return name + ": Type";
case protocol::CompletionItemKind::kConstant:
return "const " + name + " = value";
case protocol::CompletionItemKind::kProperty:
return "property " + name + ": Type";
default:
return "";
}
}
std::string Resolve::GenerateCodeExample(const std::string& name, protocol::CompletionItemKind kind)
{
std::stringstream example;
switch (kind)
{
case protocol::CompletionItemKind::kFunction:
case protocol::CompletionItemKind::kMethod:
example << "// Call " << name << "\n";
example << "result := " << name << "(param1, param2);";
break;
case protocol::CompletionItemKind::kClass:
example << "// Create instance of " << name << "\n";
example << "var obj: " << name << ";\n";
example << "obj := " << name << ".Create();";
break;
default:
// 不生成示例
break;
}
return example.str();
}
std::string Resolve::GetKeywordDocumentation(const std::string& keyword)
{
std::string lower_keyword = keyword;
std::transform(lower_keyword.begin(), lower_keyword.end(), lower_keyword.begin(), ::tolower);
auto it = kKeywordDocs.find(lower_keyword);
if (it != kKeywordDocs.end())
{
return it->second;
}
return "TSF language keyword";
}
std::optional<protocol::DocumentSymbol> Resolve::FindSymbolDetails(const std::string& name, ExecutionContext& context)
{
// 从符号服务查找详细信息
auto& symbol_service = context.GetService<service::Symbol>();
auto& document_service = context.GetService<service::Document>();
// 遍历所有文档查找符号
auto uris = document_service.GetAllDocumentUris();
for (const auto& uri : uris)
{
auto symbols = symbol_service.GetDocumentSymbols(uri);
// 递归查找匹配的符号
std::function<std::optional<protocol::DocumentSymbol>(const std::vector<protocol::DocumentSymbol>&)>
find_symbol = [&](const std::vector<protocol::DocumentSymbol>& symbol_list)
-> std::optional<protocol::DocumentSymbol> {
for (const auto& symbol : symbol_list)
{
if (symbol.name == name)
{
return symbol;
}
// 递归查找子符号
auto result = find_symbol(symbol.children.value());
if (result.has_value())
{
return result;
}
}
return std::nullopt;
};
auto result = find_symbol(symbols);
if (result.has_value())
const auto& params = symbol_info.callable->parameters;
for (size_t i = 0; i < params.size(); ++i)
{
return result;
if (i > 0)
snippet << ", ";
// 生成占位符 ${n:param_name}
snippet << "${" << (i + 1) << ":";
// 可选:包含类型提示
if (params[i].typed && !params[i].typed->type_name.empty())
snippet << params[i].name << ": " << params[i].typed->type_name;
else
snippet << params[i].name;
snippet << "}";
}
}
return std::nullopt;
snippet << ")$0"; // $0 是最终光标位置
return snippet.str();
}
}
@@ -1,8 +1,9 @@
#pragma once
#include <string>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
#include "../../service/detail/symbol/symbol_types.hpp"
namespace lsp::providers::completion_item
namespace lsp::provider::completion_item
{
class Resolve : public IRequestProvider
{
@@ -14,89 +15,9 @@ namespace lsp::providers::completion_item
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
private:
// 解析补全项,添加详细信息
protocol::CompletionItem ResolveCompletionItem(const protocol::CompletionItem& item, ExecutionContext& context);
// 根据补全项类型获取文档
std::string GetDocumentationForItem(const protocol::CompletionItem& item, ExecutionContext& context);
// 获取函数/方法的详细签名
std::string GetDetailedSignature(const std::string& name, protocol::CompletionItemKind kind, ExecutionContext& context);
// 生成代码示例
std::string GenerateCodeExample(const std::string& name, protocol::CompletionItemKind kind);
// 获取TSF关键字的详细说明
std::string GetKeywordDocumentation(const std::string& keyword);
// 查找符号的详细信息
std::optional<protocol::DocumentSymbol> FindSymbolDetails(const std::string& name, ExecutionContext& context);
static protocol::string GeneratorFunctionMarkdown(const service::SymbolInfo& symbol_info);
static protocol::string GenerateFunctionSnippet(const service::SymbolInfo& symbol_info);
};
namespace
{
// TSF关键字文档
const std::unordered_map<std::string, std::string> kKeywordDocs = {
{ "function", "Declares a function.\n\nSyntax:\n```tsf\nfunction name(params): return_type;\n```" },
{ "procedure", "Declares a procedure (function with no return value).\n\nSyntax:\n```tsf\nprocedure name(params);\n```" },
{ "begin", "Starts a block statement.\n\nUsed with: end" },
{ "end", "Ends a block statement, case statement, or unit.\n\nUsed with: begin, case, unit" },
{ "if", "Conditional statement.\n\nSyntax:\n```tsf\nif condition then\n statement\nelse\n statement\n```" },
{ "then", "Part of if-then statement.\n\nFollows the condition in an if statement." },
{ "else", "Alternative branch in conditional statement.\n\nUsed with: if-then" },
{ "for", "Loop statement.\n\nSyntax:\n```tsf\nfor i := start to end do\n statement\n```" },
{ "while", "While loop.\n\nSyntax:\n```tsf\nwhile condition do\n statement\n```" },
{ "repeat", "Repeat-until loop.\n\nSyntax:\n```tsf\nrepeat\n statements\nuntil condition;\n```" },
{ "until", "Loop termination condition.\n\nUsed with: repeat" },
{ "do", "Loop body indicator.\n\nUsed with: for, while" },
{ "case", "Case statement for multiple conditions.\n\nSyntax:\n```tsf\ncase expression of\n value1: statement;\n value2: statement;\nelse\n statement;\nend;\n```" },
{ "of", "Part of case statement.\n\nUsed with: case, array, set" },
{ "var", "Variable declaration.\n\nSyntax:\n```tsf\nvar name: type;\n```" },
{ "const", "Constant declaration.\n\nSyntax:\n```tsf\nconst name = value;\n```" },
{ "type", "Type declaration.\n\nSyntax:\n```tsf\ntype name = type_definition;\n```" },
{ "class", "Class declaration.\n\nSyntax:\n```tsf\ntype MyClass = class\n // members\nend;\n```" },
{ "unit", "Unit (module) declaration.\n\nSyntax:\n```tsf\nunit UnitName;\ninterface\n // public declarations\nimplementation\n // private implementation\nend.\n```" },
{ "interface", "Public section of a unit.\n\nContains declarations visible to other units." },
{ "implementation", "Private section of a unit.\n\nContains implementation details." },
{ "uses", "Import other units.\n\nSyntax:\n```tsf\nuses Unit1, Unit2, Unit3;\n```" },
{ "public", "Public access modifier.\n\nMembers are accessible from outside the class." },
{ "private", "Private access modifier.\n\nMembers are only accessible within the class." },
{ "protected", "Protected access modifier.\n\nMembers are accessible within the class and derived classes." },
{ "virtual", "Virtual method modifier.\n\nMethod can be overridden in derived classes." },
{ "override", "Override method modifier.\n\nMethod overrides a virtual method from base class." },
{ "inherited", "Call inherited method.\n\nSyntax:\n```tsf\ninherited MethodName(params);\n```" },
{ "property", "Property declaration.\n\nSyntax:\n```tsf\nproperty Name: Type read GetMethod write SetMethod;\n```" },
{ "true", "Boolean literal.\n\nRepresents logical true value." },
{ "false", "Boolean literal.\n\nRepresents logical false value." },
{ "nil", "Null pointer value.\n\nRepresents an uninitialized or empty reference." },
{ "self", "Reference to current object instance.\n\nUsed within class methods." },
{ "and", "Logical AND operator.\n\nReturns true if both operands are true." },
{ "or", "Logical OR operator.\n\nReturns true if at least one operand is true." },
{ "not", "Logical NOT operator.\n\nInverts the boolean value." },
{ "div", "Integer division operator.\n\nReturns integer quotient." },
{ "mod", "Modulo operator.\n\nReturns remainder of division." },
{ "shl", "Shift left operator.\n\nShifts bits to the left." },
{ "shr", "Shift right operator.\n\nShifts bits to the right." },
{ "break", "Exit from loop.\n\nImmediately exits the current loop." },
{ "continue", "Continue to next iteration.\n\nSkips remaining statements in current loop iteration." },
{ "exit", "Exit from procedure/function.\n\nImmediately returns from current procedure." },
{ "return", "Return value from function.\n\nSyntax:\n```tsf\nreturn expression;\n```" },
{ "try", "Exception handling block.\n\nSyntax:\n```tsf\ntry\n statements\nexcept\n exception_handler\nend;\n```" },
{ "except", "Exception handler.\n\nUsed with: try" },
{ "finally", "Finally block.\n\nAlways executed after try block." },
{ "raise", "Raise an exception.\n\nSyntax:\n```tsf\nraise Exception.Create('message');\n```" }
};
// 内置函数文档
const std::unordered_map<std::string, std::string> kBuiltinFunctions = {
{ "writeln", "**writeln**(text: string)\n\nWrites text to standard output with newline.\n\nExample:\n```tsf\nwriteln('Hello, World!');\n```" },
{ "write", "**write**(text: string)\n\nWrites text to standard output without newline.\n\nExample:\n```tsf\nwrite('Enter name: ');\n```" },
{ "readln", "**readln**(): string\n\nReads a line from standard input.\n\nExample:\n```tsf\nvar name: string;\nname := readln();\n```" },
{ "length", "**length**(s: string): integer\n\nReturns the length of a string.\n\nExample:\n```tsf\nlen := length('hello'); // returns 5\n```" },
{ "copy", "**copy**(s: string; index, count: integer): string\n\nReturns a substring.\n\nExample:\n```tsf\nsubstr := copy('hello', 2, 3); // returns 'ell'\n```" },
{ "pos", "**pos**(substr, s: string): integer\n\nFinds position of substring.\n\nExample:\n```tsf\nindex := pos('lo', 'hello'); // returns 4\n```" },
{ "delete", "**delete**(var s: string; index, count: integer)\n\nDeletes characters from string.\n\nExample:\n```tsf\ndelete(s, 1, 3); // removes first 3 characters\n```" },
{ "insert", "**insert**(source: string; var target: string; index: integer)\n\nInserts string at position.\n\nExample:\n```tsf\ninsert('abc', s, 5);\n```" }
};
}
}
@@ -2,7 +2,7 @@
#include "./resolve.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::document_link
namespace lsp::provider::document_link
{
std::string Resolve::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::document_link
namespace lsp::provider::document_link
{
class Resolve : public IRequestProvider
{
+1 -2
View File
@@ -1,8 +1,7 @@
#include "./exit.hpp"
namespace lsp::providers
namespace lsp::provider
{
std::string Exit::GetMethod() const
{
return "exit";
+2 -2
View File
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers
namespace lsp::provider
{
class Exit : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./initialize.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers
namespace lsp::provider
{
std::string Initialize::GetMethod() const
{
@@ -35,53 +35,69 @@ namespace lsp::providers
{
protocol::InitializeResult result;
result.serverInfo.name = "TSL Language Server";
result.serverInfo.version = "1.0.0";
protocol::TextDocumentSyncOptions text_document_sync_options;
text_document_sync_options.openClose = true;
text_document_sync_options.change = protocol::TextDocumentSyncKind::kIncremental;
protocol::CompletionOptions completion_provider;
completion_provider.resolveProvider = false;
protocol::SemanticTokensOptions semantic_tokens_options;
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Namespace);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Type);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Class);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Enum);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Interface);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Struct);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::TypeParameter);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Parameter);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Variable);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Property);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::EnumMember);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Event);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Function);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Method);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Macro);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Keyword);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Modifier);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Comment);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::String);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Number);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Regexp);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Operator);
semantic_tokens_options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Decorator);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Declaration);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Definition);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Readonly);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Static);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Deprecated);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Abstract);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Async);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Modification);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Documentation);
semantic_tokens_options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::DefaultLibrary);
semantic_tokens_options.range = true;
semantic_tokens_options.full = protocol::SemanticTokensOptions::Full{.delta = true};
result.capabilities.textDocumentSync = text_document_sync_options;
result.capabilities.completionProvider = completion_provider;
result.capabilities.semanticTokensProvider = semantic_tokens_options;
result.serverInfo.version = __DATE__;
result.capabilities.textDocumentSync = BuildTextDocumentSyncOptions();
result.capabilities.completionProvider = BuildCompletionOptions();
// result.capabilities.semanticTokensProvider = BuildSemanticTokenOptions();
return result;
}
protocol::TextDocumentSyncOptions Initialize::BuildTextDocumentSyncOptions()
{
protocol::TextDocumentSyncOptions options;
options.openClose = true;
options.change = protocol::TextDocumentSyncKind::kIncremental;
return options;
}
protocol::CompletionOptions Initialize::BuildCompletionOptions()
{
protocol::CompletionOptions options;
options.triggerCharacters = { std::vector<std::string>{ "." } };
options.resolveProvider = true;
options.completionItem = {.labelDetailsSupport = true};
return options;
}
protocol::SemanticTokensOptions Initialize::BuildSemanticTokenOptions()
{
protocol::SemanticTokensOptions options;
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Namespace);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Type);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Class);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Enum);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Interface);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Struct);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::TypeParameter);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Parameter);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Variable);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Property);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::EnumMember);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Event);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Function);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Method);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Macro);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Keyword);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Modifier);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Comment);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::String);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Number);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Regexp);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Operator);
options.legend.tokenTypes.emplace_back(protocol::SemanticTokenTypesLiterals::Decorator);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Declaration);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Definition);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Readonly);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Static);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Deprecated);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Abstract);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Async);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Modification);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::Documentation);
options.legend.tokenModifiers.emplace_back(protocol::SemanticTokenModifiersLiterals::DefaultLibrary);
options.range = true;
options.full = protocol::SemanticTokensOptions::Full{ .delta = true };
return options;
}
}
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers
namespace lsp::provider
{
class Initialize : public IRequestProvider
{
@@ -14,5 +14,8 @@ namespace lsp::providers
private:
protocol::InitializeResult BuildInitializeResult();
protocol::TextDocumentSyncOptions BuildTextDocumentSyncOptions();
protocol::CompletionOptions BuildCompletionOptions();
protocol::SemanticTokensOptions BuildSemanticTokenOptions();
};
}
@@ -1,7 +1,7 @@
#include <spdlog/spdlog.h>
#include "./initialized.hpp"
namespace lsp::providers
namespace lsp::provider
{
std::string Initialized::GetMethod() const
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers
namespace lsp::provider
{
class Initialized : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./resolve.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::inlay_hint
namespace lsp::provider::inlay_hint
{
std::string Resolve::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::inlay_hint
namespace lsp::provider::inlay_hint
{
class Resolve : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./shutdown.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers
namespace lsp::provider
{
std::string Shutdown::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers
namespace lsp::provider
{
class Shutdown : public IRequestProvider
{
+1 -1
View File
@@ -2,7 +2,7 @@
#include "./event.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::telemetry
namespace lsp::provider::telemetry
{
std::string Event::GetMethod() const
{
+2 -2
View File
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::telemetry
namespace lsp::provider::telemetry
{
class Event : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./code_action.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string CodeAction::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class CodeAction : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./code_lens.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string CodeLens::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class CodeLens : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./color_presentation.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string ColorPresentation::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class ColorPresentation : public IRequestProvider
{
@@ -1,10 +1,14 @@
#include <spdlog/spdlog.h>
#include "./completion.hpp"
#include <algorithm>
#include <cctype>
#include "../../language/keyword_manager.hpp"
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"
#include "../../utils/string.hpp"
#include "../../protocol/transform/facade.hpp"
#include "./completion.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Completion::GetMethod() const
{
@@ -18,270 +22,456 @@ namespace lsp::providers::text_document
std::string Completion::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
{
spdlog::debug("TextDocumentCompletionProvider: Providing response for method {}", request.method);
spdlog::debug("{}: Processing completion request", GetProviderName());
// 验证请求是否包含参数
if (!request.params.has_value())
{
spdlog::warn("{}: Missing params in request", GetProviderName());
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
}
// 从 variant 中提取参数
protocol::CompletionParams completion_params = transform::As<protocol::CompletionParams>(request.params.value());
protocol::CompletionList completion_list = BuildCompletionResponse(completion_params, context);
// 构建响应消息
protocol::ResponseMessage response;
response.id = request.id;
response.result = transform::LSPAny(completion_list);
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();
}
// ================== Core Completion Logic ==================
protocol::CompletionList Completion::BuildCompletionResponse(const protocol::CompletionParams& params, ExecutionContext& context)
{
spdlog::trace("{}: Processing completion request for URI='{}', Position=({}, {})", GetProviderName(), params.textDocument.uri, params.position.line, params.position.character);
spdlog::trace("{}: URI='{}', Position=({}, {})", GetProviderName(), params.textDocument.uri, params.position.line, params.position.character);
// 获取补全前缀
std::string prefix = ExtractPrefix(params.textDocument.uri, params.position, context);
std::string completion_context = GetCompletionContext(params.textDocument.uri, params.position, context);
spdlog::debug("{}: Prefix='{}', Context='{}'", GetProviderName(), prefix, completion_context);
CompletionContext comp_context = ExtractCompletionContext(params, context);
// 如果提供了 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());
}
// Log completion context details
spdlog::debug("{}: Completion context - prefix='{}', is_member_access={}, is_constructor={}, object_name='{}'",
GetProviderName(),
comp_context.prefix,
comp_context.is_member_access,
comp_context.is_constructor_context,
comp_context.object_name);
// 收集所有补全项
std::vector<protocol::CompletionItem> all_items;
if (!IsMemberCompletion(completion_context))
{
std::string object_name = ExtractObjectName(completion_context);
if (!object_name.empty())
{
auto member_item = ProvideMemberCompletions(params.textDocument.uri, params.position, object_name, context);
all_items.insert(all_items.end(), member_item.begin(), member_item.end());
}
}
else
{
auto keyword_items = ProvideKeywordCompletions(prefix);
all_items.insert(all_items.end(), keyword_items.begin(), keyword_items.end());
std::vector<protocol::CompletionItem> items;
auto symbol_items = ProvideSymbolCompletions(params.textDocument.uri, prefix, context);
all_items.insert(all_items.end(), symbol_items.begin(), symbol_items.end());
auto keyword_items = ProvideKeywordCompletions(comp_context.prefix);
spdlog::trace("{}: Found {} keyword completions", GetProviderName(), keyword_items.size());
AppendCompletions(items, keyword_items);
auto snippet_items = ProvideSnippetCompletions(completion_context);
all_items.insert(all_items.end(), snippet_items.begin(), snippet_items.end());
}
auto function_items = ProvideFunctionCompletions(comp_context, context);
spdlog::trace("{}: Found {} global function completions", GetProviderName(), function_items.size());
AppendCompletions(items, function_items);
size_t before_filter = items.size();
items = FilterAndSortCompletions(items, comp_context.prefix);
spdlog::debug("{}: Completions before filter: {}, after filter: {}", GetProviderName(), before_filter, items.size());
// 构建补全列表
protocol::CompletionList result;
result.isIncomplete = false; // 表示这是完整的补全列表
result.items = std::move(all_items);
spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());
result.isIncomplete = false;
result.items = std::move(items);
spdlog::info("{}: Provided {} completion items for prefix '{}'", GetProviderName(), result.items.size(), comp_context.prefix);
return result;
}
std::string Completion::ExtractPrefix(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context)
std::vector<protocol::CompletionItem> Completion::ProvideFunctionCompletions(const CompletionContext& context, ExecutionContext& exec_context)
{
auto& document_service = context.GetService<service::Document>();
auto content = document_service.GetContent(uri);
if (!content.has_value())
return "";
std::vector<protocol::CompletionItem> items;
auto& symbol_service = exec_context.GetService<service::Symbol>();
auto global_symbols = symbol_service.GetGlobalFunctions();
for (const auto& symbol : global_symbols)
{
for (const auto& symbol_info : symbol.symbols)
{
if (symbol_info.kind == service::TsfSymbolKind::kFunction)
{
if (context.prefix.empty() || utils::StartsWith(symbol_info.name, context.prefix, true))
{
protocol::CompletionItem item;
item.label = symbol_info.name;
item.kind = protocol::CompletionItemKind::kFunction;
item.labelDetails = protocol::CompletionItemLabelDetails{
.detail = BuildFunctionSignature(symbol_info),
.description = "[G]"
};
// item.insertTextFormat = protocol::InsertTextFormat::kSnippet;
item.additionalTextEdits = {};
items.push_back(item);
}
}
}
}
auto symbols = symbol_service.GetDocumentSymbols(context.uri);
for (const auto& symbol : symbols)
{
if (symbol.kind == service::TsfSymbolKind::kFunction)
{
if (context.prefix.empty() || utils::StartsWith(symbol.name, context.prefix, true))
{
protocol::CompletionItem item;
item.label = symbol.name;
item.kind = protocol::CompletionItemKind::kFunction;
item.insertText = symbol.name + "($0)";
item.insertTextFormat = protocol::InsertTextFormat::kSnippet;
item.additionalTextEdits = {};
items.push_back(item);
}
}
}
return items;
}
Completion::CompletionContext Completion::ExtractCompletionContext(const protocol::CompletionParams& params, ExecutionContext& context)
{
CompletionContext result;
result.uri = params.textDocument.uri;
result.position = params.position;
auto& document_service = context.GetService<service::Document>();
auto content = document_service.GetContent(result.uri);
if (!content.has_value())
{
spdlog::warn("{}: Document content not available for URI: {}", GetProviderName(), result.uri);
return result;
}
// Extract line content up to cursor
size_t line_start = 0;
size_t current_line = 0;
for (size_t i = 0; i < content->length(); i++)
{
if (current_line == position.line)
if (current_line == result.position.line)
{
line_start = i;
break;
}
if ((*content)[i] == '\n')
{
current_line++;
}
}
size_t cursor_pos = line_start + position.character;
size_t cursor_pos = line_start + result.position.character;
if (cursor_pos > content->length())
cursor_pos = content->length();
// Extract line content up to cursor
result.line_context = content->substr(line_start, cursor_pos - line_start);
// Check for constructor contexts
result.is_constructor_context = DetectConstructorContext(result.line_context);
// Check for member access patterns
result.is_member_access = DetectMemberAccess(result.line_context);
if (result.is_member_access)
{
result.object_name = ExtractObjectName(result.line_context);
result.prefix = ExtractMemberPrefix(result.line_context);
spdlog::trace("{}: Member access detected - object='{}', prefix='{}'", GetProviderName(), result.object_name, result.prefix);
}
else if (result.is_constructor_context)
{
// Special handling for constructor context prefix extraction
result.prefix = ExtractConstructorPrefix(result.line_context);
spdlog::trace("{}: Constructor context detected - prefix='{}'", GetProviderName(), result.prefix);
}
else
{
result.prefix = ExtractPrefix(cursor_pos, line_start, *content);
spdlog::trace("{}: Normal context - prefix='{}'", GetProviderName(), result.prefix);
}
return result;
}
bool Completion::DetectConstructorContext(const std::string& line)
{
std::string line_lower = utils::ToLower(line);
// Check for "new " pattern (case-insensitive)
size_t new_pos = line_lower.rfind("new ");
if (new_pos != std::string::npos)
{
// Make sure we're after "new " keyword
std::string after_new = line.substr(new_pos + 4);
after_new = utils::Trim(after_new);
// If there's no content after "new " or incomplete class name (no parenthesis yet)
if (after_new.empty() || after_new.find("(") == std::string::npos)
{
spdlog::trace("{}: 'new' constructor context detected", GetProviderName());
return true;
}
}
// Check for createobject(" pattern (case-insensitive)
size_t create_pos = line_lower.rfind("createobject(\"");
if (create_pos != std::string::npos)
{
// Check if we're inside the string literal
size_t quote_start = create_pos + 14; // length of "createobject(\""
size_t quote_end = line.find('"', quote_start);
if (quote_end == std::string::npos || quote_end > line.length())
{
spdlog::trace("{}: 'createobject(\"' constructor context detected", GetProviderName());
return true;
}
}
// Check for createobject(' pattern (single quote variant, case-insensitive)
create_pos = line_lower.rfind("createobject('");
if (create_pos != std::string::npos)
{
size_t quote_start = create_pos + 14;
size_t quote_end = line.find('\'', quote_start);
if (quote_end == std::string::npos || quote_end > line.length())
{
spdlog::trace("{}: 'createobject('' constructor context detected", GetProviderName());
return true;
}
}
return false;
}
std::string Completion::ExtractConstructorPrefix(const std::string& line)
{
std::string line_lower = utils::ToLower(line);
// Handle createobject("xxx or createobject('xxx
size_t create_pos = line_lower.rfind("createobject(\"");
if (create_pos != std::string::npos)
{
std::string prefix = line.substr(create_pos + 14); // 14 = length of "createobject(\""
spdlog::trace("{}: Extracted constructor prefix from createobject(\"): '{}'", GetProviderName(), prefix);
return prefix;
}
create_pos = line_lower.rfind("createobject('");
if (create_pos != std::string::npos)
{
std::string prefix = line.substr(create_pos + 14);
spdlog::trace("{}: Extracted constructor prefix from createobject('): '{}'", GetProviderName(), prefix);
return prefix;
}
// Handle new xxx
size_t new_pos = line_lower.rfind("new ");
if (new_pos != std::string::npos)
{
std::string after_new = line.substr(new_pos + 4);
std::string prefix = utils::Trim(after_new);
spdlog::trace("{}: Extracted constructor prefix from 'new': '{}'", GetProviderName(), prefix);
return prefix;
}
return "";
}
std::string Completion::ExtractPrefix(size_t cursor_pos, size_t line_start, const std::string& content)
{
size_t prefix_start = cursor_pos;
while (prefix_start > line_start)
{
char ch = (*content)[prefix_start - 1];
char ch = content[prefix_start - 1];
if (!std::isalnum(ch) && ch != '_')
break;
prefix_start--;
}
return content->substr(prefix_start, cursor_pos - prefix_start);
return content.substr(prefix_start, cursor_pos - prefix_start);
}
std::string Completion::GetCompletionContext(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context)
std::string Completion::ExtractMemberPrefix(const std::string& line)
{
auto& document_service = context.GetService<service::Document>();
size_t last_dot = line.find_last_of('.');
if (last_dot == std::string::npos || last_dot == line.length() - 1)
return "";
return line.substr(last_dot + 1);
}
auto content = document_service.GetContent(uri);
if (!content.has_value())
bool Completion::DetectMemberAccess(const std::string& line)
{
// Check for patterns: obj., class(name)., unit(name).
if (line.find('.') == std::string::npos)
return false;
std::string line_lower = utils::ToLower(line);
// Check for class() or unit() patterns (case-insensitive)
if (line_lower.find("class(") != std::string::npos || line_lower.find("unit(") != std::string::npos)
return true;
// Check for simple object.member pattern
size_t last_dot = line.find_last_of('.');
if (last_dot != std::string::npos && last_dot > 0)
{
// Make sure there's an identifier before the dot
char before_dot = line[last_dot - 1];
return std::isalnum(before_dot) || before_dot == '_' || before_dot == ')';
}
return false;
}
std::string Completion::ExtractObjectName(const std::string& line)
{
size_t last_dot = line.find_last_of('.');
if (last_dot == std::string::npos)
return "";
size_t line_start = 0;
size_t line_end = content->length();
size_t current_line = 0;
std::string before_dot = line.substr(0, last_dot);
std::string before_dot_lower = utils::ToLower(before_dot);
for (size_t i = 0; i < content->length(); i++)
// Check for class(...) or unit(...) patterns (case-insensitive)
if (before_dot_lower.find("class(") != std::string::npos)
{
if (current_line == position.line)
{
line_start = i;
for (size_t j = i; j < content->length(); j++)
{
if ((*content)[j] == '\n')
{
line_end = j;
break;
}
}
size_t start = before_dot_lower.find("class(");
return before_dot.substr(start);
}
else if (before_dot_lower.find("unit(") != std::string::npos)
{
size_t start = before_dot_lower.find("unit(");
return before_dot.substr(start);
}
// Extract simple identifier
size_t start = last_dot;
while (start > 0)
{
char ch = line[start - 1];
if (!std::isalnum(ch) && ch != '_')
break;
}
if ((*content)[i] == '\n')
{
current_line++;
}
start--;
}
size_t cursor_pos = line_start + position.character;
if (cursor_pos > line_end)
cursor_pos = line_end;
return content->substr(line_start, cursor_pos - line_start);
}
std::vector<protocol::CompletionItem> Completion::ProvideSymbolCompletions(const protocol::DocumentUri& uri, const std::string& prefix, ExecutionContext& context)
{
std::vector<protocol::CompletionItem> items;
// 从容器获取符号服务
auto& symbol_service = context.GetService<service::Symbol>();
auto symbols = symbol_service.GetDocumentSymbols(uri);
std::function<void(const std::vector<protocol::DocumentSymbol>&)> process_symbols =
[&](const std::vector<protocol::DocumentSymbol>& symbol_list) {
for (const auto& symbol : symbol_list)
{
if (!prefix.empty() && symbol.name.find(prefix) != 0)
{
process_symbols(symbol.children.value());
continue;
}
protocol::CompletionItem item = SymbolToCompletionItem(symbol);
items.push_back(item);
process_symbols(symbol.children.value());
}
};
process_symbols(symbols);
spdlog::debug("{}: Found {} symbol completions", GetProviderName(), items.size());
return items;
}
std::vector<protocol::CompletionItem> Completion::ProvideMemberCompletions(const protocol::DocumentUri& uri, const protocol::Position& position, const std::string& object_name, ExecutionContext& context)
{
std::vector<protocol::CompletionItem> items;
// TODO: 实现成员补全
spdlog::debug("{}: Member completion for '{}' not fully implemented", GetProviderName(), object_name);
if (!object_name.empty())
{
protocol::CompletionItem item;
item.label = "Create";
item.kind = protocol::CompletionItemKind::kMethod;
item.detail = "Constructor method";
item.insertText = "Create()";
items.push_back(item);
item.label = "Free";
item.kind = protocol::CompletionItemKind::kMethod;
item.detail = "Destructor method";
item.insertText = "Free";
items.push_back(item);
}
return items;
return line.substr(start, last_dot - start);
}
// ================== Keyword Completions ==================
std::vector<protocol::CompletionItem> Completion::ProvideKeywordCompletions(const std::string& prefix)
{
std::vector<protocol::CompletionItem> items;
// 从 tsl_keywords_ 获取补全项
auto tslItems = tsl_keywords_.GetCompletionItems(prefix);
for (const auto& tslItem : tslItems)
auto keywords_item = tsl::KeywordManager::GetInstance().GetKeyWordByPrefix(utils::ToLower(prefix));
for (const auto& keyword : keywords_item)
{
protocol::CompletionItem item;
item.label = tslItem.label;
item.label = keyword.keyword;
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;
item.labelDetails = protocol::CompletionItemLabelDetails{
.detail = "",
.description = "keyword"
};
item.insertText = keyword.keyword;
items.push_back(item);
}
spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
return items;
}
std::vector<protocol::CompletionItem> Completion::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
void Completion::AppendCompletions(std::vector<protocol::CompletionItem>& target, const std::vector<protocol::CompletionItem>& source)
{
spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);
target.insert(target.end(), source.begin(), source.end());
}
std::vector<protocol::CompletionItem> items;
std::vector<protocol::CompletionItem> Completion::FilterAndSortCompletions(const std::vector<protocol::CompletionItem>& items, const std::string& prefix)
{
std::vector<protocol::CompletionItem> filtered;
std::set<std::string> seen;
// TODO: 基于上下文提供补全
// 示例:添加一个变量补全
if (!prefix.empty() && prefix[0] == '$')
for (const auto& item : items)
{
protocol::CompletionItem varItem;
varItem.label = "$myVariable";
varItem.kind = protocol::CompletionItemKind::kVariable;
varItem.detail = "Local variable";
varItem.insertText = "$myVariable";
// Remove duplicates
if (seen.find(item.label) != seen.end())
continue;
seen.insert(item.label);
protocol::MarkupContent doc;
doc.kind = protocol::MarkupKindLiterals::Markdown;
doc.value = "Example variable completion";
varItem.documentation = doc;
// Filter by prefix if provided (case-insensitive)
if (!prefix.empty() && !utils::StartsWith(item.label, prefix, true))
continue;
items.push_back(varItem);
filtered.push_back(item);
}
spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
return items;
std::sort(filtered.begin(), filtered.end(), [&prefix](const protocol::CompletionItem& a, const protocol::CompletionItem& b) -> bool {
// Exact matches first (case-insensitive)
bool a_exact = utils::ToLower(a.label) == utils::ToLower(prefix);
bool b_exact = utils::ToLower(b.label) == utils::ToLower(prefix);
if (a_exact != b_exact)
return a_exact;
// Then by kind (function > variable > others > keyword)
if (a.kind.has_value() && b.kind.has_value() && a.kind.value() != b.kind.value())
{
auto kind_priority = [](protocol::CompletionItemKind kind) -> int {
switch (kind)
{
case protocol::CompletionItemKind::kFunction:
case protocol::CompletionItemKind::kMethod:
return 0; // Highest priority
case protocol::CompletionItemKind::kVariable:
case protocol::CompletionItemKind::kField:
case protocol::CompletionItemKind::kProperty:
return 1;
case protocol::CompletionItemKind::kClass:
return 2;
case protocol::CompletionItemKind::kModule:
return 3;
case protocol::CompletionItemKind::kConstant:
return 4;
case protocol::CompletionItemKind::kSnippet:
return 5;
case protocol::CompletionItemKind::kKeyword:
return 6; // Lowest priority
default:
return 5; // Others
}
};
int a_priority = kind_priority(a.kind.value());
int b_priority = kind_priority(b.kind.value());
if (a_priority != b_priority)
return a_priority < b_priority;
}
// Finally alphabetically (case-insensitive)
std::string a_lower = utils::ToLower(a.label);
std::string b_lower = utils::ToLower(b.label);
return a_lower < b_lower;
});
spdlog::trace("{}: Filtered {} items to {} items", GetProviderName(), items.size(), filtered.size());
return filtered;
}
std::string Completion::BuildFunctionSignature(const service::SymbolInfo& symbol)
{
if (!symbol.callable)
return "";
std::stringstream ss;
ss << "(";
const auto& params = symbol.callable->parameters;
for (size_t i = 0; i < params.size(); ++i)
{
if (i > 0)
ss << (params[i].typed && !params[i].typed->type_name.empty() ? "; " : ", ");
const auto& param = params[i];
ss << param.name;
if (param.typed && !param.typed->type_name.empty())
{
ss << ": " << param.typed->type_name;
}
}
ss << ")";
if (symbol.callable->return_type)
ss << " -> " << *symbol.callable->return_type;
return ss.str();
}
}
@@ -1,10 +1,10 @@
#pragma once
#include <string>
#include <vector>
#include "../base/provider_interface.hpp"
#include "../../language/tsl_keywords.hpp"
#include "../base/interface.hpp"
#include "../../service/detail/symbol/symbol_types.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Completion : public IRequestProvider
{
@@ -14,25 +14,31 @@ namespace lsp::providers::text_document
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& 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 BuildCompletionResponse(const protocol::CompletionParams& params, ExecutionContext& context);
// 获取补全前缀(从文档内容和位置计算)
std::string ExtractPrefix(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
// 提供不同类型的补全
std::vector<protocol::CompletionItem> ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix);
std::string GetCompletionContext(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
std::vector<protocol::CompletionItem> ProvideKeywordCompletions(const std::string& prefix);
std::vector<protocol::CompletionItem> ProvideSymbolCompletions(const protocol::DocumentUri& uri, const std::string& prefix, ExecutionContext& context);
std::vector<protocol::CompletionItem> ProvideMemberCompletions(const protocol::DocumentUri& uri, const protocol::Position& position, const std::string& object_name, ExecutionContext& context);
std::vector<protocol::CompletionItem> ProvideSnippetCompletions(const std::string& context);
std::vector<protocol::CompletionItem> ProvideFunctionCompletions(const CompletionContext& context, ExecutionContext& exec_context);
protocol::CompletionItem SymbolToCompletionItem(const protocol::DocumentSymbol& symbol);
bool IsMemberCompletion(const std::string& context);
std::string ExtractObjectName(const std::string& context);
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);
private:
tsl::TslKeywords tsl_keywords_;
static std::string BuildFunctionSignature(const service::SymbolInfo& symbol);
};
}
@@ -3,7 +3,7 @@
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Definition::GetMethod() const
{
@@ -1,11 +1,11 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
extern "C" {
#include <tree_sitter/api.h>
}
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Definition : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./diagnostic.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Diagnostic::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Diagnostic : public IRequestProvider
{
@@ -3,7 +3,7 @@
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DidChange::GetMethod() const
@@ -20,12 +20,12 @@ namespace lsp::providers::text_document
{
spdlog::debug("TextDocumentDidChangeProvider: Providing response for method {}", notification.method);
protocol::DidChangeTextDocumentParams did_change_text_document_params = transform::As<protocol::DidChangeTextDocumentParams>(notification.params.value());
protocol::DidChangeTextDocumentParams params = transform::As<protocol::DidChangeTextDocumentParams>(notification.params.value());
service::Document& document_service = context.GetService<service::Document>();
document_service.UpdateDocument(did_change_text_document_params);
document_service.UpdateDocument(params);
spdlog::info("Document updated: {}", did_change_text_document_params.textDocument.uri);
spdlog::info("Document updated: {}", params.textDocument.uri);
}
}
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DidChange : public INotificationProvider
{
@@ -3,7 +3,7 @@
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DidClose::GetMethod() const
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DidClose : public INotificationProvider
{
@@ -3,7 +3,7 @@
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DidOpen::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DidOpen : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./document_color.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DocumentColor::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DocumentColor : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./document_highlight.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DocumentHighlight::GetMethod() const
{
@@ -1,8 +1,8 @@
#pragma once
#include <unordered_map>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DocumentHighlight : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./document_link.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DocumentLink::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DocumentLink : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./document_symbol.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string DocumentSymbol::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class DocumentSymbol : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./folding_range.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string FoldingRange::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class FoldingRange : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./formatting.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Formatting::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Formatting : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./hover.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Hover::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Hover : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./implementation.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Implementation::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Implementation : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./inlay_hint.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string InlayHint::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class InlayHint : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./inline_value.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string InlineValue::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class InlineValue : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./linked_editing_range.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string LinkedEditingRange::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class LinkedEditingRange : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./moniker.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Moniker::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Moniker : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./on_type_formatting.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string OnTypeFormatting::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class OnTypeFormatting : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./prepare_call_hierarchy.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string PrepareCallHierarchy::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class PrepareCallHierarchy : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./prepare_rename.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string PrepareRename::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class PrepareRename : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./prepare_type_hierarchy.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string PrepareTypeHierarchy::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class PrepareTypeHierarchy : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./publish_diagnostics.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string PublishDiagnostics::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class PublishDiagnostics : public INotificationProvider
{
@@ -2,7 +2,7 @@
#include "./range_formatting.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string RangeFormatting::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class RangeFormatting : public IRequestProvider
{
@@ -4,7 +4,7 @@
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string References::GetMethod() const
{
@@ -1,22 +1,21 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
extern "C" {
#include <tree_sitter/api.h>
}
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class References : public IRequestProvider
{
public:
References() = default;
std::string GetMethod() const override;
std::string GetProviderName() const override;
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
private:
std::vector<protocol::Location> BuildReferencesResponse(const protocol::ReferenceParams& params, ExecutionContext& context);
std::vector<protocol::Location> FindReferences(const protocol::DocumentUri& uri, const std::string& identifier, bool include_declaration, ExecutionContext& context);
@@ -8,7 +8,7 @@
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string Rename::GetMethod() const
{
@@ -1,13 +1,13 @@
#pragma once
#include <string>
#include <vector>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
extern "C" {
#include <tree_sitter/api.h>
}
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class Rename : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./selection_range.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string SelectionRange::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class SelectionRange : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./semantic_tokens.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
bool IsFieldName(TSNode parent, TSNode node, const std::string& field_name)
{
@@ -1,11 +1,11 @@
#pragma once
#include <unordered_map>
#include <vector>
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
#include "../../protocol/protocol.hpp"
#include "../../service/document.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
enum class SemanticTokenType: protocol::uinteger
{
@@ -2,7 +2,7 @@
#include "./signature_help.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string SignatureHelp::GetMethod() const
{
@@ -1,7 +1,7 @@
#pragma once
#include "../base/provider_interface.hpp"
#include "../base/interface.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
class SignatureHelp : public IRequestProvider
{
@@ -2,7 +2,7 @@
#include "./type_definition.hpp"
#include "../../protocol/transform/facade.hpp"
namespace lsp::providers::text_document
namespace lsp::provider::text_document
{
std::string TypeDefinition::GetMethod() const
{

Some files were not shown because too many files have changed in this diff Show More