1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 18:17:34 +00:00

Userland: Change IPC funcs to use plain arguments instead of a struct

Instead of having a single overloaded handle method each method gets
its own unique method name now.
This commit is contained in:
Gunnar Beutner 2021-05-02 19:54:34 +02:00 committed by Andreas Kling
parent d47f15ab8b
commit 065040872f
50 changed files with 897 additions and 839 deletions

View file

@ -14,22 +14,22 @@
namespace HackStudio {
void ServerConnection::handle(const Messages::LanguageClient::AutoCompleteSuggestions& message)
void ServerConnection::auto_complete_suggestions(const Vector<GUI::AutocompleteProvider::Entry>& suggestions)
{
if (!m_current_language_client) {
dbgln("Language Server connection has no attached language client");
return;
}
m_current_language_client->provide_autocomplete_suggestions(message.suggestions());
m_current_language_client->provide_autocomplete_suggestions(suggestions);
}
void ServerConnection::handle(const Messages::LanguageClient::DeclarationLocation& message)
void ServerConnection::declaration_location(const GUI::AutocompleteProvider::ProjectLocation& location)
{
if (!m_current_language_client) {
dbgln("Language Server connection has no attached language client");
return;
}
m_current_language_client->declaration_found(message.location().file, message.location().line, message.location().column);
m_current_language_client->declaration_found(location.file, location.line, location.column);
}
void ServerConnection::die()
@ -100,9 +100,9 @@ void LanguageClient::set_active_client()
HashMap<String, NonnullOwnPtr<ServerConnectionWrapper>> ServerConnectionInstances::s_instance_for_language;
void ServerConnection::handle(const Messages::LanguageClient::DeclarationsInDocument& message)
void ServerConnection::declarations_in_document(const String& filename, const Vector<GUI::AutocompleteProvider::Declaration>& declarations)
{
ProjectDeclarations::the().set_declared_symbols(message.filename(), message.declarations());
ProjectDeclarations::the().set_declared_symbols(filename, declarations);
}
void LanguageClient::search_declaration(const String& path, size_t line, size_t column)

View file

@ -47,9 +47,9 @@ public:
virtual void die() override;
protected:
virtual void handle(const Messages::LanguageClient::AutoCompleteSuggestions&) override;
virtual void handle(const Messages::LanguageClient::DeclarationLocation&) override;
virtual void handle(const Messages::LanguageClient::DeclarationsInDocument&) override;
virtual void auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> const&) override;
virtual void declaration_location(GUI::AutocompleteProvider::ProjectLocation const&) override;
virtual void declarations_in_document(String const&, Vector<GUI::AutocompleteProvider::Declaration> const&) override;
void set_wrapper(ServerConnectionWrapper& wrapper) { m_wrapper = &wrapper; }
String m_project_path;

View file

