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 concept AutoRegisterableProvider = HasMethod && HasProviderName && requires { { T::kAutoRegister } -> std::convertible_to; } && (std::derived_from || std::derived_from); template consteval bool HasDuplicateMethods() { std::array 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 class ProviderRegistry { public: static constexpr std::size_t kProviderCount = sizeof...(Providers); using ProviderList = std::tuple; static void RegisterAll(core::RequestDispatcher& dispatcher) { (RegisterProvider(dispatcher), ...); } private: static_assert(!HasDuplicateMethods(), "Duplicate method names detected in providers."); template static void RegisterProvider(core::RequestDispatcher& dispatcher) { auto provider = std::make_shared(); if constexpr (std::derived_from) { dispatcher.RegisterRequestProvider(provider); } else if constexpr (std::derived_from) { dispatcher.RegisterNotificationProvider(provider); } spdlog::debug("Registered provider [{}] for [{}]", Provider::kProviderName, Provider::kMethod); } }; }