1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:37:35 +00:00

HackStudio: Map connections to langauge-servers by language name

HackStudio keeps a map that stores the different ServerConnection
instances we have open.

Previously, that map was indexed by a project's root path.
This did not make much sense because we only support opening a single
project with each instance of the HackStudio program.

We now index the different ServerConnections by the language name, which
allows us to support talking to multiple language-servers in the same
project (e.g C++ and Shell).

This also fixes an issue where if you first opened a Shell file, and
then a C++ file in the same project, then C++ language-server features
would not work.
This commit is contained in:
Itamar 2021-03-04 14:12:48 +02:00 committed by Andreas Kling
parent 289c466fef
commit 74070ef74d
3 changed files with 21 additions and 29 deletions

View file

@ -122,7 +122,7 @@ void LanguageClient::on_server_crash()
{ {
VERIFY(m_server_connection); VERIFY(m_server_connection);
auto project_path = m_server_connection->project_path(); auto project_path = m_server_connection->project_path();
ServerConnection::remove_instance_for_project(project_path); ServerConnection::remove_instance_for_language(project_path);
m_server_connection = nullptr; m_server_connection = nullptr;
auto notification = GUI::Notification::construct(); auto notification = GUI::Notification::construct();
@ -133,27 +133,16 @@ void LanguageClient::on_server_crash()
notification->show(); notification->show();
} }
HashMap<String, NonnullRefPtr<ServerConnection>> ServerConnection::s_instances_for_projects; HashMap<String, NonnullRefPtr<ServerConnection>> ServerConnection::s_instance_for_language;
RefPtr<ServerConnection> ServerConnection::instance_for_project(const String& project_path) void ServerConnection::set_instance_for_project(const String& language_name, NonnullRefPtr<ServerConnection>&& instance)
{ {
auto key = LexicalPath { project_path }.string(); s_instance_for_language.set(language_name, move(instance));
auto value = s_instances_for_projects.get(key);
if (!value.has_value())
return nullptr;
return *value.value();
} }
void ServerConnection::set_instance_for_project(const String& project_path, NonnullRefPtr<ServerConnection>&& instance) void ServerConnection::remove_instance_for_language(const String& language_name)
{ {
auto key = LexicalPath { project_path }.string(); s_instance_for_language.remove(language_name);
s_instances_for_projects.set(key, move(instance));
}
void ServerConnection::remove_instance_for_project(const String& project_path)
{
auto key = LexicalPath { project_path }.string();
s_instances_for_projects.remove(key);
} }
void ServerConnection::handle(const Messages::LanguageClient::DeclarationsInDocument& message) void ServerConnection::handle(const Messages::LanguageClient::DeclarationsInDocument& message)
{ {

View file

@ -69,24 +69,24 @@ public:
WeakPtr<LanguageClient> language_client() { return m_language_client; } WeakPtr<LanguageClient> language_client() { return m_language_client; }
const String& project_path() const { return m_project_path; } const String& project_path() const { return m_project_path; }
template<typename ConcreteType> template<typename LanguageServerType>
static NonnullRefPtr<ServerConnection> get_or_create(const String& project_path) static NonnullRefPtr<ServerConnection> get_or_create(const String& project_path)
{ {
auto key = LexicalPath { project_path }.string(); auto key = LanguageServerType::language_name();
if (auto instance = s_instances_for_projects.get(key); instance.has_value()) if (auto instance = s_instance_for_language.get(key); instance.has_value()) {
return *instance.value(); return *instance.value();
}
auto connection = ConcreteType::construct(project_path); auto connection = LanguageServerType::construct(project_path);
connection->handshake(); connection->handshake();
set_instance_for_project(project_path, *connection); set_instance_for_project(LanguageServerType::language_name(), *connection);
return *connection; return *connection;
} }
static RefPtr<ServerConnection> instance_for_project(const String& project_path); static void set_instance_for_project(const String& language_name, NonnullRefPtr<ServerConnection>&&);
static void set_instance_for_project(const String& project_path, NonnullRefPtr<ServerConnection>&&); static void remove_instance_for_language(const String& language_name);
static void remove_instance_for_project(const String& project_path);
virtual void die(); virtual void die() override;
protected: protected:
virtual void handle(const Messages::LanguageClient::AutoCompleteSuggestions&) override; virtual void handle(const Messages::LanguageClient::AutoCompleteSuggestions&) override;
@ -97,7 +97,7 @@ protected:
WeakPtr<LanguageClient> m_language_client; WeakPtr<LanguageClient> m_language_client;
private: private:
static HashMap<String, NonnullRefPtr<ServerConnection>> s_instances_for_projects; static HashMap<String, NonnullRefPtr<ServerConnection>> s_instance_for_language;
}; };
class LanguageClient : public Weakable<LanguageClient> { class LanguageClient : public Weakable<LanguageClient> {

View file

@ -32,10 +32,13 @@
#include <DevTools/HackStudio/LanguageServers/LanguageServerEndpoint.h> #include <DevTools/HackStudio/LanguageServers/LanguageServerEndpoint.h>
#include <LibIPC/ServerConnection.h> #include <LibIPC/ServerConnection.h>
#define LANGUAGE_CLIENT(namespace_, socket_name) \ #define LANGUAGE_CLIENT(language_name_, socket_name) \
namespace namespace_ { \ namespace language_name_ { \
class ServerConnection : public HackStudio::ServerConnection { \ class ServerConnection : public HackStudio::ServerConnection { \
C_OBJECT(ServerConnection) \ C_OBJECT(ServerConnection) \
public: \
static const char* language_name() { return #language_name_; } \
\
private: \ private: \
ServerConnection(const String& project_path) \ ServerConnection(const String& project_path) \
: HackStudio::ServerConnection("/tmp/portal/language/" #socket_name, project_path) \ : HackStudio::ServerConnection("/tmp/portal/language/" #socket_name, project_path) \