From ebf9b52e71923b35ff4292773760c7d8eae026d0 Mon Sep 17 00:00:00 2001 From: nxtumUbun Date: Fri, 25 Oct 2024 01:00:16 -0700 Subject: [PATCH] compile with fake interface --- .../PluginSkeletonGenerator.py | 3 +- PluginSkeletonGenerator/file_data.py | 260 ++++++++++++------ PluginSkeletonGenerator/help.txt | 5 - PluginSkeletonGenerator/menu.py | 6 +- PluginSkeletonGenerator/templates/.cmake.txt | 2 + .../templates/.plugin_conf_in.txt | 2 + .../templates/.plugin_header.txt | 2 +- .../templates/.plugin_implementation.txt | 15 +- .../templates/.plugin_source.txt | 6 +- .../iplugin_methods/.deinitialize_oop.txt | 6 +- .../iplugin_methods/.initialize_oop.txt | 10 +- .../templates/module/.module_header.txt | 1 + .../templates/nested_class/.config_class.txt | 2 +- .../nested_class/.rpc_inotification.txt | 2 +- .../templates/nested_methods/.configure.txt | 1 + PluginSkeletonGenerator/tests/IHello.h | 28 ++ 16 files changed, 241 insertions(+), 110 deletions(-) delete mode 100644 PluginSkeletonGenerator/help.txt create mode 100644 PluginSkeletonGenerator/tests/IHello.h diff --git a/PluginSkeletonGenerator/PluginSkeletonGenerator.py b/PluginSkeletonGenerator/PluginSkeletonGenerator.py index 66e1174..792bd41 100755 --- a/PluginSkeletonGenerator/PluginSkeletonGenerator.py +++ b/PluginSkeletonGenerator/PluginSkeletonGenerator.py @@ -10,7 +10,7 @@ class PluginGenerator: def __init__(self, blueprint_data) -> None: self.blueprint_data = blueprint_data self.directory = self.blueprint_data.plugin_name - os.makedirs(self.blueprint_data.plugin_name, exist_ok=True) + os.makedirs(self.blueprint_data.plugin_name, exist_ok=False) self.indenter = Indenter() def load_template(self, template_name): @@ -55,6 +55,7 @@ def generate_conf_in(self): # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# def main(): + print('[NOTE]: The output from this generator is a skeleton, therefore it uses example methods. Please correct the generated methods accordingly!') menu.menu() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# if __name__ == "__main__": diff --git a/PluginSkeletonGenerator/file_data.py b/PluginSkeletonGenerator/file_data.py index ea73af1..66caad3 100644 --- a/PluginSkeletonGenerator/file_data.py +++ b/PluginSkeletonGenerator/file_data.py @@ -56,12 +56,14 @@ def populate_keywords(self): def generate_comrpc_includes(self): includes = [] for comrpc in self.comrpc_interfaces: - if comrpc == 'IConfiguration': + if comrpc == 'IConfiguration' and self.type == HeaderData.HeaderType.HEADER: break - includes.append(f'#include ') - for interface in self.jsonrpc_interfaces: - if 'I' + interface[1:] in self.notification_interfaces: - includes.append(f'#include ') + includes.append(f'#include ') + if self.type == HeaderData.HeaderType.HEADER: + includes.append("#include ") + for interface in self.jsonrpc_interfaces: + if 'I' + interface[1:] in self.notification_interfaces: + includes.append(f'#include ') return '\n'.join(includes) if includes else 'rm\*n' def generate_inherited_classes(self): @@ -83,14 +85,14 @@ def generate_oop_inherited_classes(self): def notification_registers(self, interface): text = [] text.append('\n~INDENT_INCREASE~') - text.append('\nASSERT(notification);') + text.append('\nASSERT(notification != nullptr);') text.append('\n_adminLock.Lock();') - text.append(f'''\nauto item = std::find(_notifications{interface}.begin(), _notifications{interface}.end(), notification); - ASSERT(item == _notifications{interface}.end()); - if (item == _notifications{interface}.end()) {{ + text.append(f'''\nauto item = std::find(_{interface[1:].lower()}Notification.begin(), _{interface[1:].lower()}Notification.end(), notification); + ASSERT(item == _{interface[1:].lower()}Notification.end()); + if (item == _{interface[1:].lower()}Notification.end()) {{ ~INDENT_INCREASE~ notification->AddRef(); - notifications{interface}.push_back(notification); + _{interface[1:].lower()}Notification.push_back(notification); ~INDENT_DECREASE~ }} @@ -101,16 +103,16 @@ def notification_registers(self, interface): def notification_unregisters(self,interface): text = [] text.append(f'''\n~INDENT_INCREASE~ - ASSERT(notification); + ASSERT(notification != nullptr); _adminLock.Lock(); - auto item = std::find(_notifications{interface}.begin(), _notifications{interface}.end(), notification); - ASSERT(item != _notifications{interface}.end()); + auto item = std::find(_{interface[1:].lower()}Notification.begin(), _{interface[1:].lower()}Notification.end(), notification); + ASSERT(item != _{interface[1:].lower()}Notification.end()); - if (item != _notifications{interface}.end()) {{ + if (item != _{interface[1:].lower()}Notification.end()) {{ ~INDENT_INCREASE~ - _notifications{interface}.erase(item); (*item)->Release(); + _{interface[1:].lower()}Notification.erase(item); ~INDENT_DECREASE~ }} _adminLock.Unlock(); @@ -130,21 +132,31 @@ def generate_inherited_methods(self): if (inherited == 'IConfiguration'): continue if self.type == HeaderData.HeaderType.HEADER: - methods.append(f"// {inherited} methods\n" f"void {inherited}Method1() override;\n") + methods.append(f"// {inherited} methods\n" f"uint32_t {inherited}Method1() override;") if inherited in self.notification_interfaces: methods.append(f'void Register(Exchange::{inherited}::INotification* notification) override;') - methods.append(f'void Unregister(Exchange::{inherited}::INotification* notification) override;') + methods.append(f'void Unregister(const Exchange::{inherited}::INotification* notification) override;') + if f'J{inherited[1:]}' in self.jsonrpc_interfaces and self.out_of_process: + methods.append(f'void {inherited}NotificationExample();') else: methods.append(f'// {inherited} methods') - - methods.append(f'void {inherited}Method1() override {{\n\n}}\n') - if inherited in self.notification_interfaces: + if inherited in self.notification_interfaces: + methods.append(f'''uint32_t {inherited}Method1() override {{\n + ~INDENT_INCREASE~ + // This function could be used to call a notify method + Notify{inherited}(); + return Core::ERROR_NONE; + ~INDENT_DECREASE~ + }}\n''') + else: + methods.append(f'uint32_t {inherited}Method1() override {{\n~INDENT_INCREASE~\nreturn Core::ERROR_NONE;\n~INDENT_DECREASE~\n}}\n') + if inherited in self.notification_interfaces and self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION: methods.append(f'void Register(Exchange::{inherited}::INotification* notification) override {{') methods.append(self.notification_registers(inherited)) - methods.append('}') - methods.append(f'void Unregister(Exchange::{inherited}::INotification* notification) override {{') + methods.append('}\n') + methods.append(f'void Unregister(const Exchange::{inherited}::INotification* notification) override {{') methods.append(self.notification_unregisters(inherited)) - methods.append('}') + methods.append('}\n') if self.comrpc_interfaces: if self.comrpc_interfaces[-1] == "IConfiguration": @@ -158,7 +170,7 @@ def generate_plugin_methods(self): method = [] if self.type == HeaderData.HeaderType.HEADER: method = [f'void {self.plugin_name}Method();'] - if self.notification_interfaces: + if self.out_of_process: method.append(f'void Deactivated(RPC::IRemoteConnection* connection);') return '\n'.join(method) @@ -180,7 +192,7 @@ def generate_interface_aggregate(self): for comrpc in self.comrpc_interfaces: if comrpc == "IConfiguration": break - aggregates.append(f'INTERFACE_AGGREGATE(Exchange::{comrpc}, _impl{comrpc})') + aggregates.append(f'INTERFACE_AGGREGATE(Exchange::{comrpc}, _impl{comrpc[1:]})') return ('\n').join(aggregates) if aggregates else 'rm\*n' def generate_module_plugin_name(self): @@ -195,15 +207,15 @@ def generate_base_constructor(self): def generate_interface_constructor(self): constructor = [] if not self.comrpc_interfaces: - return '' + return 'rm\*n' if self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION: constructor = [f": Exchange::{self.comrpc_interfaces[0]}()"] + [f", Exchange::{comrpc}()" for comrpc in self.comrpc_interfaces[1:]] - constructor.append(', test(0)') + constructor.append(', _test(0)') if self.notification_interfaces: constructor.append(', _adminLock()') for interface in self.notification_interfaces: - constructor.append(f', _notifications{interface}()') + constructor.append(f', _{interface[1:].lower()}Notification()') if (not self.out_of_process and self.type == HeaderData.HeaderType.HEADER): if self.comrpc_interfaces: @@ -216,22 +228,35 @@ def generate_interface_constructor(self): def generate_member_impl(self): members = [] + if self.out_of_process: + members.append("PluginHost::IShell* _service;") + members.append("uint32_t _connectionId;") if self.out_of_process: for comrpc in self.comrpc_interfaces: if comrpc == 'IConfiguration': break - members.append(f"Exchange::{comrpc}* _impl{comrpc};") - if self.jsonrpc: - members.append("Core::SinkType _notification;") + members.append(f"Exchange::{comrpc}* _impl{comrpc[1:]};") + members.append(f"Core::SinkType _notification;") + if self.notification_interfaces and not self.out_of_process: + members.append(f"mutable Core::CriticalSection _adminLock;") + for comrpc in self.notification_interfaces: + members.append(f'{comrpc[1:]}NotificationVector _{comrpc[1:].lower()}Notification;') return "\n".join(members) if members else 'rm\*n' def generate_member_constructor(self): members = [] if self.out_of_process: + members.append(f", _service(nullptr)") + members.append(f", _connectionId(0)") for comrpc in self.comrpc_interfaces: if comrpc == "IConfiguration": break - members.append(f", _impl{comrpc}(nullptr)") + members.append(f", _impl{comrpc[1:]}(nullptr)") + members.append(f", _notification(*this)") + if self.notification_interfaces and not self.out_of_process: + members.append(f", _adminLock()") + for comrpc in self.notification_interfaces: + members.append(f", _{comrpc[1:].lower()}Notification()") return "\n".join(members) if members else 'rm\*n' def generate_notification_class(self): @@ -258,7 +283,7 @@ def generate_notification_function(self): methods = [] for inherited in self.notification_interfaces: if Utils.replace_comrpc_to_jsonrpc(inherited) in self.jsonrpc_interfaces: - methods.append(f'''void {inherited}Notification() override {{\n~INDENT_INCREASE~\nExchange::J{inherited[1:]}::Event::{inherited}Notification();\n~INDENT_DECREASE~\n}}\n''') + methods.append(f'''void {inherited}Notification() override {{\n~INDENT_INCREASE~\nExchange::J{inherited[1:]}::Event::{inherited}Notification(_parent);\n~INDENT_DECREASE~\n}}\n''') else: methods.append(f'void {inherited}Notification() override {{\n\n}}') return ("\n").join(methods) if methods else 'rm\*n' @@ -266,29 +291,37 @@ def generate_notification_function(self): def generate_oop_members(self): members = [] if self.notification_interfaces: - members.append('Core::CriticalSection _adminLock;') + members.append('mutable Core::CriticalSection _adminLock;') for interface in self.notification_interfaces: - members.append(f'std::vector _notifications{interface};') + members.append(f'{interface[1:]}NotificationVector _{interface[1:].lower()}Notification;') return '\n'.join(members) if members else 'rm\*n' def generate_notify_method(self): methods = [] - - for interface in self.notification_interfaces: - methods.append(f'void Notify{interface}() override {{') - methods.append('\n~INDENT_INCREASE~') - methods.append('\n_adminLock.Lock();') - methods.append(f'''\nfor (auto* notification : _notifications{interface}) {{ - ~INDENT_INCREASE~ - notification->{interface}Notification(); - ~INDENT_DECREASE~ - }} - _adminLock.Unlock(); - ~INDENT_DECREASE~ - }}\n''') + if self.out_of_process and self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION or not self.out_of_process and HeaderData.HeaderType.HEADER: + for interface in self.notification_interfaces: + methods.append(f'void Notify{interface}() const {{') + methods.append('\n~INDENT_INCREASE~') + methods.append('\n_adminLock.Lock();') + methods.append(f'''\nfor (auto* notification : _{interface[1:].lower()}Notification) {{ + ~INDENT_INCREASE~ + notification->{interface}Notification(); + ~INDENT_DECREASE~ + }} + _adminLock.Unlock(); + ~INDENT_DECREASE~ + }}\n''') return ''.join(methods) if methods else 'rm\*n' + def generate_using_container(self): + usings = [] + if (self.out_of_process and self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION) or \ + (not self.out_of_process and self.type == HeaderData.HeaderType.HEADER): + for comrpc in self.notification_interfaces: + usings.append(f'using {comrpc[1:]}NotificationVector = std::vector;') + return '\n'.join(usings) if usings else 'rm\*n' + def generate_keyword_map(self): return { "{{COMRPC_INTERFACE_INCLUDES}}": self.generate_comrpc_includes(), @@ -308,7 +341,8 @@ def generate_keyword_map(self): "{{NOTIFICATION_ENTRY}}" : self.generate_notification_entry(), "{{NOTIFICATION_FUNCTION}}" : self.generate_notification_function(), "{{OOP_MEMBERS}}" : self.generate_oop_members(), - "{{NOTIFY_METHOD}}" : self.generate_notify_method() + "{{NOTIFY_METHOD}}" : self.generate_notify_method(), + "{{USING_CONTAINER}}" : self.generate_using_container() } def generate_nested_map(self): @@ -318,21 +352,23 @@ def generate_nested_map(self): } def generate_jsonrpc_event(self): - if self.jsonrpc or self.notification_interfaces: + if (self.jsonrpc or self.notification_interfaces) and self.out_of_process: template_name = global_variables.RPC_NOTIFICATION_CLASS_PATH template = FileUtils.read_file(template_name) code = FileUtils.replace_keywords(template, self.keywords) return code def generate_config(self): + code = [] if self.plugin_config: + if self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION: + code.append('~INDENT_DECREASE~\nprivate:\n~INDENT_INCREASE~\n') + print("Hello)") if (not self.out_of_process) or (self.type == HeaderData.HeaderType.HEADER_IMPLEMENTATION): template_name = global_variables.CONFIG_CLASS_PATH template = FileUtils.read_file(template_name) - code = FileUtils.replace_keywords(template, self.keywords) - return code - return "rm\*n" - + code.append(f'{FileUtils.replace_keywords(template, self.keywords)}') + return ''.join(code) if code else 'rm\*n' class SourceData(FileData): def __init__( @@ -443,14 +479,39 @@ def generate_controls(self): """ def generate_plugin_method_impl(self): - if self.out_of_process: - method = [f"void {self.plugin_name}::Deactivated(RPC::IRemoteConnection* connection) {{\n\n}}\n"] + if self.out_of_process and self.notification_interfaces: + method = [f'''\nvoid {self.plugin_name}::Deactivated(RPC::IRemoteConnection* connection) {{ + ~INDENT_INCREASE~ + if (connection->Id() == _connectionId) {{ + ~INDENT_INCREASE~ + ASSERT(_service != nullptr); + Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + ~INDENT_DECREASE~ + }} + ~INDENT_DECREASE~ + }}\n'''] return "".join(method) return "rm\*n" def generate_inherited_method_impl(self): + methods = [] if not self.out_of_process: - methods = [f"void {self.plugin_name}::{inherited}Method1() {{\n\n}}\n" for inherited in self.comrpc_interfaces] + for inherited in self.comrpc_interfaces: + methods.append(f'uint32_t {self.plugin_name}::{inherited}Method1() {{') + methods.append(f'~INDENT_INCREASE~') + if Utils.replace_comrpc_to_jsonrpc(inherited) in self.jsonrpc_interfaces: + methods.append(f'''// Note this an example of a notification method that can call the JSONRPC interface equivalent. + Exchange::{Utils.replace_comrpc_to_jsonrpc(inherited)}::Event::{inherited}Notification(*this);''') + methods.append(f'return Core::ERROR_NONE;') + methods.append(f'~INDENT_DECREASE~') + methods.append(f'}}') + if inherited in self.notification_interfaces: + methods.append(f'void {self.plugin_name}::Register(Exchange::{inherited}::INotification* notification) {{') + methods.append(HeaderData.notification_registers(None, inherited)) + methods.append('}\n') + methods.append(f'void {self.plugin_name}::Unregister(const Exchange::{inherited}::INotification* notification) {{') + methods.append(HeaderData.notification_unregisters(None, inherited)) + methods.append('}\n') return ("\n").join(methods) return 'rm\*n' @@ -466,11 +527,11 @@ def generate_nested_query(self): break nested_query.append("\nrm\*n \n~INDENT_INCREASE~\n") if self.comrpc_interfaces[iteration] in self.notification_interfaces: - nested_query.append(f"_impl{self.comrpc_interfaces[iteration]}->Register(¬ification);\n") + nested_query.append(f"_impl{self.comrpc_interfaces[iteration][1:]}->Register(¬ification);\n") if any(Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[iteration]) in notif for notif in self.jsonrpc_interfaces): - nested_query.append(f'Exchange::{Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[iteration])}::Register(*this, impl{self.comrpc_interfaces[iteration]});\n') - nested_query.append(f"_impl{comrpc} = _impl{comrpc}->QueryInterface();") - nested_query.append(f'''\nif (_impl{comrpc} == nullptr) {{ + nested_query.append(f'Exchange::{Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[iteration])}::Register(*this, _impl{self.comrpc_interfaces[iteration][1:]});\n') + nested_query.append(f"_impl{comrpc[1:]} = _impl{comrpc[0][1:]}->QueryInterface();") + nested_query.append(f'''\nif (_impl{comrpc[1:]} == nullptr) {{ ~INDENT_INCREASE~ message = _T("Couldn't create instance of _impl{comrpc}") ~INDENT_DECREASE~ @@ -488,21 +549,22 @@ def generate_nested_query(self): def generate_nested_initialize(self, iteration): text = [] - rootCOMRPC = self.comrpc_interfaces[0] if self.comrpc_interfaces else 'IPlugin' + rootCOMRPC = self.comrpc_interfaces[0][1:] if self.comrpc_interfaces else 'IPlugin' if self.comrpc_interfaces: text.append("\n~INDENT_INCREASE~\n") - text.append(f'_impl{self.comrpc_interfaces[iteration]}->Register(&_notification);\n') + if self.notification_interfaces: + text.append(f'_impl{self.comrpc_interfaces[iteration][1:]}->Register(&_notification);\n') if self.jsonrpc_interfaces: if self.jsonrpc_interfaces[-1] == Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[iteration]): - text.append(f'Exchange::{self.jsonrpc_interfaces[-1]}::Register(*this, impl{self.comrpc_interfaces[iteration]});\n') + text.append(f'Exchange::{self.jsonrpc_interfaces[-1]}::Register(*this, _impl{self.comrpc_interfaces[iteration][1:]});\n') if self.plugin_config: #text.append("\n~INDENT_INCREASE~\n") text.append(f'''\nExchange::IConfiguration* configuration = _impl{rootCOMRPC}->QueryInterface(); ASSERT(configuration != nullptr); if (configuration != nullptr) {{ ~INDENT_INCREASE~ - if (configuration->configure(service) != Core::ERROR_NONE) {{ + if (configuration->Configure(service) != Core::ERROR_NONE) {{ ~INDENT_INCREASE~ message = _T("{self.plugin_name} could not be configured."); ~INDENT_DECREASE~ @@ -514,40 +576,53 @@ def generate_nested_initialize(self, iteration): return ''.join(text) if text else 'rm\*n' def generate_configure_implementation(self): - return 'Config config;\nconfig.FromString(service->ConfigLine());' if self.plugin_config else 'rm\*n' + return 'Config config;\nconfig.FromString(service->ConfigLine());\nTRACE(Trace::Information, (_T("This is just an example: [%s])"), config.Example));' if self.plugin_config else 'rm\*n' def generate_nested_deinitialize(self): text = [] if not self.comrpc_interfaces: return '' - text.append(f'if (_impl{self.comrpc_interfaces[0]} != nullptr) {{') + text.append(f'if (_impl{self.comrpc_interfaces[0][1:]} != nullptr) {{') text.append(f'\n~INDENT_INCREASE~') if self.notification_interfaces: if self.notification_interfaces[0] == self.comrpc_interfaces[0]: - text.append(f'\n_impl{self.comrpc_interfaces[0]}->Unregister(&_notification);') + text.append(f'\n_impl{self.comrpc_interfaces[0][1:]}->Unregister(&_notification);') if Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[0]) in self.jsonrpc_interfaces: text.append(f'\nExchange::{Utils.replace_comrpc_to_jsonrpc(self.comrpc_interfaces[0])}::Unregister(*this);') for comrpc in self.comrpc_interfaces[1:]: if comrpc == 'IConfiguration': break - text.append(f'''\nif (_impl{comrpc} != nullptr) {{ - \n~INDENT_INCREASE~ - _impl{comrpc}->Release();''') + text.append(f'''\nif (_impl{comrpc[1:]} != nullptr) {{ + \n~INDENT_INCREASE~\n''') if Utils.replace_comrpc_to_jsonrpc(comrpc) in self.jsonrpc_interfaces: text.append(f'\nExchange::{Utils.replace_comrpc_to_jsonrpc(comrpc)}::Unregister(*this);') if comrpc in self.notification_interfaces: - text.append(f'\n_impl{comrpc}->Unregister(&_notification);') - text.append(f'\n_impl{comrpc} = nullptr;') + text.append(f'\n_impl{comrpc[1:]}->Unregister(&_notification);') + text.append(f"\n_impl{comrpc[1:]}->Release();") + text.append(f'\n_impl{comrpc[1:]} = nullptr;') text.append('\n~INDENT_DECREASE~') text.append('\n}') text.append(f'''\nRPC::IRemoteConnection* connection(service->RemoteConnection(_connectionId)); - \nVARIABLE_IS_NOT_USED uint32_t result = _impl{self.comrpc_interfaces[0]}->Release(); - \n_impl{self.comrpc_interfaces[0]} = nullptr;''') + \nVARIABLE_IS_NOT_USED uint32_t result = _impl{self.comrpc_interfaces[0][1:]}->Release(); + \n_impl{self.comrpc_interfaces[0][1:]} = nullptr;''') return ''.join(text) - + def generate_assert_implementation(self): + asserts = [] + for comrpc in self.comrpc_interfaces: + if comrpc == 'IConfiguration': + continue + asserts.append(f'ASSERT(_impl{comrpc[1:]} == nullptr);') + return '\n'.join(asserts) + + def generate_register_notification(self): + return "_service->Register(&_notification);" + + def generate_unregister_notification(self): + return "_service->Unregister(&_notification);" + def generate_keyword_map(self): return { "{{INCLUDE}}": self.generate_include_statements(), @@ -560,6 +635,7 @@ def generate_keyword_map(self): "{{REGISTER}}": self.generate_jsonrpc_register(), "{{JSONRPC_UNREGISTER}}": self.generate_jsonrpc_unregister(), "{{COMRPC}}": f'{self.comrpc_interfaces[0] if self.comrpc_interfaces else "Exchange::IPlugin"}', + "{{COMRPC[1:]}}" : f'{self.comrpc_interfaces[0][1:] if self.comrpc_interfaces else "Exchange::IPlugin"}', "{{JSONRPC_INTERFACE_INCLUDES}}": self.generate_jsonrpc_includes(), "{{PLUGIN_METHOD_IMPL}}": self.generate_plugin_method_impl(), "{{INHERITED_METHOD_IMPL}}": self.generate_inherited_method_impl(), @@ -567,6 +643,9 @@ def generate_keyword_map(self): "{{NESTED_QUERY}}" : self.generate_nested_query(), "{{CONFIGURE_IP}}" : self.generate_configure_implementation(), "{{DEINITIALIZE}}" : self.generate_nested_deinitialize(), + "{{ASSERT_IMPL}}" : self.generate_assert_implementation(), + "{{REGISTER_NOTIFICATION}}" : self.generate_register_notification(), + "{{UNREGISTER_NOTIFICATION}}" : self.generate_unregister_notification() } def generate_nested_map(self): @@ -608,11 +687,18 @@ def generate_set_mode(self): if self.out_of_process: s = (f'set(PLUGIN_{self.plugin_name.upper()}_MODE "Local" CACHE STRING "Controls if the plugin should run in its own process, in process or remote.")') return s if s else 'rm\*n' + + def generate_set_config(self): + s = '' + if self.plugin_config: + s = (f'set(PLUGIN_{self.plugin_name.upper()}_EXAMPLE "Example Text" CACHE STRING "Example String")') + return s if s else 'rm\*n' def generate_keyword_map(self): return { "{{SOURCE_FILES}}": self.find_source_files(), - '{{SET_MODE}}' : self.generate_set_mode() + '{{SET_MODE}}' : self.generate_set_mode(), + "{{SET_CONFIG}}" : self.generate_set_config() } def find_source_files(self): @@ -650,7 +736,12 @@ def populate_keywords(self): self.keywords.update(self.generate_nested_map()) def generate_cppref(self): - return (",\n".join(f'"$cppref": "{{cppinterfacedir}}/{comrpc}.h"' for comrpc in self.comrpc_interfaces) if self.comrpc_interfaces else "rm\*n") + cppref = [] + for comrpc in self.comrpc_interfaces: + if comrpc == 'IConfiguration': + break + cppref.append(f'"$cppref": "{{cppinterfacedir}}/{comrpc}.h"') + return ",\n".join(cppref) if cppref else 'rm\*n' def generate_json_info(self): template_name = global_variables.JSON_INFO @@ -712,15 +803,18 @@ def populate_keywords(self): # self.keywords.update(self.generate_nested_map()) def generate_config(self): + configuration = [] + configuration.append("configuration = JSON()") if self.plugin_config: - return f'configuration = JSON() \nconfiguration.add("example,"mystring")' - return 'rm\*n' - + configuration.append(f'configuration.add("example", "@PLUGIN_{self.plugin_name.upper()}_EXAMPLE@")') + return '\n'.join(configuration) + def generate_root(self): root = [] if self.out_of_process: - root.append(f'root = JSON() \n root.add("mode", "@PLUGIN_{self.plugin_name.upper()}_MODE@)') - return ''.join(root) if root else 'rm\*n' + root.append(f'root = JSON() \n root.add("mode", "@PLUGIN_{self.plugin_name.upper()}_MODE@")') + root.append(f'configuration.add("root", root)') + return '\n'.join(root) if root else 'rm\*n' def generate_keyword_map(self): return { diff --git a/PluginSkeletonGenerator/help.txt b/PluginSkeletonGenerator/help.txt deleted file mode 100644 index f535040..0000000 --- a/PluginSkeletonGenerator/help.txt +++ /dev/null @@ -1,5 +0,0 @@ -To run this tool: -./PluginSkeletonGenerator.py or python3 PluginSkeletonGenerator.py - -Answer the questions accordingly. -To see examples of what the skelton is capable of, see the examples folder. \ No newline at end of file diff --git a/PluginSkeletonGenerator/menu.py b/PluginSkeletonGenerator/menu.py index 6607a04..8ad5920 100644 --- a/PluginSkeletonGenerator/menu.py +++ b/PluginSkeletonGenerator/menu.py @@ -46,6 +46,8 @@ def display_settings( print(f"JSONRPC Functionality: {jsonrpc}") print(f"JSONRPC Interfaces: {jsonrpc_interface if jsonrpc else 'N/A'} ") print(f"Out Of Process: {out_of_process}") + print(f"Plugin specific configuration: {plugin_config}") + """ print(f"Subsystem Support: {subsystems}") print(f"Subsystem Preconditions: {preconditions if subsystems else 'N/A'} ") @@ -135,7 +137,7 @@ def user_comrpc(out_of_process, comrpc_interfaces, jsonrpc_interfaces, notificat correctName = correctExtension # CorrectName at this point will always return the correct interface name without the '.h' while True: - comrpc_confirm = input(f"The name of the interface in {tempName} is (enter to confirm or type the correct interface name) {correctName}: ") + comrpc_confirm = input(f"The name of the interface in {tempName} is {correctName} (enter to confirm or type the correct interface name): ") if comrpc_confirm: correctInitial = Utils.check_correct_comrpc(comrpc_confirm) if not correctInitial: @@ -167,7 +169,7 @@ def user_comrpc(out_of_process, comrpc_interfaces, jsonrpc_interfaces, notificat def user_jsonrpc(comrpc_interface, jsonrpc_interfaces): - json_tag = get_boolean_input("Does your plugin require JSON-RPC functionality (@JSON tag): (Enter Y or N)\n") + json_tag = get_boolean_input("Does your plugin require JSON-RPC functionality (@json tag): (Enter Y or N)\n") if json_tag: jsonrpc_interface = Utils.replace_comrpc_to_jsonrpc(comrpc_interface) jsonrpc_interfaces.append(jsonrpc_interface) diff --git a/PluginSkeletonGenerator/templates/.cmake.txt b/PluginSkeletonGenerator/templates/.cmake.txt index 10f4573..eeb7c89 100644 --- a/PluginSkeletonGenerator/templates/.cmake.txt +++ b/PluginSkeletonGenerator/templates/.cmake.txt @@ -29,6 +29,7 @@ message("Setup ${MODULE_NAME} v${PROJECT_VERSION}") set(PLUGIN_{{PLUGIN_NAME_CAPS}}_STARTMODE "Activated" CACHE STRING "Automatically start {{PLUGIN_NAME}} plugin") {{SET_MODE}} +{{SET_CONFIG}} if(BUILD_REFERENCE) ~INDENT_INCREASE~ @@ -43,6 +44,7 @@ find_package(CompileSettingsDebug CONFIG REQUIRED) add_library(${MODULE_NAME} SHARED ~INDENT_INCREASE~ {{SOURCE_FILES}} + Module.cpp ~INDENT_DECREASE~ ) diff --git a/PluginSkeletonGenerator/templates/.plugin_conf_in.txt b/PluginSkeletonGenerator/templates/.plugin_conf_in.txt index 3102463..f8f1012 100644 --- a/PluginSkeletonGenerator/templates/.plugin_conf_in.txt +++ b/PluginSkeletonGenerator/templates/.plugin_conf_in.txt @@ -1,3 +1,5 @@ startmode = {{PLUGIN_STARTMODE}} + {{CONFIG}} + {{OOP_ROOT}} \ No newline at end of file diff --git a/PluginSkeletonGenerator/templates/.plugin_header.txt b/PluginSkeletonGenerator/templates/.plugin_header.txt index f9cac40..0fa0cfa 100644 --- a/PluginSkeletonGenerator/templates/.plugin_header.txt +++ b/PluginSkeletonGenerator/templates/.plugin_header.txt @@ -71,11 +71,11 @@ namespace Plugin { ~INDENT_DECREASE~ private: ~INDENT_INCREASE~ + {{USING_CONTAINER}} // Include the correct member variables for your plugin: // Note this is only an example, you are responsible for adding the correct members: uint32_t _example; - PluginHost::IShell* _service; {{MEMBER_IMPL}} ~INDENT_DECREASE~ }; diff --git a/PluginSkeletonGenerator/templates/.plugin_implementation.txt b/PluginSkeletonGenerator/templates/.plugin_implementation.txt index 38ef0b4..cc7c5b4 100644 --- a/PluginSkeletonGenerator/templates/.plugin_implementation.txt +++ b/PluginSkeletonGenerator/templates/.plugin_implementation.txt @@ -17,22 +17,20 @@ * limitations under the License. */ -#pragma once - +#include "Module.h" {{COMRPC_INTERFACE_INCLUDES}} namespace Thunder { namespace Plugin { ~INDENT_INCREASE~ - SERVICE_REGISTRATION({{PLUGIN_NAME}}Implementation, 1, 0) class {{PLUGIN_NAME}}Implementation {{OOP_INHERITED_CLASS}} { public: ~INDENT_INCREASE~ {{PLUGIN_NAME}}Implementation(const {{PLUGIN_NAME}}Implementation&) = delete; {{PLUGIN_NAME}}Implementation& operator=(const {{PLUGIN_NAME}}Implementation&) = delete; - {{PLUGIN_NAME}}({{PLUGIN_NAME}}&&) = delete; - {{PLUGIN_NAME}}& operator=({{PLUGIN_NAME}}&&) = delete; + {{PLUGIN_NAME}}Implementation({{PLUGIN_NAME}}Implementation&&) = delete; + {{PLUGIN_NAME}}Implementation& operator=({{PLUGIN_NAME}}Implementation&&) = delete; {{PLUGIN_NAME}}Implementation() ~INDENT_INCREASE~ @@ -41,6 +39,8 @@ namespace Plugin { { } ~{{PLUGIN_NAME}}Implementation() override = default; + + {{CONFIG_CLASS}} ~INDENT_DECREASE~ public: ~INDENT_INCREASE~ @@ -56,13 +56,16 @@ namespace Plugin { ~INDENT_DECREASE~ private: ~INDENT_INCREASE~ - {{CONFIG_CLASS}} +{{USING_CONTAINER}} + {{NOTIFY_METHOD}} // Note: test is just an example... uint32_t _test; {{OOP_MEMBERS}} ~INDENT_DECREASE~ }; + + SERVICE_REGISTRATION({{PLUGIN_NAME}}Implementation, 1, 0) ~INDENT_DECREASE~ } // Plugin } // Thunder \ No newline at end of file diff --git a/PluginSkeletonGenerator/templates/.plugin_source.txt b/PluginSkeletonGenerator/templates/.plugin_source.txt index d5a3c55..bce04cb 100644 --- a/PluginSkeletonGenerator/templates/.plugin_source.txt +++ b/PluginSkeletonGenerator/templates/.plugin_source.txt @@ -36,7 +36,7 @@ namespace Plugin { // Controls {} ~INDENT_DECREASE~ - ) + ); ~INDENT_DECREASE~ } @@ -54,9 +54,9 @@ void {{PLUGIN_NAME}}::Deinitialize({{VARIABLE_NOT_USED}}PluginHost::IShell* serv ~INDENT_DECREASE~ } -string {{PLUGIN_NAME}}::Information() { +string {{PLUGIN_NAME}}::Information() const { ~INDENT_INCREASE~ - return string() + return string(); ~INDENT_DECREASE~ } diff --git a/PluginSkeletonGenerator/templates/iplugin_methods/.deinitialize_oop.txt b/PluginSkeletonGenerator/templates/iplugin_methods/.deinitialize_oop.txt index fc0859c..b4ce8e9 100644 --- a/PluginSkeletonGenerator/templates/iplugin_methods/.deinitialize_oop.txt +++ b/PluginSkeletonGenerator/templates/iplugin_methods/.deinitialize_oop.txt @@ -1,14 +1,16 @@ ASSERT(_service == service); -service->Unregister(&_notification); +{{UNREGISTER_NOTIFICATION}} {{DEINITIALIZE}} + ASSERT(result == Core::ERROR_DESTRUCTION_SUCCEEDED); + // The process can disappear in the meantime... if (connection != nullptr) { ~INDENT_INCREASE~ - // But if it did not dissapear in the meantime, forcefully terminate it. Shoot to kill + // But if it did not disappear in the meantime, forcefully terminate it. Shoot to kill connection->Terminate(); connection->Release(); ~INDENT_DECREASE~ diff --git a/PluginSkeletonGenerator/templates/iplugin_methods/.initialize_oop.txt b/PluginSkeletonGenerator/templates/iplugin_methods/.initialize_oop.txt index 307910a..de7d95a 100644 --- a/PluginSkeletonGenerator/templates/iplugin_methods/.initialize_oop.txt +++ b/PluginSkeletonGenerator/templates/iplugin_methods/.initialize_oop.txt @@ -2,18 +2,18 @@ string message; ASSERT(_service == nullptr); ASSERT(service != nullptr); -ASSERT(_implementation == nullptr); +{{ASSERT_IMPL}} ASSERT(_connectionId == 0); _service = service; _service->AddRef(); -_service->Register(&_notification); +{{REGISTER_NOTIFICATION}} // Example -_impl{{COMRPC}} = service->Root(_connectionId, 2000, _T("{{PLUGIN_NAME}}Implementation")); -if (_impl{{COMRPC}} == nullptr) { +_impl{{COMRPC[1:]}} = service->Root(_connectionId, 2000, _T("{{PLUGIN_NAME}}Implementation")); +if (_impl{{COMRPC[1:]}} == nullptr) { ~INDENT_INCREASE~ - message = _T("Couldn't create instance of impl{{COMRPC}}"); + message = _T("Couldn't create instance of impl{{COMRPC[1:]}}"); ~INDENT_DECREASE~ } else { {{NESTED_QUERY}} diff --git a/PluginSkeletonGenerator/templates/module/.module_header.txt b/PluginSkeletonGenerator/templates/module/.module_header.txt index 26f37f0..fffe31c 100644 --- a/PluginSkeletonGenerator/templates/module/.module_header.txt +++ b/PluginSkeletonGenerator/templates/module/.module_header.txt @@ -25,6 +25,7 @@ #include #include +#include #undef EXTERNAL #define EXTERNAL \ No newline at end of file diff --git a/PluginSkeletonGenerator/templates/nested_class/.config_class.txt b/PluginSkeletonGenerator/templates/nested_class/.config_class.txt index cff945f..a13dd47 100644 --- a/PluginSkeletonGenerator/templates/nested_class/.config_class.txt +++ b/PluginSkeletonGenerator/templates/nested_class/.config_class.txt @@ -22,4 +22,4 @@ public: ~INDENT_INCREASE~ Core::JSON::String Example; ~INDENT_DECREASE~ -} \ No newline at end of file +}; \ No newline at end of file diff --git a/PluginSkeletonGenerator/templates/nested_class/.rpc_inotification.txt b/PluginSkeletonGenerator/templates/nested_class/.rpc_inotification.txt index bc62eee..8363553 100644 --- a/PluginSkeletonGenerator/templates/nested_class/.rpc_inotification.txt +++ b/PluginSkeletonGenerator/templates/nested_class/.rpc_inotification.txt @@ -40,4 +40,4 @@ private: ~INDENT_INCREASE~ {{PLUGIN_NAME}}& _parent; ~INDENT_DECREASE~ -} \ No newline at end of file +}; \ No newline at end of file diff --git a/PluginSkeletonGenerator/templates/nested_methods/.configure.txt b/PluginSkeletonGenerator/templates/nested_methods/.configure.txt index 28a408b..b478cc3 100644 --- a/PluginSkeletonGenerator/templates/nested_methods/.configure.txt +++ b/PluginSkeletonGenerator/templates/nested_methods/.configure.txt @@ -4,6 +4,7 @@ uint32_t Configure(PluginHost::IShell* service) override { ~INDENT_INCREASE~ Config config; config.FromString(service->ConfigLine()); + TRACE(Trace::Information, (_T("This is just an example: [%s]\n)"), config.Example)); ~INDENT_DECREASE~ } return Core::ERROR_NONE; diff --git a/PluginSkeletonGenerator/tests/IHello.h b/PluginSkeletonGenerator/tests/IHello.h new file mode 100644 index 0000000..fdcfdb6 --- /dev/null +++ b/PluginSkeletonGenerator/tests/IHello.h @@ -0,0 +1,28 @@ +#pragma once + +#include "Module.h" + +namespace Thunder { +namespace Exchange { + + // @json 1.0.0 @uncompliant:extended + struct EXTERNAL IHello: virtual public Core::IUnknown { + enum { ID = ID_VOLUMECONTROL }; + + // @event @uncompliant:extended // NOTE: extended format is deprecated!! Do not just copy this line! + struct EXTERNAL INotification : virtual public Core::IUnknown { + enum { ID = ID_VOLUMECONTROL_NOTIFICATION }; + + ~INotification() override = default; + virtual void IHelloNotification() {}; + }; + + ~IHello() override = default; + + virtual void Register(IHello::INotification* sink) {}; + virtual void Unregister(const IHello::INotification* sink) {}; + + virtual uint32_t IHelloMethod1() = 0; + }; +} +}