diff --git a/src/code_generation/cpp/cpp_class.py b/src/code_generation/cpp/cpp_class.py index b546244..576b67e 100644 --- a/src/code_generation/cpp/cpp_class.py +++ b/src/code_generation/cpp/cpp_class.py @@ -331,6 +331,12 @@ def __init__(self, **properties): # class enums self.internal_enum_elements = [] + # class using type definitions + self.internal_enum_elements = [] + + # class using type definitions + self.internal_using_type_elements = [] + def _parent_class(self): """ @return: parent class object @@ -352,6 +358,13 @@ def add_enum(self, enum): enum.ref_to_parent = self self.internal_enum_elements.append(enum) + def add_using_type(self, using): + """ + @param: enum CppEnum instance + """ + using.ref_to_parent = self + self.internal_using_type_elements.append(using) + def add_variable(self, cpp_variable): """ @param: cpp_variable CppVariable instance @@ -405,6 +418,15 @@ def _render_enum_section(self, cpp): enumItem.render_to_string(cpp) cpp.newline() + def _render_using_type_section(self, cpp): + """ + Render to string all contained enums + Method is protected as it is used by CppClass only + """ + for using_typeItem in self.internal_using_type_elements: + using_typeItem.render_to_string(cpp) + cpp.newline() + def _render_variables_declaration(self, cpp): """ Render to string all contained variable class members @@ -478,6 +500,7 @@ def class_interface(self, cpp): Should be placed in 'public:' section """ self._render_enum_section(cpp) + self._render_using_type_section(cpp) self._render_internal_classes_declaration(cpp) self._render_methods_declaration(cpp) diff --git a/src/code_generation/cpp/cpp_using_type.py b/src/code_generation/cpp/cpp_using_type.py new file mode 100644 index 0000000..e2142a5 --- /dev/null +++ b/src/code_generation/cpp/cpp_using_type.py @@ -0,0 +1,82 @@ +from code_generation.cpp.cpp_generator import CppLanguageElement, CppDeclaration, CppImplementation +from textwrap import dedent + +__doc__ = """The module encapsulates C++ code generation logics for main C++ language primitives: +classes, methods and functions, variables, enums. +Every C++ element could render its current state to a string that could be evaluated as +a legal C++ construction. + +For detailed information see code_generator.py documentation. +""" + + +# noinspection PyUnresolvedReferences +class CppUsingType(CppLanguageElement): + """ + The Python class that generates string representation for C++ variable (automatic or class member) + For example: + class MyClass + { + int m_var1; + double m_var2; + ... + } + Available properties: + type - string, variable type + initialization_value - string, initialization_value to be initialized with. + 'a = initialization_value;' for automatic variables, 'a(initialization_value)' for the class member + documentation - string, '/// Example doxygen' + is_class_member - boolean, for appropriate definition/declaration rendering + """ + availablePropertiesNames = {'type', + 'documentation', + 'is_class_member'} | CppLanguageElement.availablePropertiesNames + + def __init__(self, **properties): + input_property_names = set(properties.keys()) + self.check_input_properties_names(input_property_names) + super(CppUsingType, self).__init__(properties) + self.init_class_properties(current_class_properties=self.availablePropertiesNames, + input_properties_dict=properties) + + def declaration(self): + """ + @return: CppDeclaration wrapper, that could be used + for declaration rendering using render_to_string(cpp) interface + """ + return CppDeclaration(self) + + def definition(self): + """ + @return: CppImplementation wrapper, that could be used + for definition rendering using render_to_string(cpp) interface + """ + return CppImplementation(self) + + def render_to_string(self, cpp): + """ + Only automatic variables or static const class members could be rendered using this method + Generates complete variable definition, e.g. + """ + if self.documentation: + cpp(dedent(self.documentation)) + cpp(f'using {self.name} = {self.type};') + + def render_to_string_declaration(self, cpp): + """ + Generates declaration for the class member variables, for example + int m_var; + """ + if not self.is_class_member: + raise RuntimeError( + 'For automatic variable use its render_to_string() method') + + if self.documentation and self.is_class_member: + cpp(dedent(self.documentation)) + cpp(f'using {self.name} = {self.type};') + + def render_to_string_implementation(self, cpp): + """ + Using has no implementation + """ + return None diff --git a/tests/create_assets.py b/tests/create_assets.py index 7173e7a..4686cd4 100644 --- a/tests/create_assets.py +++ b/tests/create_assets.py @@ -117,10 +117,10 @@ def generate_func(output_dir='.'): def function_body(_, cpp1): cpp1('return 42;') - functions = [CppFunction(name='GetParam', ret_type='int'), - CppFunction(name='Calculate', ret_type='void'), + functions = [CppFunction(name='GetParam', ret_type='int', implementation_handle=lambda _, cpp: cpp("return 1;")), + CppFunction(name='Calculate', ret_type='void', implementation_handle=lambda _, cpp: cpp("return;")), CppFunction(name='GetAnswer', ret_type='int', implementation_handle=function_body), - CppFunction(name='Help', ret_type='char *', documentation='/// Returns the help documentation.'), + CppFunction(name='Help', ret_type='char *', documentation='/// Returns the help documentation.', implementation_handle=lambda _, cpp: cpp("return nullptr;")), ] for func in functions: func.render_to_string(hpp) @@ -195,30 +195,27 @@ def generate_class(output_dir='.'): def method_body(_, cpp1): cpp1('return m_var1;') - my_class.add_method(CppFunction(name="GetParam", + my_class.add_method(CppClass.CppMethod(name="GetParam", ret_type="int", - is_method=True, is_const=True, implementation_handle=method_body)) - my_class.add_method(CppFunction(name="VirtualMethod", + my_class.add_method(CppClass.CppMethod(name="VirtualMethod", ret_type="int", - is_method=True, - is_virtual=True)) + is_virtual=True, implementation_handle=method_body)) - my_class.add_method(CppFunction(name="PureVirtualMethod", + my_class.add_method(CppClass.CppMethod(name="PureVirtualMethod", ret_type="void", - is_method=True, is_virtual=True, is_pure_virtual=True)) - example_class.add_method(CppFunction( + example_class.add_method(CppClass.CppMethod( name="DoNothing", documentation="""\ /** * Example multiline documentation. */""", - ret_type="void"), + ret_type="void", implementation_handle=lambda _, cpp: cpp("return;")), ) my_class.declaration().render_to_string(my_class_h) diff --git a/tests/test_cpp_file.py b/tests/test_cpp_file.py index 2679bbf..441e6d4 100644 --- a/tests/test_cpp_file.py +++ b/tests/test_cpp_file.py @@ -8,6 +8,7 @@ from code_generation.cpp.cpp_array import CppArray from code_generation.cpp.cpp_function import CppFunction from code_generation.cpp.cpp_class import CppClass +from code_generation.cpp.cpp_using_type import CppUsingType __doc__ = """ Unit tests for C++ code generator @@ -114,6 +115,8 @@ def static_method_body(_, cpp): is_static=True, implementation_handle=static_method_body)) + my_class.add_using_type(CppUsingType(name='FooType', type='double')) + my_class.declaration().render_to_string(my_class_h) my_class.definition().render_to_string(my_class_cpp)