#pragma once #include #include #include #include namespace whetstone { class LSPCapabilityNegotiator { public: void registerSource(const std::string& source, const std::vector& caps) { caps_[source] = {caps.begin(), caps.end()}; } bool supports(const std::string& source, const std::string& capability) const { auto it = caps_.find(source); if (it == caps_.end()) return false; return it->second.count(capability) > 0; } // Returns true if the source supports the capability required by this method. // Unknown methods pass through (return true). bool shouldRoute(const std::string& source, const std::string& method) const { auto it = methodToCap_.find(method); if (it == methodToCap_.end()) return true; // unknown method: pass through return supports(source, it->second); } std::vector capabilitiesFor(const std::string& source) const { auto it = caps_.find(source); if (it == caps_.end()) return {}; return {it->second.begin(), it->second.end()}; } std::vector sourcesSupporting(const std::string& cap) const { std::vector result; for (const auto& [src, capSet] : caps_) if (capSet.count(cap)) result.push_back(src); return result; } private: std::map> caps_; const std::map methodToCap_ = { {"textDocument/hover", "hoverProvider"}, {"textDocument/definition", "definitionProvider"}, {"textDocument/references", "referencesProvider"}, {"textDocument/completion", "completionProvider"}, {"textDocument/rename", "renameProvider"}, {"textDocument/formatting", "documentFormattingProvider"}, }; }; } // namespace whetstone