tsl-devkit/lsp-server/src/provider/base/registry.cppm

73 lines
2.3 KiB
C++

module;
export module lsp.provider.base.registry;
import spdlog;
import std;
import lsp.core.dispacther;
import lsp.provider.base.interface;
export namespace lsp::provider
{
template<typename T>
concept AutoRegisterableProvider = HasMethod<T> && HasProviderName<T> &&
requires {
{ T::kAutoRegister } -> std::convertible_to<bool>;
} &&
(std::derived_from<T, core::IRequestProvider> ||
std::derived_from<T, core::INotificationProvider>);
template<AutoRegisterableProvider... Providers>
consteval bool HasDuplicateMethods()
{
std::array<std::string_view, sizeof...(Providers)> methods = { Providers::kMethod... };
for (std::size_t i = 0; i < methods.size(); ++i)
{
for (std::size_t j = i + 1; j < methods.size(); ++j)
{
if (methods[i] == methods[j])
{
return true;
}
}
}
return false;
}
template<AutoRegisterableProvider... Providers>
class ProviderRegistry
{
public:
static constexpr std::size_t kProviderCount = sizeof...(Providers);
using ProviderList = std::tuple<Providers...>;
static void RegisterAll(core::RequestDispatcher& dispatcher)
{
(RegisterProvider<Providers>(dispatcher), ...);
}
private:
static_assert(!HasDuplicateMethods<Providers...>(),
"Duplicate method names detected in providers.");
template<typename Provider>
static void RegisterProvider(core::RequestDispatcher& dispatcher)
{
auto provider = std::make_shared<Provider>();
if constexpr (std::derived_from<Provider, core::IRequestProvider>)
{
dispatcher.RegisterRequestProvider(provider);
}
else if constexpr (std::derived_from<Provider, core::INotificationProvider>)
{
dispatcher.RegisterNotificationProvider(provider);
}
spdlog::debug("Registered provider [{}] for [{}]",
Provider::kProviderName, Provider::kMethod);
}
};
}