@ -30,10 +30,10 @@ void ClientConnection::die()
exit(0);
}
void ClientConnection::handle(const Messages::LanguageServer::Greet& message)
void ClientConnection::greet(String const& project_root)
{
m_filedb.set_project_root(message.project_root());
if (unveil(message.project_root().characters(), "r") < 0) {
m_filedb.set_project_root(project_root);
if (unveil(project_root.characters(), "r") < 0) {
perror("unveil");
exit(1);
}
@ -43,80 +43,79 @@ void ClientConnection::handle(const Messages::LanguageServer::Greet& message)
}
}
void ClientConnection::handle(const Messages::LanguageServer::FileOpened& message)
void ClientConnection::file_opened(String const& filename, IPC::File const& file)
{
if (m_filedb.is_open(message.filename())) {
if (m_filedb.is_open(filename)) {
return;
}
m_filedb.add(message.filename(), message.file().take_fd());
m_autocomplete_engine->file_opened(message.filename());
m_filedb.add(filename, file.take_fd());
m_autocomplete_engine->file_opened(filename);
}
void ClientConnection::handle(const Messages::LanguageServer::FileEditInsertText& message)
void ClientConnection::file_edit_insert_text(String const& filename, String const& text, i32 start_line, i32 start_column)
{
dbgln_if(LANGUAGE_SERVER_DEBUG, "InsertText for file: {}", message.filename());
dbgln_if(LANGUAGE_SERVER_DEBUG, "Text: {}", message.text());
dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{}]", message.start_line(), message.start_column());
m_filedb.on_file_edit_insert_text(message.filename(), message.text(), message.start_line(), message.start_column());
m_autocomplete_engine->on_edit(message.filename());
dbgln_if(LANGUAGE_SERVER_DEBUG, "InsertText for file: {}", filename);
dbgln_if(LANGUAGE_SERVER_DEBUG, "Text: {}", text);
dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{}]", start_line, start_column);
m_filedb.on_file_edit_insert_text(filename, text, start_line, start_column);
m_autocomplete_engine->on_edit(filename);
}
void ClientConnection::handle(const Messages::LanguageServer::FileEditRemoveText& message)
void ClientConnection::file_edit_remove_text(String const& filename, i32 start_line, i32 start_column, i32 end_line, i32 end_column)
{
dbgln_if(LANGUAGE_SERVER_DEBUG, "RemoveText for file: {}", message.filename());
dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{} - {}:{}]", message.start_line(), message.start_column(), message.end_line(), message.end_column());
m_filedb.on_file_edit_remove_text(message.filename(), message.start_line(), message.start_column(), message.end_line(), message.end_column());
m_autocomplete_engine->on_edit(message.filename());
dbgln_if(LANGUAGE_SERVER_DEBUG, "RemoveText for file: {}", filename);
dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{} - {}:{}]", start_line, start_column, end_line, end_column);
m_filedb.on_file_edit_remove_text(filename, start_line, start_column, end_line, end_column);
m_autocomplete_engine->on_edit(filename);
}
void ClientConnection::handle(const Messages::LanguageServer::AutoCompleteSuggestions& message)
void ClientConnection::auto_complete_suggestions(GUI::AutocompleteProvider::ProjectLocation const& location)
{
dbgln_if(LANGUAGE_SERVER_DEBUG, "AutoCompleteSuggestions for: {} {}:{}", message.location().file, message.location().line, message.location().column);
dbgln_if(LANGUAGE_SERVER_DEBUG, "AutoCompleteSuggestions for: {} {}:{}", location.file, location.line, location.column);
auto document = m_filedb.get(message.location().file);
auto document = m_filedb.get(location.file);
if (!document) {
dbgln("file {} has not been opened", message.location().file);
dbgln("file {} has not been opened", location.file);
return;
}
GUI::TextPosition autocomplete_position = { (size_t)message.location().line, (size_t)max(message.location().column, message.location().column - 1) };
Vector<GUI::AutocompleteProvider::Entry> suggestions = m_autocomplete_engine->get_suggestions(message.location().file, autocomplete_position);
GUI::TextPosition autocomplete_position = { (size_t)location.line, (size_t)max(location.column, location.column - 1) };
Vector<GUI::AutocompleteProvider::Entry> suggestions = m_autocomplete_engine->get_suggestions(location.file, autocomplete_position);
post_message(Messages::LanguageClient::AutoCompleteSuggestions(move(suggestions)));
}
void ClientConnection::handle(const Messages::LanguageServer::SetFileContent& message)
void ClientConnection::set_file_content(String const& filename, String const& content)
{
dbgln_if(LANGUAGE_SERVER_DEBUG, "SetFileContent: {}", message.filename());
auto document = m_filedb.get(message.filename());
dbgln_if(LANGUAGE_SERVER_DEBUG, "SetFileContent: {}", filename);
auto document = m_filedb.get(filename);
if (!document) {
m_filedb.add(message.filename(), message.content());
VERIFY(m_filedb.is_open(message.filename()));
m_filedb.add(filename, content);
VERIFY(m_filedb.is_open(filename));
} else {
const auto& content = message.content();
document->set_text(content.view());
}
VERIFY(m_filedb.is_open(message.filename()));
m_autocomplete_engine->on_edit(message.filename());
VERIFY(m_filedb.is_open(filename));
m_autocomplete_engine->on_edit(filename);
}
void ClientConnection::handle(const Messages::LanguageServer::FindDeclaration& message)
void ClientConnection::find_declaration(GUI::AutocompleteProvider::ProjectLocation const& location)
{
dbgln_if(LANGUAGE_SERVER_DEBUG, "FindDeclaration: {} {}:{}", message.location().file, message.location().line, message.location().column);
auto document = m_filedb.get(message.location().file);
dbgln_if(LANGUAGE_SERVER_DEBUG, "FindDeclaration: {} {}:{}", location.file, location.line, location.column);
auto document = m_filedb.get(location.file);
if (!document) {
dbgln("file {} has not been opened", message.location().file);
dbgln("file {} has not been opened", location.file);
return;
}
GUI::TextPosition identifier_position = { (size_t)message.location().line, (size_t)message.location().column };
auto location = m_autocomplete_engine->find_declaration_of(message.location().file, identifier_position);
if (!location.has_value()) {
GUI::TextPosition identifier_position = { (size_t)location.line, (size_t)location.column };
auto decl_location = m_autocomplete_engine->find_declaration_of(location.file, identifier_position);
if (!decl_location.has_value()) {
dbgln("could not find declaration");
return;
}
dbgln_if(LANGUAGE_SERVER_DEBUG, "declaration location: {} {}:{}", location.value().file, location.value().line, location.value().column);
post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { location.value().file, location.value().line, location.value().column }));
dbgln_if(LANGUAGE_SERVER_DEBUG, "declaration location: {} {}:{}", decl_location.value().file, decl_location.value().line, decl_location.value().column);
post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { decl_location.value().file, decl_location.value().line, decl_location.value().column }));
}
void ClientConnection::set_declarations_of_document_callback(ClientConnection& instance, const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations)

