tree-sitter and lsp-methods
This commit is contained in:
parent
e9972fd869
commit
aac12137cb
|
|
@ -1,4 +1,5 @@
|
|||
cmake_minimum_required(VERSION 4.0)
|
||||
|
||||
project(tsl-server)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
|
@ -8,6 +9,13 @@ message(STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
|
|||
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
|
||||
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if (DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS ">>> CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
if (DEFINED VCPKG_TARGET_TRIPLET)
|
||||
message(STATUS ">>> VCPKG_TARGET_TRIPLET: ${VCPKG_TARGET_TRIPLET}")
|
||||
endif()
|
||||
|
||||
# 设置默认构建类型
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE
|
||||
|
|
@ -17,50 +25,38 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||
"MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/W4 /permissive- /Zc:__cplusplus /utf-8)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
else()
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# MinGW/MSYS2 静态链接
|
||||
if(MINGW)
|
||||
add_link_options(-static -static-libgcc -static-libstdc++)
|
||||
endif()
|
||||
|
||||
# Linux 静态链接
|
||||
if(UNIX AND NOT APPLE)
|
||||
elseif(UNIX AND NOT APPLE) # Linux 静态链接
|
||||
add_link_options(-static-libgcc -static-libstdc++)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(DEFINED VCPKG_DIR)
|
||||
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
set(CMAKE_TOOLCHAIN_FILE
|
||||
${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
|
||||
CACHE PATH "")
|
||||
endif()
|
||||
message(STATUS ">>> Vcpkg: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
|
||||
if(NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
set(VCPKG_TARGET_TRIPLET
|
||||
"x64-windows-static"
|
||||
CACHE STRING "")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_INCLUDE_PATH
|
||||
${VCPKG_DIR}/installed/x64-windows-static/include)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${VCPKG_DIR}/installed/x64-windows-static)
|
||||
if(WIN32)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib" ".dll.a")
|
||||
else()
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so")
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib" ".so")
|
||||
|
||||
find_package(glaze CONFIG REQUIRED)
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
find_package(Taskflow REQUIRED)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
find_package(unofficial-tree-sitter CONFIG REQUIRED)
|
||||
set(TREESITTER_TARGET unofficial::tree-sitter::tree-sitter)
|
||||
else()
|
||||
# find_package(PkgConfig REQUIRED)
|
||||
# pkg_check_modules(TREESITTER tree-sitter)
|
||||
find_library(TREESITTER_LIBRARY tree-sitter) # use ${TREESITTER_LIBRARY}
|
||||
set(TREESITTER_TARGET ${TREESITTER_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT TARGET spdlog::spdlog_header_only)
|
||||
message(WARNING "spdlog header-only target not found, using shared library")
|
||||
endif()
|
||||
|
|
@ -68,10 +64,6 @@ if(NOT TARGET fmt::fmt-header-only)
|
|||
message(WARNING "fmt header-only target not found, using shared library")
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set(SOURCES
|
||||
src/main.cpp
|
||||
|
|
@ -79,21 +71,22 @@ set(SOURCES
|
|||
src/language/tsl_keywords.cpp
|
||||
src/core/dispacther.cpp
|
||||
src/core/server.cpp
|
||||
src/scheduler/request_scheduler.cpp
|
||||
src/scheduler/request.cpp
|
||||
src/provider/base/provider_registry.cpp
|
||||
src/provider/base/provider_interface.cpp
|
||||
src/provider/initialize/initialize_provider.cpp
|
||||
src/provider/initialized/initialized_provider.cpp
|
||||
src/provider/text_document/did_open_provider.cpp
|
||||
src/provider/text_document/did_change_provider.cpp
|
||||
src/provider/text_document/did_close_provider.cpp
|
||||
src/provider/text_document/completion_provider.cpp
|
||||
src/provider/shutdown/shutdown_provider.cpp
|
||||
src/provider/exit/exit_provider.cpp
|
||||
src/provider/cancel_request/cancel_request_provider.cpp
|
||||
src/provider/trace/set_trace_provider.cpp
|
||||
src/services/document.cpp
|
||||
)
|
||||
src/provider/initialize/initialize.cpp
|
||||
src/provider/initialized/initialized.cpp
|
||||
src/provider/text_document/did_open.cpp
|
||||
src/provider/text_document/did_change.cpp
|
||||
src/provider/text_document/did_close.cpp
|
||||
src/provider/text_document/completion.cpp
|
||||
src/provider/text_document/semantic_tokens.cpp
|
||||
src/provider/shutdown/shutdown.cpp
|
||||
src/provider/exit/exit.cpp
|
||||
src/provider/cancel_request/cancel_request.cpp
|
||||
src/provider/trace/set_trace.cpp
|
||||
src/service/document.cpp
|
||||
src/tree-sitter/parser.c)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE src)
|
||||
|
|
@ -101,11 +94,20 @@ target_include_directories(${PROJECT_NAME} PRIVATE src)
|
|||
target_compile_definitions(${PROJECT_NAME} PRIVATE SPDLOG_HEADER_ONLY
|
||||
FMT_HEADER_ONLY)
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME} PRIVATE glaze::glaze Taskflow::Taskflow
|
||||
spdlog::spdlog_header_only fmt::fmt-header-only)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
glaze::glaze
|
||||
Taskflow::Taskflow
|
||||
spdlog::spdlog_header_only
|
||||
fmt::fmt-header-only
|
||||
${TREESITTER_TARGET} # 使用变量,避免条件判断
|
||||
$<$<PLATFORM_ID:Linux>:Threads::Threads> # 使用生成器表达式
|
||||
)
|
||||
|
||||
# Linux 需要链接 pthread
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-Wall -Wextra -Wpedantic
|
||||
$<$<CONFIG:Debug>:-g -O0>
|
||||
$<$<CONFIG:Release>:-O3>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ namespace lsp::core
|
|||
};
|
||||
}
|
||||
|
||||
void RequestDispatcher::SetRequestScheduler(scheduler::RequestScheduler* scheduler)
|
||||
void RequestDispatcher::SetRequestScheduler(scheduler::Request* scheduler)
|
||||
{
|
||||
scheduler_ = scheduler;
|
||||
request_scheduler_ = scheduler;
|
||||
spdlog::debug("RequestScheduler set in dispatcher");
|
||||
}
|
||||
|
||||
void RequestDispatcher::SetSeviceContainer(services::ServiceContainer* service_container)
|
||||
void RequestDispatcher::SetSeviceContainer(service::Container* service_container)
|
||||
{
|
||||
service_container_ = service_container;
|
||||
spdlog::debug("DocumentService is set in dispatcher");
|
||||
spdlog::debug("ServiceContainer is set in dispatcher");
|
||||
}
|
||||
|
||||
void RequestDispatcher::RegisterRequestProvider(std::shared_ptr<providers::IRequestProvider> provider)
|
||||
|
|
@ -31,7 +31,6 @@ namespace lsp::core
|
|||
std::string method = provider->GetMethod();
|
||||
|
||||
providers_[method] = provider;
|
||||
spdlog::info("Registered request provider '{}' for method: {}", provider->GetProviderName(), method);
|
||||
}
|
||||
|
||||
void RequestDispatcher::RegisterNotificationProvider(std::shared_ptr<providers::INotificationProvider> provider)
|
||||
|
|
@ -40,7 +39,6 @@ namespace lsp::core
|
|||
std::string method = provider->GetMethod();
|
||||
|
||||
notification_providers_[method] = provider;
|
||||
spdlog::info("Registered notification provider '{}' for method: {}", provider->GetProviderName(), method);
|
||||
}
|
||||
|
||||
void RequestDispatcher::RegisterLifecycleCallback(providers::LifecycleCallback callback)
|
||||
|
|
@ -52,7 +50,7 @@ namespace lsp::core
|
|||
|
||||
std::string RequestDispatcher::Dispatch(const protocol::RequestMessage& request)
|
||||
{
|
||||
providers::ExecutionContext context(context_lifecycle_callback_, *scheduler_, *service_container_);
|
||||
providers::ExecutionContext context(context_lifecycle_callback_, *request_scheduler_, *service_container_);
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock(providers_mutex_);
|
||||
auto it = providers_.find(request.method);
|
||||
|
|
@ -62,13 +60,13 @@ namespace lsp::core
|
|||
lock.unlock();
|
||||
try
|
||||
{
|
||||
spdlog::debug("Dispatching request '{}' to provider '{}'", request.method, provider->GetProviderName());
|
||||
spdlog::debug("Dispatching request [{}] to provider [{}]", request.method, provider->GetProviderName());
|
||||
return provider->ProvideResponse(request, context);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
spdlog::error("Provider error for method {}: {}", request.method, e.what());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, e.what());
|
||||
spdlog::error("Provider error for method [{}]: {}", request.method, e.what());
|
||||
return providers::BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, e.what());
|
||||
}
|
||||
}
|
||||
return HandleUnknownRequest(request);
|
||||
|
|
@ -76,10 +74,9 @@ namespace lsp::core
|
|||
|
||||
void RequestDispatcher::Dispatch(const protocol::NotificationMessage& notification)
|
||||
{
|
||||
providers::ExecutionContext context(context_lifecycle_callback_, *scheduler_, *service_container_);
|
||||
providers::ExecutionContext context(context_lifecycle_callback_, *request_scheduler_, *service_container_);
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock(notification_providers_mutex_);
|
||||
// 先尝试精确匹配
|
||||
auto it = notification_providers_.find(notification.method);
|
||||
if (it != notification_providers_.end())
|
||||
{
|
||||
|
|
@ -88,13 +85,13 @@ namespace lsp::core
|
|||
|
||||
try
|
||||
{
|
||||
spdlog::debug("Dispatching notification '{}' to provider '{}'", notification.method, provider->GetProviderName());
|
||||
spdlog::debug("Dispatching notification [{}] to provider [{}]", notification.method, provider->GetProviderName());
|
||||
provider->HandleNotification(notification, context);
|
||||
return;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
spdlog::error("Notification provider '{}' threw exception for method '{}': {}", provider->GetProviderName(), notification.method, e.what());
|
||||
spdlog::error("Notification provider [{}] threw exception for method '{}': {}", provider->GetProviderName(), notification.method, e.what());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -137,11 +134,6 @@ namespace lsp::core
|
|||
return requests;
|
||||
}
|
||||
|
||||
std::string RequestDispatcher::BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
|
||||
{
|
||||
return providers::IRequestProvider::BuildErrorResponseMessage(request, code, message);
|
||||
}
|
||||
|
||||
void RequestDispatcher::NotifyAllLifecycleListeners(providers::ServerLifecycleEvent event)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(callbacks_mutex_);
|
||||
|
|
@ -183,7 +175,7 @@ namespace lsp::core
|
|||
|
||||
std::string RequestDispatcher::HandleUnknownRequest(const protocol::RequestMessage& request)
|
||||
{
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kMethodNotFound, "Method not found: " + request.method);
|
||||
return providers::BuildErrorResponseMessage(request, protocol::ErrorCodes::kMethodNotFound, "Method not found: " + request.method);
|
||||
}
|
||||
|
||||
void RequestDispatcher::HandleUnknownNotification(const protocol::NotificationMessage& notification)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <shared_mutex>
|
||||
#include "../protocol/protocol.hpp"
|
||||
#include "../provider/base/provider_interface.hpp"
|
||||
#include "../services/service_container.hpp"
|
||||
#include "../service/base/container.hpp"
|
||||
|
||||
namespace lsp::core
|
||||
{
|
||||
|
|
@ -15,8 +15,8 @@ namespace lsp::core
|
|||
RequestDispatcher();
|
||||
~RequestDispatcher() = default;
|
||||
|
||||
void SetRequestScheduler(scheduler::RequestScheduler* scheduler);
|
||||
void SetSeviceContainer(services::ServiceContainer* service_container);
|
||||
void SetRequestScheduler(scheduler::Request* scheduler);
|
||||
void SetSeviceContainer(service::Container* service_container);
|
||||
|
||||
void RegisterRequestProvider(std::shared_ptr<providers::IRequestProvider> provider);
|
||||
void RegisterNotificationProvider(std::shared_ptr<providers::INotificationProvider> provider);
|
||||
|
|
@ -32,8 +32,6 @@ namespace lsp::core
|
|||
std::vector<std::string> GetSupportedNotifications() const;
|
||||
std::vector<std::string> GetAllSupportedMethods() const;
|
||||
|
||||
std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
|
||||
|
||||
private:
|
||||
void NotifyAllLifecycleListeners(providers::ServerLifecycleEvent event);
|
||||
std::string HandleUnknownRequest(const protocol::RequestMessage& request);
|
||||
|
|
@ -52,7 +50,7 @@ namespace lsp::core
|
|||
providers::LifecycleCallback context_lifecycle_callback_;
|
||||
|
||||
// 服务引用
|
||||
scheduler::RequestScheduler* scheduler_ = nullptr;
|
||||
services::ServiceContainer* service_container_ = nullptr;
|
||||
scheduler::Request* request_scheduler_ = nullptr;
|
||||
service::Container* service_container_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <spdlog/spdlog.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
|
|
@ -8,15 +7,13 @@
|
|||
#endif
|
||||
#include "../provider/base/provider_registry.hpp"
|
||||
#include "../protocol/transform/facade.hpp"
|
||||
#include "../scheduler/request_scheduler.hpp"
|
||||
#include "../services/document.hpp"
|
||||
#include "../services/document.hpp"
|
||||
#include "../service/document.hpp"
|
||||
#include "./server.hpp"
|
||||
|
||||
namespace lsp::core
|
||||
{
|
||||
LspServer::LspServer(size_t concurrency) :
|
||||
scheduler_(4)
|
||||
request_scheduler_(4)
|
||||
{
|
||||
spdlog::info("Initializing LSP server with {} worker threads", concurrency);
|
||||
|
||||
|
|
@ -130,10 +127,10 @@ namespace lsp::core
|
|||
|
||||
void LspServer::HandleMessage(const std::string& raw_message)
|
||||
{
|
||||
if (auto request = transform::Deserialize<protocol::RequestMessage>(raw_message))
|
||||
HandleRequest(*request);
|
||||
else if (auto notification = transform::Deserialize<protocol::NotificationMessage>(raw_message))
|
||||
if (auto notification = transform::Deserialize<protocol::NotificationMessage>(raw_message))
|
||||
HandleNotification(*notification);
|
||||
else if (auto request = transform::Deserialize<protocol::RequestMessage>(raw_message))
|
||||
HandleRequest(*request);
|
||||
else if (auto response = transform::Deserialize<protocol::ResponseMessage>(raw_message))
|
||||
HandleResponse(*response);
|
||||
else
|
||||
|
|
@ -160,7 +157,7 @@ namespace lsp::core
|
|||
else
|
||||
{
|
||||
// 异步处理
|
||||
scheduler_.Submit(request_id, [this, request]() -> std::optional<std::string> {
|
||||
request_scheduler_.Submit(request_id, [this, request]() -> std::optional<std::string> {
|
||||
if (is_shutting_down_)
|
||||
{
|
||||
spdlog::debug("Skipping request {} due to shutdown", request.method);
|
||||
|
|
@ -174,13 +171,12 @@ namespace lsp::core
|
|||
catch (const std::exception& e)
|
||||
{
|
||||
spdlog::error("Request processing failed: {}", e.what());
|
||||
return dispatcher_.BuildErrorResponseMessage( request, protocol::ErrorCode::kInternalError, e.what());
|
||||
return providers::BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, e.what());
|
||||
}
|
||||
});
|
||||
}
|
||||
spdlog::debug("Processing request method: {}", request.method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LspServer::HandleNotification(const protocol::NotificationMessage& notification)
|
||||
|
|
@ -282,7 +278,7 @@ namespace lsp::core
|
|||
{
|
||||
spdlog::debug("Initializing core services...");
|
||||
|
||||
dispatcher_.SetRequestScheduler(&scheduler_);
|
||||
dispatcher_.SetRequestScheduler(&request_scheduler_);
|
||||
|
||||
dispatcher_.RegisterLifecycleCallback(
|
||||
[this](providers::ServerLifecycleEvent event) {
|
||||
|
|
@ -290,7 +286,7 @@ namespace lsp::core
|
|||
});
|
||||
providers::RegisterAllProviders(dispatcher_);
|
||||
|
||||
scheduler_.SetResponseCallback([this](const std::string& response) {
|
||||
request_scheduler_.SetResponseCallback([this](const std::string& response) {
|
||||
SendResponse(response);
|
||||
});
|
||||
|
||||
|
|
@ -301,26 +297,26 @@ namespace lsp::core
|
|||
{
|
||||
spdlog::debug("Initializing extension services...");
|
||||
|
||||
// service_container_.RegisterService(std::shared_ptr<services::DocumentService>());
|
||||
service_container_.RegisterService(std::make_shared<service::Document>());
|
||||
dispatcher_.SetSeviceContainer(&service_container_);
|
||||
|
||||
spdlog::debug("Extension services initialized");
|
||||
}
|
||||
|
||||
void LspServer::SendError(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
|
||||
void LspServer::SendError(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message)
|
||||
{
|
||||
spdlog::warn("Sending error response - method: {}, code: {}, message: {}", request.method, static_cast<int>(code), message);
|
||||
std::string error_response = dispatcher_.BuildErrorResponseMessage(request, code, message);
|
||||
std::string error_response = providers::BuildErrorResponseMessage(request, code, message);
|
||||
SendResponse(error_response);
|
||||
}
|
||||
|
||||
void LspServer::SendStateError(const protocol::RequestMessage& request)
|
||||
{
|
||||
if (!is_initialized_)
|
||||
SendError(request, protocol::ErrorCode::kServerNotInitialized, "Server not initialized");
|
||||
SendError(request, protocol::ErrorCodes::kServerNotInitialized, "Server not initialized");
|
||||
else if (is_shutting_down_)
|
||||
SendError(request, protocol::ErrorCode::kInvalidRequest, "Server is shutting down, only 'exit' is allowed");
|
||||
SendError(request, protocol::ErrorCodes::kInvalidRequest, "Server is shutting down, only 'exit' is allowed");
|
||||
else
|
||||
SendError(request, protocol::ErrorCode::kInternalError, "Request not allowed in current state");
|
||||
SendError(request, protocol::ErrorCodes::kInternalError, "Request not allowed in current state");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
#pragma once
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include "./dispacther.hpp"
|
||||
#include "../scheduler/request_scheduler.hpp"
|
||||
#include "../provider/base/provider_registry.hpp"
|
||||
#include "../scheduler/request.hpp"
|
||||
|
||||
namespace lsp::core
|
||||
{
|
||||
|
|
@ -46,13 +44,13 @@ namespace lsp::core
|
|||
private:
|
||||
void InitializeCoreServices();
|
||||
void InitializeExtensionServices();
|
||||
void SendError(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
|
||||
void SendError(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message);
|
||||
void SendStateError(const protocol::RequestMessage& request);
|
||||
|
||||
private:
|
||||
RequestDispatcher dispatcher_;
|
||||
scheduler::RequestScheduler scheduler_;
|
||||
services::ServiceContainer service_container_;
|
||||
scheduler::Request request_scheduler_;
|
||||
service::Container service_container_;
|
||||
|
||||
std::atomic<bool> is_initialized_ = false;
|
||||
std::atomic<bool> is_shutting_down_ = false;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ namespace lsp::protocol
|
|||
struct TextDocumentContentChangeEvent
|
||||
{
|
||||
Range range;
|
||||
std::optional<uinteger> rangeLength;
|
||||
string text;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace lsp::protocol
|
||||
{
|
||||
enum class ErrorCode : int
|
||||
enum class ErrorCodes : int
|
||||
{
|
||||
kParseError = -32700,
|
||||
kInvalidRequest = -32600,
|
||||
|
|
@ -37,7 +37,7 @@ namespace lsp::protocol
|
|||
|
||||
struct ResponseError: Message
|
||||
{
|
||||
ErrorCode code;
|
||||
ErrorCodes code;
|
||||
string message;
|
||||
std::optional<LSPAny> data;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace lsp::protocol
|
|||
|
||||
struct SemanticTokensLegend
|
||||
{
|
||||
std::vector<string> tokenType;
|
||||
std::vector<string> tokenTypes;
|
||||
std::vector<string> tokenModifiers;
|
||||
};
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ namespace lsp::protocol
|
|||
|
||||
SemanticTokensLegend legend;
|
||||
std::optional<boolean> range;
|
||||
std::variant<Full, boolean> full;
|
||||
std::optional<std::variant<Full, boolean>> full;
|
||||
};
|
||||
|
||||
struct SemanticTokensRegistrationOptions : TextDocumentRegistrationOptions, SemanticTokensOptions, StaticRegistrationOptions
|
||||
|
|
@ -124,7 +124,7 @@ namespace lsp::protocol
|
|||
{
|
||||
uinteger start;
|
||||
uinteger deleteCount;
|
||||
std::optional<uinteger> data;
|
||||
std::optional<std::vector<uinteger>> data;
|
||||
};
|
||||
|
||||
struct SemanticTokensDelta
|
||||
|
|
|
|||
|
|
@ -52,6 +52,16 @@ namespace lsp::protocol
|
|||
std::optional<std::vector<DocumentSymbol>> children;
|
||||
};
|
||||
|
||||
struct SymbolInformation
|
||||
{
|
||||
string name;
|
||||
SymbolKind kind;
|
||||
std::optional<std::vector<SymbolTag>> tags;
|
||||
std::optional<boolean> deprecated;
|
||||
Location location;
|
||||
std::optional<string> containerName;
|
||||
};
|
||||
|
||||
struct DocumentSymbolClientCapabilities
|
||||
{
|
||||
struct SymbolKinds
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <exception>
|
||||
#include "../detail/basic_types.hpp"
|
||||
|
||||
namespace lsp::transform
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace lsp::transform
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<std::string> Serialize(const T& obj)
|
||||
inline std::optional<std::string> Serialize(const T& obj)
|
||||
{
|
||||
std::string json;
|
||||
auto ce = glz::write_json(obj, json);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
#include "./provider_interface.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
std::string IRequestProvider::BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
|
||||
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::string json;
|
||||
auto ec = glz::write_json(error, json);
|
||||
if (ec)
|
||||
{
|
||||
spdlog::error("Failed to serialize error response: {}", glz::format_error(ec, json));
|
||||
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"}})";
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../../scheduler/request.hpp"
|
||||
#include "../../service/base/container.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../scheduler/request_scheduler.hpp"
|
||||
#include "../../services/service_container.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
|
@ -22,15 +21,15 @@ namespace lsp::providers
|
|||
class ExecutionContext
|
||||
{
|
||||
public:
|
||||
ExecutionContext(LifecycleCallback lifecycle_callback, scheduler::RequestScheduler& scheduler, services::ServiceContainer& container) :
|
||||
lifecycle_callback_(lifecycle_callback), scheduler_(scheduler), service_container_(container) {}
|
||||
ExecutionContext(LifecycleCallback lifecycle_callback, scheduler::Request& scheduler, service::Container& container) :
|
||||
lifecycle_callback_(lifecycle_callback), request_scheduler_(scheduler), service_container_(container) {}
|
||||
|
||||
scheduler::RequestScheduler& GetScheduler() const { return scheduler_; }
|
||||
scheduler::Request& GetScheduler() const { return request_scheduler_; }
|
||||
|
||||
template<typename T>
|
||||
T& GetService() const
|
||||
{
|
||||
return service_container_.Get<T>();
|
||||
return service_container_.GetService<T>();
|
||||
}
|
||||
|
||||
void TriggerLifecycleEvent(ServerLifecycleEvent event) const
|
||||
|
|
@ -41,8 +40,8 @@ namespace lsp::providers
|
|||
|
||||
private:
|
||||
LifecycleCallback lifecycle_callback_;
|
||||
scheduler::RequestScheduler& scheduler_;
|
||||
services::ServiceContainer& service_container_;
|
||||
scheduler::Request& request_scheduler_;
|
||||
service::Container& service_container_;
|
||||
};
|
||||
|
||||
// LSP请求提供者接口基类
|
||||
|
|
@ -65,7 +64,6 @@ namespace lsp::providers
|
|||
|
||||
// 处理LSP请求
|
||||
virtual std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) = 0;
|
||||
static std::string BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message);
|
||||
};
|
||||
|
||||
// LSP 通知处理器接口
|
||||
|
|
@ -78,4 +76,5 @@ namespace lsp::providers
|
|||
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,15 +1,16 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./provider_registry.hpp"
|
||||
#include "../initialize/initialize_provider.hpp"
|
||||
#include "../initialized/initialized_provider.hpp"
|
||||
#include "../text_document/did_open_provider.hpp"
|
||||
#include "../text_document/did_change_provider.hpp"
|
||||
#include "../text_document/did_close_provider.hpp"
|
||||
#include "../text_document/completion_provider.hpp"
|
||||
#include "../trace/set_trace_provider.hpp"
|
||||
#include "../shutdown/shutdown_provider.hpp"
|
||||
#include "../cancel_request/cancel_request_provider.hpp"
|
||||
#include "../exit/exit_provider.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
|
||||
{
|
||||
|
|
@ -18,16 +19,19 @@ namespace lsp::providers
|
|||
{
|
||||
spdlog::info("Registering LSP providers...");
|
||||
|
||||
RegisterProvider<initialize::InitializeProvider>(dispatcher);
|
||||
RegisterProvider<initialized::InitializedProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidOpenProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidChangeProvider>(dispatcher);
|
||||
RegisterProvider<text_document::DidCloseProvider>(dispatcher);
|
||||
RegisterProvider<text_document::CompletionProvider>(dispatcher);
|
||||
RegisterProvider<set_trace::SetTraceProvider>(dispatcher);
|
||||
RegisterProvider<shutdown::ShutdownProvider>(dispatcher);
|
||||
RegisterProvider<cancel_request::CancelRequestProvider>(dispatcher);
|
||||
RegisterProvider<exit::ExitProvider>(dispatcher);
|
||||
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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace lsp::providers
|
|||
{
|
||||
auto provider = std::make_shared<ProviderClass>();
|
||||
dispatcher.RegisterRequestProvider(provider);
|
||||
spdlog::info("Registered request provider '{}' for method: {}", provider->GetProviderName(), provider->GetMethod());
|
||||
spdlog::info("Registered request provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
|
||||
}
|
||||
|
||||
// 注册通知处理器的模板函数
|
||||
|
|
@ -23,7 +23,7 @@ namespace lsp::providers
|
|||
{
|
||||
auto provider = std::make_shared<ProviderClass>();
|
||||
dispatcher.RegisterNotificationProvider(provider);
|
||||
spdlog::info("Registered notification provider '{}' for method: {}", provider->GetProviderName(), provider->GetMethod());
|
||||
spdlog::info("Registered notification provider [{}] for method: [{}]", provider->GetProviderName(), provider->GetMethod());
|
||||
}
|
||||
|
||||
// 批量注册provider
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./incoming_calls.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::call_hierarchy
|
||||
{
|
||||
std::string IncomingCalls::GetMethod() const
|
||||
{
|
||||
return "callHierarchy/incomingCalls";
|
||||
}
|
||||
|
||||
std::string IncomingCalls::GetProviderName() const
|
||||
{
|
||||
return "CallHierarchyIncomingCalls";
|
||||
}
|
||||
|
||||
std::string IncomingCalls::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("IncomingCallsProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::shutdown
|
||||
namespace lsp::providers::call_hierarchy
|
||||
{
|
||||
class ShutdownProvider : public IRequestProvider
|
||||
class IncomingCalls : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
ShutdownProvider() = default;
|
||||
IncomingCalls() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./outgoing_calls.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::call_hierarchy
|
||||
{
|
||||
std::string OutgoingCalls::GetMethod() const
|
||||
{
|
||||
return "callHierarchy/outgoingCalls";
|
||||
}
|
||||
|
||||
std::string OutgoingCalls::GetProviderName() const
|
||||
{
|
||||
return "CallHierarchyOutgoingCalls";
|
||||
}
|
||||
|
||||
std::string OutgoingCalls::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("OutgoingCallsProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::call_hierarchy
|
||||
{
|
||||
class OutgoingCalls : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
OutgoingCalls() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include "./cancel_request.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
std::string CancelRequest::GetMethod() const
|
||||
{
|
||||
return "$/cancelRequest";
|
||||
}
|
||||
|
||||
std::string CancelRequest::GetProviderName() const
|
||||
{
|
||||
return "CancelRequest";
|
||||
}
|
||||
|
||||
void CancelRequest::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("CancelRequestProvider: Providing response for method {}", notification.method);
|
||||
|
||||
auto params = transform::As<protocol::CancelParams>(notification.params.value());
|
||||
std::string id_to_cancel = transform::debug::GetIdString(params.id);
|
||||
spdlog::info("Processing cancel request for ID: {}", id_to_cancel);
|
||||
|
||||
auto& scheduler = context.GetScheduler();
|
||||
bool cancelled = scheduler.Cancel(id_to_cancel);
|
||||
spdlog::info("Cancel request {} result: {}", id_to_cancel, cancelled ? "success" : "not found");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
#pragma once
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../scheduler/request_scheduler.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::cancel_request
|
||||
namespace lsp::providers
|
||||
{
|
||||
class CancelRequestProvider : public INotificationProvider
|
||||
class CancelRequest : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
CancelRequest() = default;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#include "./cancel_request_provider.hpp"
|
||||
|
||||
namespace lsp::providers::cancel_request
|
||||
{
|
||||
std::string CancelRequestProvider::GetMethod() const
|
||||
{
|
||||
return "$/cancelRequest";
|
||||
}
|
||||
|
||||
std::string CancelRequestProvider::GetProviderName() const
|
||||
{
|
||||
return "CancelRequestProvider";
|
||||
}
|
||||
|
||||
void CancelRequestProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto params = transform::As<protocol::CancelParams>(notification.params.value());
|
||||
std::string id_to_cancel = transform::debug::GetIdString(params.id);
|
||||
spdlog::info("Processing cancel request for ID: {}", id_to_cancel);
|
||||
|
||||
auto& scheduler = context.GetScheduler();
|
||||
|
||||
bool cancelled = scheduler.Cancel(id_to_cancel);
|
||||
spdlog::info("Cancel request {} result: {}", id_to_cancel, cancelled ? "success" : "not found");
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
spdlog::error("Error handling cancel request: {}", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./register_capability.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::client
|
||||
{
|
||||
std::string RegisterCapability::GetMethod() const
|
||||
{
|
||||
return "client/registerCapability";
|
||||
}
|
||||
|
||||
std::string RegisterCapability::GetProviderName() const
|
||||
{
|
||||
return "ClientRegisterCapability";
|
||||
}
|
||||
|
||||
std::string RegisterCapability::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("RegisterCapabilityProvider: Providing response for method {}", request.method);
|
||||
// 这个方法通常不会被调用,因为这是服务器发起的请求
|
||||
// 但为了完整性还是实现它
|
||||
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = std::nullopt; // 成功返回null
|
||||
|
||||
std::optional<std::string> json = transform::Serialize(response);
|
||||
if (!json.has_value())
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Internal error");
|
||||
return json.value();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
|
||||
namespace lsp::providers::client
|
||||
{
|
||||
class RegisterCapability : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
RegisterCapability() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./unregister_capability.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::client
|
||||
{
|
||||
std::string UnregisterCapability::GetMethod() const
|
||||
{
|
||||
return "client/unregisterCapability";
|
||||
}
|
||||
|
||||
std::string UnregisterCapability::GetProviderName() const
|
||||
{
|
||||
return "ClientUnregisterCapability";
|
||||
}
|
||||
|
||||
std::string UnregisterCapability::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("UnregisterCapabilityProvider: Providing response for method {}", request.method);
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = std::nullopt;
|
||||
|
||||
std::optional<std::string> json = transform::Serialize(response);
|
||||
if (!json.has_value())
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Internal error");
|
||||
return json.value();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
|
||||
namespace lsp::providers::client
|
||||
{
|
||||
class UnregisterCapability : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
UnregisterCapability() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./resolve.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::code_action
|
||||
{
|
||||
std::string Resolve::GetMethod() const
|
||||
{
|
||||
return "codeAction/resolve";
|
||||
}
|
||||
|
||||
std::string Resolve::GetProviderName() const
|
||||
{
|
||||
return "CodeActionResolve";
|
||||
}
|
||||
|
||||
std::string Resolve::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("CodeActionResolveProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::code_action
|
||||
{
|
||||
class Resolve : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Resolve() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./resolve.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::code_lens
|
||||
{
|
||||
std::string Resolve::GetMethod() const
|
||||
{
|
||||
return "codeLens/resolve";
|
||||
}
|
||||
|
||||
std::string Resolve::GetProviderName() const
|
||||
{
|
||||
return "CodeLensResolve";
|
||||
}
|
||||
|
||||
std::string Resolve::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("CodeLensResolveProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::code_lens
|
||||
{
|
||||
class Resolve : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Resolve() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./resolve.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
#include "../../service/symbol.hpp"
|
||||
|
||||
namespace lsp::providers::completion_item
|
||||
{
|
||||
std::string Resolve::GetMethod() const
|
||||
{
|
||||
return "completionItem/resolve";
|
||||
}
|
||||
|
||||
std::string Resolve::GetProviderName() const
|
||||
{
|
||||
return "CompletionItemResolve";
|
||||
}
|
||||
|
||||
std::string Resolve::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("CompletionItemResolveProvider: Providing response for method {}", request.method);
|
||||
|
||||
if (!request.params.has_value())
|
||||
{
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
// 解析补全项参数
|
||||
protocol::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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
spdlog::debug("{}: Item '{}' already resolved", GetProviderName(), item.label);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// 根据补全项类型添加详细信息
|
||||
if (!resolved.detail.has_value())
|
||||
{
|
||||
resolved.detail = GetDetailedSignature(item.label,
|
||||
item.kind.value_or(protocol::CompletionItemKind::kText),
|
||||
context);
|
||||
}
|
||||
|
||||
// 添加文档
|
||||
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)
|
||||
{
|
||||
std::stringstream doc;
|
||||
|
||||
// 根据类型获取文档
|
||||
if (item.kind == protocol::CompletionItemKind::kKeyword)
|
||||
{
|
||||
// 关键字文档
|
||||
std::string keyword_doc = GetKeywordDocumentation(item.label);
|
||||
if (!keyword_doc.empty())
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
||||
// 添加代码示例
|
||||
std::string example = GenerateCodeExample(item.label, *item.kind);
|
||||
if (!example.empty())
|
||||
{
|
||||
doc << "\n\n**Example:**\n```tsf\n"
|
||||
<< example << "\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)
|
||||
{
|
||||
// 变量/常量文档
|
||||
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.";
|
||||
}
|
||||
|
||||
return doc.str();
|
||||
}
|
||||
|
||||
std::string Resolve::GetDetailedSignature(const std::string& name, protocol::CompletionItemKind kind, ExecutionContext& context)
|
||||
{
|
||||
// 尝试从符号服务获取签名
|
||||
auto symbol = FindSymbolDetails(name, context);
|
||||
if (symbol.has_value() && symbol->detail.has_value())
|
||||
{
|
||||
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())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::completion_item
|
||||
{
|
||||
class Resolve : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Resolve() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
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);
|
||||
};
|
||||
|
||||
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```" }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./resolve.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::document_link
|
||||
{
|
||||
std::string Resolve::GetMethod() const
|
||||
{
|
||||
return "documentLink/resolve";
|
||||
}
|
||||
|
||||
std::string Resolve::GetProviderName() const
|
||||
{
|
||||
return "DocumentLinkResolve";
|
||||
}
|
||||
|
||||
std::string Resolve::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("DocumentLinkResolveProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::document_link
|
||||
{
|
||||
class Resolve : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Resolve() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,21 +1,20 @@
|
|||
#include "./exit_provider.hpp"
|
||||
#include "./exit.hpp"
|
||||
|
||||
namespace lsp::providers::exit
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
std::string ExitProvider::GetMethod() const
|
||||
std::string Exit::GetMethod() const
|
||||
{
|
||||
return "exit";
|
||||
}
|
||||
|
||||
std::string ExitProvider::GetProviderName() const
|
||||
std::string Exit::GetProviderName() const
|
||||
{
|
||||
return "ExitProvider";
|
||||
return "Exit";
|
||||
}
|
||||
|
||||
void ExitProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
void Exit::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
// static_cast<void>(context);
|
||||
spdlog::debug("ExitProvider: Providing response for method {}", notification.method);
|
||||
spdlog::info("Exit notification received");
|
||||
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::set_trace
|
||||
namespace lsp::providers
|
||||
{
|
||||
class SetTraceProvider : public INotificationProvider
|
||||
class Exit : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
SetTraceProvider() = default;
|
||||
Exit() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./initialize.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
std::string Initialize::GetMethod() const
|
||||
{
|
||||
return "initialize";
|
||||
}
|
||||
|
||||
std::string Initialize::GetProviderName() const
|
||||
{
|
||||
return "Initialize";
|
||||
}
|
||||
|
||||
std::string Initialize::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(BuildInitializeResult());
|
||||
std::optional<std::string> json = transform::Serialize(response);
|
||||
if (!json.has_value())
|
||||
{
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kInitializeFailed);
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Internal error");
|
||||
}
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kInitialized);
|
||||
return json.value();
|
||||
}
|
||||
|
||||
protocol::InitializeResult Initialize::BuildInitializeResult()
|
||||
{
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
namespace lsp::providers
|
||||
{
|
||||
using namespace lsp;
|
||||
class InitializeProvider : public IRequestProvider
|
||||
class Initialize : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
InitializeProvider() = default;
|
||||
Initialize() = default;
|
||||
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./initialize_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::initialize
|
||||
{
|
||||
std::string InitializeProvider::GetMethod() const
|
||||
{
|
||||
return "initialize";
|
||||
}
|
||||
|
||||
std::string InitializeProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializeProvider";
|
||||
}
|
||||
|
||||
std::string InitializeProvider::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", request.method);
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(BuildInitializeResult());
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
if (ec)
|
||||
{
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kInitializeFailed);
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
|
||||
}
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kInitialized);
|
||||
return json;
|
||||
}
|
||||
|
||||
protocol::InitializeResult InitializeProvider::BuildInitializeResult()
|
||||
{
|
||||
protocol::InitializeResult result;
|
||||
result.serverInfo.name = "TSL Language Server";
|
||||
result.serverInfo.version = "1.0.0";
|
||||
protocol::TextDocumentSyncOptions opts;
|
||||
opts.openClose = true;
|
||||
opts.change = protocol::TextDocumentSyncKind::kIncremental;
|
||||
protocol::CompletionOptions completion_provider;
|
||||
completion_provider.resolveProvider = false;
|
||||
|
||||
result.capabilities.textDocumentSync = opts;
|
||||
result.capabilities.completionProvider = completion_provider;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./initialized.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
|
||||
std::string Initialized::GetMethod() const
|
||||
{
|
||||
return "initialized";
|
||||
}
|
||||
|
||||
std::string Initialized::GetProviderName() const
|
||||
{
|
||||
return "Initialized";
|
||||
}
|
||||
|
||||
void Initialized::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context); // 如果不需要上下文,可以忽略
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", notification.method);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
class Initialized : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
Initialized() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./initialized_provider.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
|
||||
std::string InitializedProvider::GetMethod() const
|
||||
{
|
||||
return "initialized";
|
||||
}
|
||||
|
||||
std::string InitializedProvider::GetProviderName() const
|
||||
{
|
||||
return "InitializedProvider";
|
||||
}
|
||||
|
||||
void InitializedProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context); // 如果不需要上下文,可以忽略
|
||||
spdlog::debug("InitializeProvider: Providing response for method {}", notification.method);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::initialized
|
||||
{
|
||||
class InitializedProvider : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
InitializedProvider() = default;
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./resolve.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::inlay_hint
|
||||
{
|
||||
std::string Resolve::GetMethod() const
|
||||
{
|
||||
return "inlayHint/resolve";
|
||||
}
|
||||
|
||||
std::string Resolve::GetProviderName() const
|
||||
{
|
||||
return "InlayHintResolve";
|
||||
}
|
||||
|
||||
std::string Resolve::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("InlayHintResolveProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::inlay_hint
|
||||
{
|
||||
class Resolve : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Resolve() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./shutdown.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
std::string Shutdown::GetMethod() const
|
||||
{
|
||||
return "shutdown";
|
||||
}
|
||||
|
||||
std::string Shutdown::GetProviderName() const
|
||||
{
|
||||
return "Shutdown";
|
||||
}
|
||||
|
||||
std::string Shutdown::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("ShutdownProvider: Providing response for method {}", request.method);
|
||||
|
||||
// 触发关闭事件
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kShuttingDown);
|
||||
|
||||
// 构建响应 - shutdown 返回 null
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
auto json = transform::Serialize(response);
|
||||
if (!json.has_value())
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Failed to serialize response");
|
||||
spdlog::info("Shutdown request processed successfully");
|
||||
return json.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers
|
||||
{
|
||||
class Shutdown : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Shutdown() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./shutdown_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::shutdown
|
||||
{
|
||||
std::string ShutdownProvider::GetMethod() const
|
||||
{
|
||||
return "shutdown";
|
||||
}
|
||||
|
||||
std::string ShutdownProvider::GetProviderName() const
|
||||
{
|
||||
return "ShutdownProvider";
|
||||
}
|
||||
|
||||
std::string ShutdownProvider::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("ShutdownProvider: Providing response for method {}", request.method);
|
||||
|
||||
try
|
||||
{
|
||||
// 触发关闭事件
|
||||
context.TriggerLifecycleEvent(ServerLifecycleEvent::kShuttingDown);
|
||||
|
||||
// 构建响应 - shutdown 返回 null
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
if (ec)
|
||||
{
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Failed to serialize response");
|
||||
}
|
||||
|
||||
spdlog::info("Shutdown request processed successfully");
|
||||
return json;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
spdlog::error("Shutdown request failed: {}", e.what());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./event.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::telemetry
|
||||
{
|
||||
std::string Event::GetMethod() const
|
||||
{
|
||||
return "telemetry/event";
|
||||
}
|
||||
|
||||
std::string Event::GetProviderName() const
|
||||
{
|
||||
return "TelemetryEvent";
|
||||
}
|
||||
|
||||
void Event::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("TelemetryEventProvider: Handling notification for method {}", notification.method);
|
||||
|
||||
// TODO: Implement the actual notification handling logic
|
||||
// 1. Parse notification parameters
|
||||
// 2. Update appropriate services/state
|
||||
// 3. Trigger any necessary side effects
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::telemetry
|
||||
{
|
||||
class Event : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
Event() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./code_action.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string CodeAction::GetMethod() const
|
||||
{
|
||||
return "textDocument/codeAction";
|
||||
}
|
||||
|
||||
std::string CodeAction::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentCodeAction";
|
||||
}
|
||||
|
||||
std::string CodeAction::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("TextDocumentCodeActionProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class CodeAction : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
CodeAction() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./code_lens.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string CodeLens::GetMethod() const
|
||||
{
|
||||
return "textDocument/codeLens";
|
||||
}
|
||||
|
||||
std::string CodeLens::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentCodeLens";
|
||||
}
|
||||
|
||||
std::string CodeLens::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentCodeLensProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class CodeLens : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
CodeLens() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./color_presentation.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string ColorPresentation::GetMethod() const
|
||||
{
|
||||
return "textDocument/colorPresentation";
|
||||
}
|
||||
|
||||
std::string ColorPresentation::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentColorPresentation";
|
||||
}
|
||||
|
||||
std::string ColorPresentation::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentColorPresentationProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class ColorPresentation : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
ColorPresentation() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./completion.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
#include "../../service/symbol.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Completion::GetMethod() const
|
||||
{
|
||||
return "textDocument/completion";
|
||||
}
|
||||
|
||||
std::string Completion::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentCompletion";
|
||||
}
|
||||
|
||||
std::string Completion::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentCompletionProvider: Providing response for method {}", request.method);
|
||||
|
||||
// 验证请求是否包含参数
|
||||
if (!request.params.has_value())
|
||||
{
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
// 从 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();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 获取补全前缀
|
||||
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);
|
||||
|
||||
// 如果提供了 context,可以使用其中的信息
|
||||
if (params.context.has_value())
|
||||
{
|
||||
spdlog::trace("{}: Trigger kind: {}", GetProviderName(), static_cast<int>(params.context->triggerKind));
|
||||
if (params.context->triggerCharacter.has_value())
|
||||
spdlog::trace("{}: Trigger character: '{}'", GetProviderName(), params.context->triggerCharacter.value());
|
||||
}
|
||||
|
||||
// 收集所有补全项
|
||||
std::vector<protocol::CompletionItem> 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());
|
||||
|
||||
auto symbol_items = ProvideSymbolCompletions(params.textDocument.uri, prefix, context);
|
||||
all_items.insert(all_items.end(), symbol_items.begin(), symbol_items.end());
|
||||
|
||||
auto snippet_items = ProvideSnippetCompletions(completion_context);
|
||||
all_items.insert(all_items.end(), snippet_items.begin(), snippet_items.end());
|
||||
}
|
||||
|
||||
// 构建补全列表
|
||||
protocol::CompletionList result;
|
||||
result.isIncomplete = false; // 表示这是完整的补全列表
|
||||
result.items = std::move(all_items);
|
||||
|
||||
spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Completion::ExtractPrefix(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context)
|
||||
{
|
||||
auto& document_service = context.GetService<service::Document>();
|
||||
auto content = document_service.GetContent(uri);
|
||||
if (!content.has_value())
|
||||
return "";
|
||||
|
||||
size_t line_start = 0;
|
||||
size_t current_line = 0;
|
||||
|
||||
for (size_t i = 0; i < content->length(); i++)
|
||||
{
|
||||
if (current_line == position.line)
|
||||
{
|
||||
line_start = i;
|
||||
break;
|
||||
}
|
||||
if ((*content)[i] == '\n')
|
||||
{
|
||||
current_line++;
|
||||
}
|
||||
}
|
||||
|
||||
size_t cursor_pos = line_start + position.character;
|
||||
if (cursor_pos > content->length())
|
||||
cursor_pos = content->length();
|
||||
|
||||
size_t prefix_start = cursor_pos;
|
||||
while (prefix_start > line_start)
|
||||
{
|
||||
char ch = (*content)[prefix_start - 1];
|
||||
if (!std::isalnum(ch) && ch != '_')
|
||||
break;
|
||||
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)
|
||||
{
|
||||
auto& document_service = context.GetService<service::Document>();
|
||||
|
||||
auto content = document_service.GetContent(uri);
|
||||
if (!content.has_value())
|
||||
return "";
|
||||
|
||||
size_t line_start = 0;
|
||||
size_t line_end = content->length();
|
||||
size_t current_line = 0;
|
||||
|
||||
for (size_t i = 0; i < content->length(); i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((*content)[i] == '\n')
|
||||
{
|
||||
current_line++;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
protocol::CompletionItem item;
|
||||
item.label = tslItem.label;
|
||||
item.kind = protocol::CompletionItemKind::kKeyword;
|
||||
item.detail = "TSL Keyword";
|
||||
|
||||
// 创建文档内容
|
||||
protocol::MarkupContent documentation;
|
||||
documentation.kind = protocol::MarkupKindLiterals::PlainText;
|
||||
documentation.value = "TSL language keyword";
|
||||
item.documentation = documentation;
|
||||
|
||||
item.insertText = tslItem.label;
|
||||
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> Completion::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
|
||||
{
|
||||
spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);
|
||||
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// TODO: 基于上下文提供补全
|
||||
// 示例:添加一个变量补全
|
||||
if (!prefix.empty() && prefix[0] == '$')
|
||||
{
|
||||
protocol::CompletionItem varItem;
|
||||
varItem.label = "$myVariable";
|
||||
varItem.kind = protocol::CompletionItemKind::kVariable;
|
||||
varItem.detail = "Local variable";
|
||||
varItem.insertText = "$myVariable";
|
||||
|
||||
protocol::MarkupContent doc;
|
||||
doc.kind = protocol::MarkupKindLiterals::Markdown;
|
||||
doc.value = "Example variable completion";
|
||||
varItem.documentation = doc;
|
||||
|
||||
items.push_back(varItem);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../language/tsl_keywords.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
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;
|
||||
|
||||
private:
|
||||
// 构建完整的补全响应
|
||||
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);
|
||||
|
||||
protocol::CompletionItem SymbolToCompletionItem(const protocol::DocumentSymbol& symbol);
|
||||
bool IsMemberCompletion(const std::string& context);
|
||||
std::string ExtractObjectName(const std::string& context);
|
||||
|
||||
private:
|
||||
tsl::TslKeywords tsl_keywords_;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./completion_provider.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string CompletionProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/completion";
|
||||
}
|
||||
|
||||
std::string CompletionProvider::GetProviderName() const
|
||||
{
|
||||
return "CompletionProvider";
|
||||
}
|
||||
|
||||
std::string CompletionProvider::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("CompletionProvider: Providing response for method {}", request.method);
|
||||
|
||||
try {
|
||||
// 验证请求是否包含参数
|
||||
if (!request.params.has_value())
|
||||
{
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
// 从 variant 中提取参数
|
||||
protocol::CompletionParams completion_params = transform::As<protocol::CompletionParams>(request.params.value());
|
||||
protocol::CompletionList completion_list = BuildCompletionResponse(completion_params);
|
||||
|
||||
// 构建响应消息
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
response.result = transform::LSPAny(completion_list);
|
||||
|
||||
std::string json;
|
||||
auto ec = glz::write_json(response, json);
|
||||
if (ec) {
|
||||
spdlog::error("{}: Failed to serialize response: {}", GetProviderName(), glz::format_error(ec, json));
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Failed to serialize response");
|
||||
}
|
||||
|
||||
return json;
|
||||
|
||||
} catch (const transform::ConversionError& e) {
|
||||
spdlog::error("{}: Failed to convert params: {}", GetProviderName(), e.what());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Invalid completion params");
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("{}: Unexpected error: {}", GetProviderName(), e.what());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protocol::CompletionList CompletionProvider::BuildCompletionResponse(const protocol::CompletionParams& params)
|
||||
{
|
||||
spdlog::trace("{}: Processing completion request for URI='{}', Position=({}, {})",
|
||||
GetProviderName(),
|
||||
params.textDocument.uri,
|
||||
params.position.line,
|
||||
params.position.character);
|
||||
|
||||
// 获取补全前缀
|
||||
std::string prefix = ExtractPrefix(params.textDocument, params.position);
|
||||
|
||||
// 如果提供了 context,可以使用其中的信息
|
||||
if (params.context.has_value())
|
||||
{
|
||||
spdlog::trace("{}: Trigger kind: {}", GetProviderName(), static_cast<int>(params.context->triggerKind));
|
||||
if (params.context->triggerCharacter.has_value())
|
||||
spdlog::trace("{}: Trigger character: '{}'", GetProviderName(), params.context->triggerCharacter.value());
|
||||
}
|
||||
|
||||
// 收集所有补全项
|
||||
std::vector<protocol::CompletionItem> allItems;
|
||||
|
||||
// 添加关键字补全
|
||||
auto keywordItems = ProvideKeywordCompletions(prefix);
|
||||
allItems.insert(allItems.end(), keywordItems.begin(), keywordItems.end());
|
||||
|
||||
// 添加上下文相关补全
|
||||
auto contextualItems = ProvideContextualCompletions(params.textDocument, params.position, prefix);
|
||||
allItems.insert(allItems.end(), contextualItems.begin(), contextualItems.end());
|
||||
|
||||
// 构建补全列表
|
||||
protocol::CompletionList result;
|
||||
result.isIncomplete = false; // 表示这是完整的补全列表
|
||||
result.items = std::move(allItems);
|
||||
|
||||
spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CompletionProvider::ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position)
|
||||
{
|
||||
// TODO: 实现从文档内容和位置计算前缀
|
||||
// 这需要访问文档管理器来获取文档内容
|
||||
// 现在返回空字符串
|
||||
spdlog::trace("{}: ExtractPrefix not implemented, returning empty string", GetProviderName());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideKeywordCompletions(const std::string& prefix)
|
||||
{
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// 从 tsl_keywords_ 获取补全项
|
||||
auto tslItems = tsl_keywords_.GetCompletionItems(prefix);
|
||||
|
||||
for (const auto& tslItem : tslItems) {
|
||||
protocol::CompletionItem item;
|
||||
item.label = tslItem.label;
|
||||
item.kind = protocol::CompletionItemKind::kKeyword;
|
||||
item.detail = "TSL Keyword";
|
||||
|
||||
// 创建文档内容
|
||||
protocol::MarkupContent documentation;
|
||||
documentation.kind = protocol::MarkupKindLiterals::PlainText;
|
||||
documentation.value = "TSL language keyword";
|
||||
item.documentation = documentation;
|
||||
|
||||
item.insertText = tslItem.label;
|
||||
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<protocol::CompletionItem> CompletionProvider::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
|
||||
{
|
||||
spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);
|
||||
|
||||
std::vector<protocol::CompletionItem> items;
|
||||
|
||||
// TODO: 基于上下文提供补全
|
||||
// 示例:添加一个变量补全
|
||||
if (!prefix.empty() && prefix[0] == '$')
|
||||
{
|
||||
protocol::CompletionItem varItem;
|
||||
varItem.label = "$myVariable";
|
||||
varItem.kind = protocol::CompletionItemKind::kVariable;
|
||||
varItem.detail = "Local variable";
|
||||
varItem.insertText = "$myVariable";
|
||||
|
||||
protocol::MarkupContent doc;
|
||||
doc.kind = protocol::MarkupKindLiterals::Markdown;
|
||||
doc.value = "Example variable completion";
|
||||
varItem.documentation = doc;
|
||||
|
||||
items.push_back(varItem);
|
||||
}
|
||||
|
||||
spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../base/provider_interface.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../language/tsl_keywords.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class CompletionProvider : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
CompletionProvider() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
|
||||
private:
|
||||
// 构建完整的补全响应
|
||||
protocol::CompletionList BuildCompletionResponse(const protocol::CompletionParams& params);
|
||||
|
||||
// 获取补全前缀(从文档内容和位置计算)
|
||||
std::string ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position);
|
||||
|
||||
// 提供不同类型的补全
|
||||
std::vector<protocol::CompletionItem> ProvideKeywordCompletions(const std::string& prefix);
|
||||
std::vector<protocol::CompletionItem> ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix);
|
||||
|
||||
private:
|
||||
tsl::TslKeywords tsl_keywords_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./definition.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Definition::GetMethod() const
|
||||
{
|
||||
return "textDocument/definition";
|
||||
}
|
||||
|
||||
std::string Definition::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDefinition";
|
||||
}
|
||||
|
||||
std::string Definition::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentDefinitionProvider: Providing response for method {}", request.method);
|
||||
|
||||
if (!request.params.has_value())
|
||||
{
|
||||
spdlog::warn("{}: Missing params in request", GetProviderName());
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInvalidParams, "Missing params");
|
||||
}
|
||||
|
||||
protocol::DefinitionParams params = transform::As<protocol::DefinitionParams>(request.params.value());
|
||||
|
||||
auto location = BuildDefinitionResponse(params, context);
|
||||
|
||||
protocol::ResponseMessage response;
|
||||
response.id = request.id;
|
||||
|
||||
if (location.has_value())
|
||||
{
|
||||
response.result = transform::LSPAny(*location);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.result = std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> json = transform::Serialize(response);
|
||||
if (!json.has_value())
|
||||
return BuildErrorResponseMessage(request, protocol::ErrorCodes::kInternalError, "Failed to serialize response");
|
||||
return json.value();
|
||||
}
|
||||
|
||||
std::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{};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <tree_sitter/api.h>
|
||||
}
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Definition : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Definition() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
|
||||
private:
|
||||
std::optional<protocol::Location> BuildDefinitionResponse(const protocol::DefinitionParams& params, ExecutionContext& context);
|
||||
std::optional<protocol::Location> FindLocalDefinition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
|
||||
std::string GetIdentifierAtPosition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
|
||||
|
||||
TSNode FindDefinitionNode(TSNode root, const std::string& identifier, const std::string& content);
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const char* kUnit = "unit";
|
||||
constexpr const char* kInterfaceSection = "interface_section";
|
||||
constexpr const char* kImplementationSection = "implementation_section";
|
||||
constexpr const char* kFunctionDefinition = "function_definition_statement";
|
||||
constexpr const char* kFunctionDeclaration = "function_declaration_statement";
|
||||
constexpr const char* kClassDefinition = "class_definition_statement";
|
||||
constexpr const char* kVarStatement = "var_statement";
|
||||
constexpr const char* kConstStatement = "const_statement";
|
||||
constexpr const char* kIdentifier = "identifier";
|
||||
constexpr const char* kMethodWithImplementation = "method_with_implementation";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./diagnostic.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Diagnostic::GetMethod() const
|
||||
{
|
||||
return "textDocument/diagnostic";
|
||||
}
|
||||
|
||||
std::string Diagnostic::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDiagnostic";
|
||||
}
|
||||
|
||||
std::string Diagnostic::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("TextDocumentDiagnosticProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Diagnostic : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Diagnostic() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./did_change.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidChange::GetMethod() const
|
||||
{
|
||||
return "textDocument/didChange";
|
||||
}
|
||||
|
||||
std::string DidChange::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDidChange";
|
||||
}
|
||||
|
||||
void DidChange::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentDidChangeProvider: Providing response for method {}", notification.method);
|
||||
|
||||
protocol::DidChangeTextDocumentParams did_change_text_document_params = transform::As<protocol::DidChangeTextDocumentParams>(notification.params.value());
|
||||
|
||||
service::Document& document_service = context.GetService<service::Document>();
|
||||
document_service.UpdateDocument(did_change_text_document_params);
|
||||
|
||||
spdlog::info("Document updated: {}", did_change_text_document_params.textDocument.uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidCloseProvider : public INotificationProvider
|
||||
class DidChange : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
DidCloseProvider() = default;
|
||||
DidChange() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./did_change_provider.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../services/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidChangeProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didChange";
|
||||
}
|
||||
|
||||
std::string DidChangeProvider::GetProviderName() const
|
||||
{
|
||||
return "DidChangeProvider";
|
||||
}
|
||||
|
||||
void DidChangeProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("DidChangeProvider: Providing response for method {}", notification.method);
|
||||
|
||||
protocol::DidChangeTextDocumentParams did_change_text_document_params = transform::As<protocol::DidChangeTextDocumentParams>(notification.params.value());
|
||||
|
||||
services::DocumentService& document_service = context.GetService<services::DocumentService>();
|
||||
document_service.UpdateDocument(did_change_text_document_params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./did_close.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidClose::GetMethod() const
|
||||
{
|
||||
return "textDocument/didClose";
|
||||
}
|
||||
|
||||
std::string DidClose::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDidClose";
|
||||
}
|
||||
|
||||
void DidClose::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentDidCloseProvider: Providing response for method {}", notification.method);
|
||||
|
||||
protocol::DidCloseTextDocumentParams did_close_text_document_params = transform::As<protocol::DidCloseTextDocumentParams>(notification.params.value());
|
||||
|
||||
service::Document& document_service = context.GetService<service::Document>();
|
||||
document_service.CloseDocument(did_close_text_document_params);
|
||||
|
||||
spdlog::info("Document closed: {}", did_close_text_document_params.textDocument.uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidChangeProvider : public INotificationProvider
|
||||
class DidClose : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
DidChangeProvider() = default;
|
||||
DidClose() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./did_close_provider.hpp"
|
||||
#include "../../protocol/protocol.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../services/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
|
||||
std::string DidCloseProvider::GetMethod() const
|
||||
{
|
||||
return "textDocument/didClose";
|
||||
}
|
||||
|
||||
std::string DidCloseProvider::GetProviderName() const
|
||||
{
|
||||
return "DidCloseProvider";
|
||||
}
|
||||
|
||||
void DidCloseProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("DidCloseProvider: Providing response for method {}", notification.method);
|
||||
|
||||
protocol::DidCloseTextDocumentParams did_close_text_document_params = transform::As<protocol::DidCloseTextDocumentParams>(notification.params.value());
|
||||
|
||||
services::DocumentService& document_service = context.GetService<services::DocumentService>();
|
||||
document_service.CloseDocument(did_close_text_document_params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,27 +1,27 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./did_open_provider.hpp"
|
||||
#include "../../services/document.hpp"
|
||||
#include "./did_open.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
#include "../../service/document.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DidOpenProvider::GetMethod() const
|
||||
std::string DidOpen::GetMethod() const
|
||||
{
|
||||
return "textDocument/didOpen";
|
||||
}
|
||||
|
||||
std::string DidOpenProvider::GetProviderName() const
|
||||
std::string DidOpen::GetProviderName() const
|
||||
{
|
||||
return "DidOpenProvider";
|
||||
return "TextDocumentDidOpen";
|
||||
}
|
||||
|
||||
void DidOpenProvider::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
void DidOpen::HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("DidOpenProvider: Providing response for method {}", notification.method);
|
||||
spdlog::debug("TextDocumentDidOpenProvider: Providing response for method {}", notification.method);
|
||||
|
||||
protocol::DidOpenTextDocumentParams did_open_text_document_params = transform::As<protocol::DidOpenTextDocumentParams>(notification.params.value());
|
||||
|
||||
services::DocumentService& document_service = context.GetService<services::DocumentService>();
|
||||
service::Document& document_service = context.GetService<service::Document>();
|
||||
document_service.OpenDocument(did_open_text_document_params);
|
||||
|
||||
/*
|
||||
|
|
@ -34,6 +34,7 @@ namespace lsp::providers::text_document
|
|||
diagnosticService->diagnose(uri);
|
||||
}
|
||||
*/
|
||||
spdlog::info("Document opened: {}", did_open_text_document_params.textDocument.uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,10 +4,11 @@
|
|||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DidOpenProvider : public INotificationProvider
|
||||
class DidOpen : public INotificationProvider
|
||||
{
|
||||
public:
|
||||
DidOpenProvider() = default;
|
||||
DidOpen() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
void HandleNotification(const protocol::NotificationMessage& notification, ExecutionContext& context) override;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./document_color.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DocumentColor::GetMethod() const
|
||||
{
|
||||
return "textDocument/documentColor";
|
||||
}
|
||||
|
||||
std::string DocumentColor::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDocumentColor";
|
||||
}
|
||||
|
||||
std::string DocumentColor::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("TextDocumentDocumentColorProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DocumentColor : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
DocumentColor() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./document_highlight.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DocumentHighlight::GetMethod() const
|
||||
{
|
||||
return "textDocument/documentHighlight";
|
||||
}
|
||||
|
||||
std::string DocumentHighlight::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDocumentHighlight";
|
||||
}
|
||||
|
||||
std::string DocumentHighlight::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
static_cast<void>(context);
|
||||
spdlog::debug("TextDocumentDocumentHighlightProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DocumentHighlight : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
DocumentHighlight() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./document_link.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DocumentLink::GetMethod() const
|
||||
{
|
||||
return "textDocument/documentLink";
|
||||
}
|
||||
|
||||
std::string DocumentLink::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDocumentLink";
|
||||
}
|
||||
|
||||
std::string DocumentLink::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentDocumentLinkProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DocumentLink : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
DocumentLink() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./document_symbol.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string DocumentSymbol::GetMethod() const
|
||||
{
|
||||
return "textDocument/documentSymbol";
|
||||
}
|
||||
|
||||
std::string DocumentSymbol::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentDocumentSymbol";
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class DocumentSymbol : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
DocumentSymbol() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./folding_range.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string FoldingRange::GetMethod() const
|
||||
{
|
||||
return "textDocument/foldingRange";
|
||||
}
|
||||
|
||||
std::string FoldingRange::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentFoldingRange";
|
||||
}
|
||||
|
||||
std::string FoldingRange::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentFoldingRangeProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class FoldingRange : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
FoldingRange() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./formatting.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Formatting::GetMethod() const
|
||||
{
|
||||
return "textDocument/formatting";
|
||||
}
|
||||
|
||||
std::string Formatting::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentFormatting";
|
||||
}
|
||||
|
||||
std::string Formatting::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentFormattingProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Formatting : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Formatting() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./hover.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Hover::GetMethod() const
|
||||
{
|
||||
return "textDocument/hover";
|
||||
}
|
||||
|
||||
std::string Hover::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentHover";
|
||||
}
|
||||
|
||||
std::string Hover::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentHoverProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Hover : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Hover() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./implementation.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Implementation::GetMethod() const
|
||||
{
|
||||
return "textDocument/implementation";
|
||||
}
|
||||
|
||||
std::string Implementation::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentImplementation";
|
||||
}
|
||||
|
||||
std::string Implementation::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentImplementationProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Implementation : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Implementation() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./inlay_hint.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string InlayHint::GetMethod() const
|
||||
{
|
||||
return "textDocument/inlayHint";
|
||||
}
|
||||
|
||||
std::string InlayHint::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentInlayHint";
|
||||
}
|
||||
|
||||
std::string InlayHint::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentInlayHintProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class InlayHint : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
InlayHint() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./inline_value.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string InlineValue::GetMethod() const
|
||||
{
|
||||
return "textDocument/inlineValue";
|
||||
}
|
||||
|
||||
std::string InlineValue::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentInlineValue";
|
||||
}
|
||||
|
||||
std::string InlineValue::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentInlineValueProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class InlineValue : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
InlineValue() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./linked_editing_range.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string LinkedEditingRange::GetMethod() const
|
||||
{
|
||||
return "textDocument/linkedEditingRange";
|
||||
}
|
||||
|
||||
std::string LinkedEditingRange::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentLinkedEditingRange";
|
||||
}
|
||||
|
||||
std::string LinkedEditingRange::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentLinkedEditingRangeProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class LinkedEditingRange : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
LinkedEditingRange() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./moniker.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string Moniker::GetMethod() const
|
||||
{
|
||||
return "textDocument/moniker";
|
||||
}
|
||||
|
||||
std::string Moniker::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentMoniker";
|
||||
}
|
||||
|
||||
std::string Moniker::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentMonikerProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class Moniker : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
Moniker() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include <spdlog/spdlog.h>
|
||||
#include "./on_type_formatting.hpp"
|
||||
#include "../../protocol/transform/facade.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
std::string OnTypeFormatting::GetMethod() const
|
||||
{
|
||||
return "textDocument/onTypeFormatting";
|
||||
}
|
||||
|
||||
std::string OnTypeFormatting::GetProviderName() const
|
||||
{
|
||||
return "TextDocumentOnTypeFormatting";
|
||||
}
|
||||
|
||||
std::string OnTypeFormatting::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
|
||||
{
|
||||
spdlog::debug("TextDocumentOnTypeFormattingProvider: 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "../base/provider_interface.hpp"
|
||||
|
||||
namespace lsp::providers::text_document
|
||||
{
|
||||
class OnTypeFormatting : public IRequestProvider
|
||||
{
|
||||
public:
|
||||
OnTypeFormatting() = default;
|
||||
|
||||
std::string GetMethod() const override;
|
||||
std::string GetProviderName() const override;
|
||||
std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue