mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:32:45 +00:00 
			
		
		
		
	IPCCompiler: Use new SourceGenerator class.
This commit is contained in:
		
							parent
							
								
									b99cebf63a
								
							
						
					
					
						commit
						0c5497829e
					
				
					 1 changed files with 283 additions and 132 deletions
				
			
		|  | @ -27,6 +27,7 @@ | |||
| #include <AK/Function.h> | ||||
| #include <AK/GenericLexer.h> | ||||
| #include <AK/HashMap.h> | ||||
| #include <AK/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibCore/File.h> | ||||
| #include <ctype.h> | ||||
|  | @ -64,13 +65,13 @@ struct Endpoint { | |||
| int main(int argc, char** argv) | ||||
| { | ||||
|     if (argc != 2) { | ||||
|         printf("usage: %s <IPC endpoint definition file>\n", argv[0]); | ||||
|         outln("usage: {} <IPC endpoint definition file>", argv[0]); | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     auto file = Core::File::construct(argv[1]); | ||||
|     if (!file->open(Core::IODevice::ReadOnly)) { | ||||
|         fprintf(stderr, "Error: Cannot open %s: %s\n", argv[1], file->error_string()); | ||||
|         warnln("Error: Cannot open {}: {}", argv[1], file->error_string()); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|  | @ -81,7 +82,7 @@ int main(int argc, char** argv) | |||
| 
 | ||||
|     auto assert_specific = [&](char ch) { | ||||
|         if (lexer.peek() != ch) | ||||
|             warn() << "assert_specific: wanted '" << ch << "', but got '" << lexer.peek() << "' at index " << lexer.tell(); | ||||
|             warnln("assert_specific: wanted '{}', but got '{}' at index {}", ch, lexer.peek(), lexer.tell()); | ||||
|         bool saw_expected = lexer.consume_specific(ch); | ||||
|         ASSERT(saw_expected); | ||||
|     }; | ||||
|  | @ -199,38 +200,62 @@ int main(int argc, char** argv) | |||
|     while (lexer.tell() < file_contents.size()) | ||||
|         parse_endpoint(); | ||||
| 
 | ||||
|     out() << "#pragma once"; | ||||
|     out() << "#include <AK/MemoryStream.h>"; | ||||
|     out() << "#include <AK/OwnPtr.h>"; | ||||
|     out() << "#include <AK/URL.h>"; | ||||
|     out() << "#include <AK/Utf8View.h>"; | ||||
|     out() << "#include <LibGfx/Color.h>"; | ||||
|     out() << "#include <LibGfx/Rect.h>"; | ||||
|     out() << "#include <LibGfx/ShareableBitmap.h>"; | ||||
|     out() << "#include <LibIPC/Decoder.h>"; | ||||
|     out() << "#include <LibIPC/Dictionary.h>"; | ||||
|     out() << "#include <LibIPC/Encoder.h>"; | ||||
|     out() << "#include <LibIPC/Endpoint.h>"; | ||||
|     out() << "#include <LibIPC/Message.h>"; | ||||
|     out(); | ||||
|     SourceGenerator generator; | ||||
| 
 | ||||
|     generator.append(R"~~~( | ||||
| #pragma once | ||||
| #include <AK/MemoryStream.h> | ||||
| #include <AK/OwnPtr.h> | ||||
| #include <AK/URL.h> | ||||
| #include <AK/Utf8View.h> | ||||
| #include <LibGfx/Color.h> | ||||
| #include <LibGfx/Rect.h> | ||||
| #include <LibGfx/ShareableBitmap.h> | ||||
| #include <LibIPC/Decoder.h> | ||||
| #include <LibIPC/Dictionary.h> | ||||
| #include <LibIPC/Encoder.h> | ||||
| #include <LibIPC/Endpoint.h> | ||||
| #include <LibIPC/Message.h> | ||||
| )~~~"); | ||||
| 
 | ||||
|     for (auto& endpoint : endpoints) { | ||||
|         out() << "namespace Messages::" << endpoint.name << " {"; | ||||
|         out(); | ||||
|         SourceGenerator endpoint_generator { generator }; | ||||
| 
 | ||||
|         endpoint_generator.set("endpoint.name", endpoint.name); | ||||
|         endpoint_generator.set("endpoint.magic", String::number(endpoint.magic)); | ||||
| 
 | ||||
|         endpoint_generator.append(R"~~~( | ||||
| namespace Messages::@endpoint.name@ { | ||||
| )~~~"); | ||||
| 
 | ||||
|         HashMap<String, int> message_ids; | ||||
| 
 | ||||
|         out() << "enum class MessageID : i32 {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
| enum class MessageID : i32 { | ||||
| )~~~"); | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             SourceGenerator message_generator { endpoint_generator }; | ||||
| 
 | ||||
|             message_ids.set(message.name, message_ids.size() + 1); | ||||
|             out() << "    " << message.name << " = " << message_ids.size() << ","; | ||||
|             message_generator.set("message.name", message.name); | ||||
|             message_generator.set("message.id", String::number(message_ids.size())); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|     @message.name@ = @message.id@, | ||||
| )~~~"); | ||||
|             if (message.is_synchronous) { | ||||
|                 message_ids.set(message.response_name(), message_ids.size() + 1); | ||||
|                 out() << "    " << message.response_name() << " = " << message_ids.size() << ","; | ||||
|                 message_generator.set("message.name", message.response_name()); | ||||
|                 message_generator.set("message.id", String::number(message_ids.size())); | ||||
| 
 | ||||
|                 message_generator.append(R"~~~( | ||||
|     @message.name@ = @message.id@, | ||||
| )~~~"); | ||||
|             } | ||||
|         } | ||||
|         out() << "};"; | ||||
|         out(); | ||||
|         endpoint_generator.append(R"~~~( | ||||
| }; | ||||
| )~~~"); | ||||
| 
 | ||||
|         auto constructor_for_message = [&](const String& name, const Vector<Parameter>& parameters) { | ||||
|             StringBuilder builder; | ||||
|  | @ -267,31 +292,58 @@ int main(int argc, char** argv) | |||
|         }; | ||||
| 
 | ||||
|         auto do_message = [&](const String& name, const Vector<Parameter>& parameters, const String& response_type = {}) { | ||||
|             out() << "class " << name << " final : public IPC::Message {"; | ||||
|             out() << "public:"; | ||||
|             if (!response_type.is_null()) | ||||
|                 out() << "    typedef class " << response_type << " ResponseType;"; | ||||
|             out() << "    " << constructor_for_message(name, parameters); | ||||
|             out() << "    virtual ~" << name << "() override {}"; | ||||
|             out() << "    virtual i32 endpoint_magic() const override { return " << endpoint.magic << "; }"; | ||||
|             out() << "    virtual i32 message_id() const override { return (int)MessageID::" << name << "; }"; | ||||
|             out() << "    static i32 static_message_id() { return (int)MessageID::" << name << "; }"; | ||||
|             out() << "    virtual const char* message_name() const override { return \"" << endpoint.name << "::" << name << "\"; }"; | ||||
|             out() << "    static OwnPtr<" << name << "> decode(InputMemoryStream& stream, size_t& size_in_bytes)"; | ||||
|             out() << "    {"; | ||||
|             SourceGenerator message_generator { endpoint_generator }; | ||||
| 
 | ||||
|             out() << "        IPC::Decoder decoder(stream);"; | ||||
|             message_generator.set("message.name", name); | ||||
|             message_generator.set("message.response_type", response_type); | ||||
|             message_generator.set("message.constructor", constructor_for_message(name, parameters)); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
| class @message.name@ final : public IPC::Message { | ||||
| public: | ||||
| )~~~"); | ||||
| 
 | ||||
|             if (!response_type.is_null()) | ||||
|                 message_generator.append(R"~~~( | ||||
|    typedef class @message.response_type@ ResponseType; | ||||
| )~~~"); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|     @message.constructor@ | ||||
|     virtual ~@message.name@() override {} | ||||
| 
 | ||||
|     virtual i32 endpoint_magic() const override { return @endpoint.magic@; } | ||||
|     virtual i32 message_id() const override { return (int)MessageID::@message.name@; } | ||||
|     static i32 static_message_id() { return (int)MessageID::@message.name@; } | ||||
|     virtual const char* message_name() const override { return "@endpoint.name@::@message.name@"; } | ||||
| 
 | ||||
|     static OwnPtr<@message.name@> decode(InputMemoryStream& stream, size_t& size_in_bytes) | ||||
|     { | ||||
|         IPC::Decoder decoder {stream}; | ||||
| )~~~"); | ||||
| 
 | ||||
|             for (auto& parameter : parameters) { | ||||
|                 String initial_value = "{}"; | ||||
|                 SourceGenerator parameter_generator { message_generator }; | ||||
| 
 | ||||
|                 parameter_generator.set("parameter.type", parameter.type); | ||||
|                 parameter_generator.set("parameter.name", parameter.name); | ||||
| 
 | ||||
|                 if (parameter.type == "bool") | ||||
|                     initial_value = "false"; | ||||
|                 out() << "        " << parameter.type << " " << parameter.name << " = " << initial_value << ";"; | ||||
|                 out() << "        if (!decoder.decode(" << parameter.name << "))"; | ||||
|                 out() << "            return nullptr;"; | ||||
|                     parameter_generator.set("parameter.initial_value", "false"); | ||||
|                 else | ||||
|                     parameter_generator.set("parameter.initial_value", "{}"); | ||||
| 
 | ||||
|                 parameter_generator.append(R"~~~( | ||||
|         @parameter.type@ @parameter.name@ = @parameter.initial_value@; | ||||
|         if (!decoder.decode(@parameter.name@)) | ||||
|             return nullptr; | ||||
| )~~~"); | ||||
| 
 | ||||
|                 if (parameter.attributes.contains_slow("UTF8")) { | ||||
|                     out() << "        if (!Utf8View(" << parameter.name << ").validate())"; | ||||
|                     out() << "            return nullptr;"; | ||||
|                     parameter_generator.append(R"~~~( | ||||
|         if (!Utf8View(@parameter.name@).validate()) | ||||
|             return nullptr; | ||||
| )~~~"); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | @ -302,29 +354,65 @@ int main(int argc, char** argv) | |||
|                 if (i != parameters.size() - 1) | ||||
|                     builder.append(", "); | ||||
|             } | ||||
|             out() << "        size_in_bytes = stream.offset();"; | ||||
|             out() << "        return make<" << name << ">(" << builder.to_string() << ");"; | ||||
|             out() << "    }"; | ||||
|             out() << "    virtual IPC::MessageBuffer encode() const override"; | ||||
|             out() << "    {"; | ||||
|             out() << "        IPC::MessageBuffer buffer;"; | ||||
|             out() << "        IPC::Encoder stream(buffer);"; | ||||
|             out() << "        stream << endpoint_magic();"; | ||||
|             out() << "        stream << (int)MessageID::" << name << ";"; | ||||
| 
 | ||||
|             message_generator.set("message.constructor_call_parameters", builder.build()); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|         size_in_bytes = stream.offset(); | ||||
|         return make<@message.name@>(@message.constructor_call_parameters@); | ||||
|     } | ||||
| )~~~"); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|     virtual IPC::MessageBuffer encode() const override | ||||
|     { | ||||
|         IPC::MessageBuffer buffer; | ||||
|         IPC::Encoder stream(buffer); | ||||
|         stream << endpoint_magic(); | ||||
|         stream << (int)MessageID::@message.name@; | ||||
| )~~~"); | ||||
| 
 | ||||
|             for (auto& parameter : parameters) { | ||||
|                 out() << "        stream << m_" << parameter.name << ";"; | ||||
|                 SourceGenerator parameter_generator { message_generator }; | ||||
| 
 | ||||
|                 parameter_generator.set("parameter.name", parameter.name); | ||||
|                 parameter_generator.append(R"~~~( | ||||
|         stream << m_@parameter.name@; | ||||
| )~~~"); | ||||
|             } | ||||
|             out() << "        return buffer;"; | ||||
|             out() << "    }"; | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|         return buffer; | ||||
|     } | ||||
| )~~~"); | ||||
| 
 | ||||
|             for (auto& parameter : parameters) { | ||||
|                 out() << "    const " << parameter.type << "& " << parameter.name << "() const { return m_" << parameter.name << "; }"; | ||||
|                 SourceGenerator parameter_generator { message_generator }; | ||||
| 
 | ||||
|                 parameter_generator.set("parameter.type", parameter.type); | ||||
|                 parameter_generator.set("parameter.name", parameter.name); | ||||
|                 parameter_generator.append(R"~~~( | ||||
|     const @parameter.type@& @parameter.name@() const { return m_@parameter.name@; } | ||||
| )~~~"); | ||||
|             } | ||||
|             out() << "private:"; | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
| private: | ||||
|             )~~~"); | ||||
| 
 | ||||
|             for (auto& parameter : parameters) { | ||||
|                 out() << "    " << parameter.type << " m_" << parameter.name << ";"; | ||||
|                 SourceGenerator parameter_generator { message_generator }; | ||||
| 
 | ||||
|                 parameter_generator.set("parameter.type", parameter.type); | ||||
|                 parameter_generator.set("parameter.name", parameter.name); | ||||
|                 parameter_generator.append(R"~~~( | ||||
|     @parameter.type@ m_@parameter.name@; | ||||
| )~~~"); | ||||
|             } | ||||
|             out() << "};"; | ||||
|             out(); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
| }; | ||||
|             )~~~"); | ||||
|         }; | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             String response_name; | ||||
|  | @ -334,94 +422,149 @@ int main(int argc, char** argv) | |||
|             } | ||||
|             do_message(message.name, message.inputs, response_name); | ||||
|         } | ||||
|         out() << "}"; | ||||
|         out(); | ||||
| 
 | ||||
|         out() << "class " << endpoint.name << "Endpoint : public IPC::Endpoint {"; | ||||
|         out() << "public:"; | ||||
|         out() << "    " << endpoint.name << "Endpoint() {}"; | ||||
|         out() << "    virtual ~" << endpoint.name << "Endpoint() override {}"; | ||||
|         out() << "    static int static_magic() { return " << endpoint.magic << "; }"; | ||||
|         out() << "    virtual int magic() const override { return " << endpoint.magic << "; }"; | ||||
|         out() << "    static String static_name() { return \"" << endpoint.name << "\"; };"; | ||||
|         out() << "    virtual String name() const override { return \"" << endpoint.name << "\"; };"; | ||||
|         out() << "    static OwnPtr<IPC::Message> decode_message(const ByteBuffer& buffer, size_t& size_in_bytes)"; | ||||
|         out() << "    {"; | ||||
|         out() << "        InputMemoryStream stream { buffer };"; | ||||
|         out() << "        i32 message_endpoint_magic = 0;"; | ||||
|         out() << "        stream >> message_endpoint_magic;"; | ||||
|         out() << "        if (stream.handle_any_error()) {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
| } // namespace Messages::@endpoint.name@
 | ||||
|         )~~~"); | ||||
| 
 | ||||
|         endpoint_generator.append(R"~~~( | ||||
| class @endpoint.name@Endpoint : public IPC::Endpoint { | ||||
| public: | ||||
|     @endpoint.name@Endpoint() { } | ||||
|     virtual ~@endpoint.name@Endpoint() override { } | ||||
| 
 | ||||
|     static int static_magic() { return @endpoint.magic@; } | ||||
|     virtual int magic() const override { return @endpoint.magic@; } | ||||
|     static String static_name() { return "@endpoint.name@"; } | ||||
|     virtual String name() const override { return "@endpoint.name@"; } | ||||
| 
 | ||||
|     static OwnPtr<IPC::Message> decode_message(const ByteBuffer& buffer, size_t& size_in_bytes) | ||||
|     { | ||||
|         InputMemoryStream stream { buffer }; | ||||
|         i32 message_endpoint_magic = 0; | ||||
|         stream >> message_endpoint_magic; | ||||
|         if (stream.handle_any_error()) { | ||||
| )~~~"); | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         out() << "            dbg() << \"Failed to read message endpoint magic\";"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             dbgln("Failed to read message endpoint magic"); | ||||
| )~~~"); | ||||
| #endif | ||||
|         out() << "            return nullptr;"; | ||||
|         out() << "        }"; | ||||
|         out() << "        if (message_endpoint_magic != " << endpoint.magic << ") {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         if (message_endpoint_magic != @endpoint.magic@) { | ||||
| )~~~"); | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         out() << "            dbg() << \"endpoint magic \" << message_endpoint_magic << \" != " << endpoint.magic << "\";"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             dbgln("Endpoint magic number message_endpoint_magic != @endpoint.magic@"); | ||||
| )~~~"); | ||||
| #endif | ||||
|         out() << "            return nullptr;"; | ||||
|         out() << "        }"; | ||||
|         out() << "        i32 message_id = 0;"; | ||||
|         out() << "        stream >> message_id;"; | ||||
|         out() << "        if (stream.handle_any_error()) {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         i32 message_id = 0; | ||||
|         stream >> message_id; | ||||
|         if (stream.handle_any_error()) { | ||||
| )~~~"); | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         out() << "            dbg() << \"Failed to read message ID\";"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             dbgln("Failed to read message ID"); | ||||
| )~~~"); | ||||
| #endif | ||||
|         out() << "            return nullptr;"; | ||||
|         out() << "        }"; | ||||
|         out() << "        OwnPtr<IPC::Message> message;"; | ||||
|         out() << "        switch (message_id) {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         OwnPtr<IPC::Message> message; | ||||
|         switch (message_id) { | ||||
| )~~~"); | ||||
| 
 | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             auto do_decode_message = [&](const String& name) { | ||||
|                 out() << "        case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":"; | ||||
|                 out() << "            message = Messages::" << endpoint.name << "::" << name << "::decode(stream, size_in_bytes);"; | ||||
|                 out() << "            break;"; | ||||
|                 SourceGenerator message_generator { endpoint_generator }; | ||||
| 
 | ||||
|                 message_generator.set("message.name", name); | ||||
| 
 | ||||
|                 message_generator.append(R"~~~( | ||||
|         case (int)Messages::@endpoint.name@::MessageID::@message.name@: | ||||
|             message = Messages::@endpoint.name@::@message.name@::decode(stream, size_in_bytes); | ||||
|             break; | ||||
| )~~~"); | ||||
|             }; | ||||
| 
 | ||||
|             do_decode_message(message.name); | ||||
|             if (message.is_synchronous) | ||||
|                 do_decode_message(message.response_name()); | ||||
|         } | ||||
|         out() << "        default:"; | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         out() << "            dbg() << \"Failed to decode " << endpoint.name << ".(\" << message_id << \")\";"; | ||||
| #endif | ||||
|         out() << "            return nullptr;"; | ||||
| 
 | ||||
|         out() << "        }"; | ||||
|         out() << "        if (stream.handle_any_error()) {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|         default: | ||||
| )~~~"); | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         out() << "            dbg() << \"Failed to read the message\";"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             dbgln("Failed to decode @endpoint.name@.({})", message_id); | ||||
| )~~~"); | ||||
| #endif | ||||
|         out() << "            return nullptr;"; | ||||
|         out() << "        }"; | ||||
|         out() << "        return message;"; | ||||
|         out() << "    }"; | ||||
|         out(); | ||||
|         out() << "    virtual OwnPtr<IPC::Message> handle(const IPC::Message& message) override"; | ||||
|         out() << "    {"; | ||||
|         out() << "        switch (message.message_id()) {"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         if (stream.handle_any_error()) { | ||||
| )~~~"); | ||||
| #ifdef GENERATE_DEBUG_CODE | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             dbgln("Failed to read the message"); | ||||
| )~~~"); | ||||
| #endif | ||||
|         endpoint_generator.append(R"~~~( | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         return message; | ||||
|     } | ||||
| 
 | ||||
|     virtual OwnPtr<IPC::Message> handle(const IPC::Message& message) override | ||||
|     { | ||||
|         switch (message.message_id()) { | ||||
| )~~~"); | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             auto do_decode_message = [&](const String& name, bool returns_something) { | ||||
|                 out() << "        case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":"; | ||||
|                 SourceGenerator message_generator { endpoint_generator }; | ||||
| 
 | ||||
|                 message_generator.set("message.name", name); | ||||
|                 message_generator.append(R"~~~( | ||||
|         case (int)Messages::@endpoint.name@::MessageID::@message.name@: | ||||
| )~~~"); | ||||
|                 if (returns_something) { | ||||
|                     out() << "            return handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));"; | ||||
|                     message_generator.append(R"~~~( | ||||
|             return handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message)); | ||||
| )~~~"); | ||||
|                 } else { | ||||
|                     out() << "            handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));"; | ||||
|                     out() << "            return nullptr;"; | ||||
|                     message_generator.append(R"~~~( | ||||
|             handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message)); | ||||
|             return nullptr; | ||||
| )~~~"); | ||||
|                 } | ||||
|             }; | ||||
|             do_decode_message(message.name, message.is_synchronous); | ||||
|             if (message.is_synchronous) | ||||
|                 do_decode_message(message.response_name(), false); | ||||
|         } | ||||
|         out() << "        default:"; | ||||
|         out() << "            return nullptr;"; | ||||
| 
 | ||||
|         out() << "        }"; | ||||
|         out() << "    }"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
|         default: | ||||
|             return nullptr; | ||||
|         } | ||||
|     } | ||||
| )~~~"); | ||||
| 
 | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             SourceGenerator message_generator { endpoint_generator }; | ||||
| 
 | ||||
|             message_generator.set("message.name", message.name); | ||||
| 
 | ||||
|             String return_type = "void"; | ||||
|             if (message.is_synchronous) { | ||||
|                 StringBuilder builder; | ||||
|  | @ -433,30 +576,38 @@ int main(int argc, char** argv) | |||
|                 builder.append(">"); | ||||
|                 return_type = builder.to_string(); | ||||
|             } | ||||
|             out() << "    virtual " << return_type << " handle(const Messages::" << endpoint.name << "::" << message.name << "&) = 0;"; | ||||
|             message_generator.set("message.complex_return_type", return_type); | ||||
| 
 | ||||
|             message_generator.append(R"~~~( | ||||
|     virtual @message.complex_return_type@ handle(const Messages::@endpoint.name@::@message.name@&) = 0; | ||||
| )~~~"); | ||||
|         } | ||||
| 
 | ||||
|         out() << "private:"; | ||||
|         out() << "};"; | ||||
|         endpoint_generator.append(R"~~~( | ||||
| private: | ||||
| }; | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     outln("{}", generator.generate()); | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
|     for (auto& endpoint : endpoints) { | ||||
|         warn() << "Endpoint: '" << endpoint.name << "' (magic: " << endpoint.magic << ")"; | ||||
|         warnln("Endpoint '{}' (magic: {})", endpoint.name, endpoint.magic); | ||||
|         for (auto& message : endpoint.messages) { | ||||
|             warn() << "  Message: '" << message.name << "'"; | ||||
|             warn() << "    Sync: " << message.is_synchronous; | ||||
|             warn() << "    Inputs:"; | ||||
|             warnln("  Message: '{}'", message.name); | ||||
|             warnln("    Sync: {}", message.is_synchronous); | ||||
|             warnln("    Inputs:"); | ||||
|             for (auto& parameter : message.inputs) | ||||
|                 warn() << "        Parameter: " << parameter.name << " (" << parameter.type << ")"; | ||||
|                 warnln("      Parameter: {} ({})", parameter.name, parameter.type); | ||||
|             if (message.inputs.is_empty()) | ||||
|                 warn() << "        (none)"; | ||||
|                 warnln("      (none)"); | ||||
|             if (message.is_synchronous) { | ||||
|                 warn() << "    Outputs:"; | ||||
|                 warnln("    Outputs:"); | ||||
|                 for (auto& parameter : message.outputs) | ||||
|                     warn() << "        Parameter: " << parameter.name << " (" << parameter.type << ")"; | ||||
|                     warnln("      Parameter: {} ({})", parameter.name, parameter.type); | ||||
|                 if (message.outputs.is_empty()) | ||||
|                     warn() << "        (none)"; | ||||
|                     warnln("      (none)"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 asynts
						asynts