View file

@ -29,14 +29,14 @@ public:
virtual void die() override;
protected:
virtual void handle(const Messages::LanguageServer::Greet&) override;
virtual void handle(const Messages::LanguageServer::FileOpened&) override;
virtual void handle(const Messages::LanguageServer::FileEditInsertText&) override;
virtual void handle(const Messages::LanguageServer::FileEditRemoveText&) override;
virtual void handle(const Messages::LanguageServer::SetFileContent&) override;
virtual void handle(const Messages::LanguageServer::AutoCompleteSuggestions&) override;
virtual void handle(const Messages::LanguageServer::FindDeclaration&) override;
virtual void handle(const Messages::LanguageServer::SetAutoCompleteMode&) override = 0;
virtual void greet(String const&) override;
virtual void file_opened(String const&, IPC::File const&) override;
virtual void file_edit_insert_text(String const&, String const&, i32, i32) override;
virtual void file_edit_remove_text(String const&, i32, i32, i32, i32) override;
virtual void set_file_content(String const&, String const&) override;
virtual void auto_complete_suggestions(GUI::AutocompleteProvider::ProjectLocation const&) override;
virtual void find_declaration(GUI::AutocompleteProvider::ProjectLocation const&) override;
virtual void set_auto_complete_mode(String const&) override = 0;
static void set_declarations_of_document_callback(ClientConnection&, const String&, Vector<GUI::AutocompleteProvider::Declaration>&&);

View file

@ -26,10 +26,10 @@ public:
virtual ~ClientConnection() override = default;
private:
virtual void handle(const Messages::LanguageServer::SetAutoCompleteMode& message) override
virtual void set_auto_complete_mode(String const& mode) override
{
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "SetAutoCompleteMode: {}", message.mode());
if (message.mode() == "Parser")
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "SetAutoCompleteMode: {}", mode);
if (mode == "Parser")
m_autocomplete_engine = make<ParserAutoComplete>(*this, m_filedb);
else
m_autocomplete_engine = make<LexerAutoComplete>(*this, m_filedb);

View file

@ -23,6 +23,6 @@ class ClientConnection final : public LanguageServers::ClientConnection {
virtual ~ClientConnection() override = default;
private:
virtual void handle(const Messages::LanguageServer::SetAutoCompleteMode&) override { }
virtual void set_auto_complete_mode(String const&) override { }
};
}

View file

@ -45,6 +45,21 @@ struct Endpoint {
Vector<Message> messages;
};
static String snake_case(String const& identifier)
{
StringBuilder builder;
bool was_new_word = true;
for (auto ch : identifier) {
if (!builder.is_empty() && isupper(ch) && !was_new_word) {
builder.append('_');
was_new_word = true;
} else if (!isupper(ch))
was_new_word = false;
builder.append(tolower(ch));
}
return builder.to_string();
}
int main(int argc, char** argv)
{
if (argc != 2) {
@ -540,24 +555,38 @@ public:
switch (message.message_id()) {
)~~~");
for (auto& message : endpoint.messages) {
auto do_handle_message = [&](const String& name, bool returns_something) {
auto do_handle_message = [&](String const& name, Vector<Parameter> const& parameters, bool returns_something) {
auto message_generator = endpoint_generator.fork();
StringBuilder argument_generator;
for (size_t i = 0; i < parameters.size(); ++i) {
auto& parameter = parameters[i];
argument_generator.append("request.");
argument_generator.append(parameter.name);
argument_generator.append("()");
if (i != parameters.size() - 1)
argument_generator.append(", ");
}
message_generator.set("message.name", name);
message_generator.set("message.response_type", message.response_name());
message_generator.set("handler_name", snake_case(name));
message_generator.set("arguments", argument_generator.to_string());
message_generator.append(R"~~~(
case (int)Messages::@endpoint.name@::MessageID::@message.name@: {
)~~~");
if (returns_something) {
if (message.outputs.is_empty()) {
message_generator.append(R"~~~(
handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message));
[[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.name@&>(message);
@handler_name@(@arguments@);
auto response = Messages::@endpoint.name@::@message.response_type@ { };
return make<IPC::MessageBuffer>(response.encode());
)~~~");
} else {
message_generator.append(R"~~~(
auto response = handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message));
[[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.name@&>(message);
auto response = @handler_name@(@arguments@);
if (!response.valid())
return {};
return make<IPC::MessageBuffer>(response.encode());
@ -565,7 +594,8 @@ public:
}
} else {
message_generator.append(R"~~~(
handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message));
[[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.name@&>(message);
@handler_name@(@arguments@);
return {};
)~~~");
}
@ -573,9 +603,9 @@ public:
}
)~~~");
};
do_handle_message(message.name, message.is_synchronous);
do_handle_message(message.name, message.inputs, message.is_synchronous);
if (message.is_synchronous)
do_handle_message(message.response_name(), false);
do_handle_message(message.response_name(), message.outputs, false);
}
endpoint_generator.append(R"~~~(
default:
@ -587,23 +617,61 @@ public:
for (auto& message : endpoint.messages) {
auto message_generator = endpoint_generator.fork();
message_generator.set("message.name", message.name);
auto do_handle_message_decl = [&](String const& name, Vector<Parameter> const& parameters, bool is_response) {
String return_type = "void";
if (message.is_synchronous && !message.outputs.is_empty() && !is_response) {
StringBuilder builder;
builder.append("Messages::");
builder.append(endpoint.name);
builder.append("::");
builder.append(message.name);
builder.append("Response");
return_type = builder.to_string();
}
message_generator.set("message.complex_return_type", return_type);
String return_type = "void";
if (message.is_synchronous && !message.outputs.is_empty()) {
StringBuilder builder;
builder.append("Messages::");
builder.append(endpoint.name);
builder.append("::");
builder.append(message.name);
builder.append("Response");
return_type = builder.to_string();
}
message_generator.set("message.complex_return_type", return_type);
message_generator.set("handler_name", snake_case(name));
message_generator.append(R"~~~(
virtual @message.complex_return_type@ @handler_name@()~~~");
message_generator.append(R"~~~(
virtual @message.complex_return_type@ handle(const Messages::@endpoint.name@::@message.name@&) = 0;
auto make_argument_type = [](String const& type) {
StringBuilder builder;
bool const_ref = true;
if (type == "u8" || type == "i8" || type == "u16" || type == "i16"
|| type == "u32" || type == "i32" || type == "bool" || type == "double"
|| type == "float" || type == "int" || type == "unsigned" || type == "unsigned int")
const_ref = false;
builder.append(type);
if (const_ref)
builder.append(" const&");
return builder.to_string();
};
for (size_t i = 0; i < parameters.size(); ++i) {
auto& parameter = parameters[i];
auto argument_generator = message_generator.fork();
argument_generator.set("argument.type", make_argument_type(parameter.type));
argument_generator.set("argument.name", parameter.name);
argument_generator.append("[[maybe_unused]] @argument.type@ @argument.name@");
if (i != parameters.size() - 1)
argument_generator.append(", ");
}
if (is_response) {
message_generator.append(R"~~~() { };
)~~~");
} else {
message_generator.append(R"~~~() = 0;
)~~~");
}
};
do_handle_message_decl(message.name, message.inputs, false);
if (message.is_synchronous)
do_handle_message_decl(message.response_name(), message.outputs, true);
}
endpoint_generator.append(R"~~~(