diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-06-19 14:22:19 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-06-19 17:17:49 -0400 |
commit | 6b311efc1742cdb94381cc929c85ce8e5480b218 (patch) | |
tree | fcb2db2d87081f0c11b142079436b5aeec595d46 /buildscripts/idl | |
parent | 1babec6a705c242628a765935ac9d98b56a41218 (diff) | |
download | mongo-6b311efc1742cdb94381cc929c85ce8e5480b218.tar.gz |
SERVER-29715 IDL generator for commands with required namespace should generate a constructor
Diffstat (limited to 'buildscripts/idl')
-rw-r--r-- | buildscripts/idl/idl/generator.py | 47 | ||||
-rw-r--r-- | buildscripts/idl/idl/struct_types.py | 68 |
2 files changed, 71 insertions, 44 deletions
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py index 673f351e11c..5ac49cda708 100644 --- a/buildscripts/idl/idl/generator.py +++ b/buildscripts/idl/idl/generator.py @@ -332,6 +332,14 @@ class _CppHeaderFileWriter(_CppFileWriterBase): return writer.IndentedScopedBlock(self._writer, 'class %s {' % common.title_case(class_name), '};') + def gen_class_constructors(self, struct): + # type: (ast.Struct) -> None + """Generate the declarations for the class constructors.""" + struct_type_info = struct_types.get_struct_info(struct) + + if struct_type_info.get_constructor_method(): + self._writer.write_line(struct_type_info.get_constructor_method().get_declaration()) + def gen_serializer_methods(self, struct): # type: (ast.Struct) -> None """Generate a serializer method declarations.""" @@ -529,6 +537,10 @@ class _CppHeaderFileWriter(_CppFileWriterBase): self.write_empty_line() # Write constructor + self.gen_class_constructors(struct) + self.write_empty_line() + + # Write serialization self.gen_serializer_methods(struct) if isinstance(struct, ast.Command): @@ -693,16 +705,15 @@ class _CppSourceFileWriter(_CppFileWriterBase): object_value = self._gen_field_deserializer_expression('element', field) self._writer.write_line('%s = %s;' % (_get_field_member_name(field), object_value)) - def gen_command_namespace_check(self, command): - # type: (ast.Command) -> None - """Generate a namespace check for a command.""" - - with self._predicate("firstFieldFound == false"): - struct_type_info = struct_types.get_struct_info(command) - struct_type_info.gen_namespace_check(self._writer) + def gen_constructors(self, struct): + # type: (ast.Struct) -> None + """Generate the C++ constructor definitions.""" - self._writer.write_line('firstFieldFound = true;') - self._writer.write_line('continue;') + struct_type_info = struct_types.get_struct_info(struct) + if struct_type_info.get_constructor_method(): + with self._block('%s : _nss(nss) {' % + (struct_type_info.get_constructor_method().get_definition()), '}'): + self._writer.write_line('// Used for initialization only') def gen_deserializer_methods(self, struct): # type: (ast.Struct) -> None @@ -713,7 +724,13 @@ class _CppSourceFileWriter(_CppFileWriterBase): with self._block('%s {' % (struct_type_info.get_deserializer_static_method().get_definition()), '}'): - self._writer.write_line('%s object;' % common.title_case(struct.name)) + if isinstance(struct, ast.Command) and struct_type_info.get_constructor_method(): + self._writer.write_line('%s object(%s);' % ( + common.title_case(struct.name), + 'ctxt.parseNSCollectionRequired(dbName, bsonObject.firstElement())')) + else: + self._writer.write_line('%s object;' % common.title_case(struct.name)) + self._writer.write_line(struct_type_info.get_deserializer_method().get_call('object')) self._writer.write_line('return object;') @@ -731,8 +748,12 @@ class _CppSourceFileWriter(_CppFileWriterBase): self._writer.write_line('const auto fieldName = element.fieldNameStringData();') self._writer.write_empty_line() + # For commands, we need to skip over the first field if isinstance(struct, ast.Command): - self.gen_command_namespace_check(struct) + with self._predicate("firstFieldFound == false"): + self._writer.write_line('firstFieldFound = true;') + self._writer.write_line('continue;') + self._writer.write_empty_line() field_usage_check.add_store() self._writer.write_empty_line() @@ -988,6 +1009,10 @@ class _CppSourceFileWriter(_CppFileWriterBase): self.gen_string_constants_definitions(struct) self.write_empty_line() + # Write constructor + self.gen_constructors(struct) + self.write_empty_line() + # Write deserializer self.gen_deserializer_methods(struct) self.write_empty_line() diff --git a/buildscripts/idl/idl/struct_types.py b/buildscripts/idl/idl/struct_types.py index 1a92b1ed4f8..82ec208d65c 100644 --- a/buildscripts/idl/idl/struct_types.py +++ b/buildscripts/idl/idl/struct_types.py @@ -27,7 +27,7 @@ from . import writer class MethodInfo(object): """Class that encapslates information about a method and how to declare, define, and call it.""" - def __init__(self, class_name, method_name, args, return_type, static=False, const=False): + def __init__(self, class_name, method_name, args, return_type=None, static=False, const=False): # type: (unicode, unicode, List[unicode], unicode, bool, bool) -> None # pylint: disable=too-many-arguments """Create a MethodInfo instance.""" @@ -43,16 +43,21 @@ class MethodInfo(object): """Get a declaration for a method.""" pre_modifiers = '' post_modifiers = '' + return_type_str = '' + if self._static: pre_modifiers = 'static ' if self._const: post_modifiers = ' const' + if self._return_type: + return_type_str = self._return_type + ' ' + return common.template_args( - "${pre_modifiers}${return_type} ${method_name}(${args})${post_modifiers};", + "${pre_modifiers}${return_type}${method_name}(${args})${post_modifiers};", pre_modifiers=pre_modifiers, - return_type=self._return_type, + return_type=return_type_str, method_name=self._method_name, args=', '.join(self._args), post_modifiers=post_modifiers) @@ -62,14 +67,18 @@ class MethodInfo(object): """Get a definition for a method.""" pre_modifiers = '' post_modifiers = '' + return_type_str = '' if self._const: post_modifiers = ' const' + if self._return_type: + return_type_str = self._return_type + ' ' + return common.template_args( - "${pre_modifiers}${return_type} ${class_name}::${method_name}(${args})${post_modifiers}", + "${pre_modifiers}${return_type}${class_name}::${method_name}(${args})${post_modifiers}", pre_modifiers=pre_modifiers, - return_type=self._return_type, + return_type=return_type_str, class_name=self._class_name, method_name=self._method_name, args=', '.join(self._args), @@ -98,6 +107,12 @@ class StructTypeInfoBase(object): __metaclass__ = ABCMeta @abstractmethod + def get_constructor_method(self): + # type: () -> MethodInfo + """Get the constructor method for a struct.""" + pass + + @abstractmethod def get_serializer_method(self): # type: () -> MethodInfo """Get the serializer method for a struct.""" @@ -139,12 +154,6 @@ class StructTypeInfoBase(object): """Serialize the first field of a Command.""" pass - @abstractmethod - def gen_namespace_check(self, indented_writer): - # type: (writer.IndentedTextWriter) -> None - """Generate the namespace check predicate for a command.""" - pass - class _StructTypeInfo(StructTypeInfoBase): """Class for struct code generation.""" @@ -154,6 +163,10 @@ class _StructTypeInfo(StructTypeInfoBase): """Create a _StructTypeInfo instance.""" self._struct = struct + def get_constructor_method(self): + # type: () -> MethodInfo + pass + def get_serializer_method(self): # type: () -> MethodInfo return MethodInfo( @@ -193,10 +206,6 @@ class _StructTypeInfo(StructTypeInfoBase): # type: (writer.IndentedTextWriter) -> None pass - def gen_namespace_check(self, indented_writer): - # type: (writer.IndentedTextWriter) -> None - pass - class _IgnoredCommandTypeInfo(_StructTypeInfo): """Class for command code generation.""" @@ -236,10 +245,6 @@ class _IgnoredCommandTypeInfo(_StructTypeInfo): # type: (writer.IndentedTextWriter) -> None indented_writer.write_line('builder->append("%s", 1);' % (self._command.name)) - def gen_namespace_check(self, indented_writer): - # type: (writer.IndentedTextWriter) -> None - pass - class _CommandWithNamespaceTypeInfo(_StructTypeInfo): """Class for command code generation.""" @@ -251,23 +256,24 @@ class _CommandWithNamespaceTypeInfo(_StructTypeInfo): super(_CommandWithNamespaceTypeInfo, self).__init__(command) + def get_constructor_method(self): + # type: () -> MethodInfo + class_name = common.title_case(self._struct.name) + return MethodInfo(class_name, class_name, ['const NamespaceString& nss']) + def get_serializer_method(self): # type: () -> MethodInfo # Commands that require namespaces require it as a parameter to serialize() return MethodInfo( common.title_case(self._struct.name), - 'serialize', ['const NamespaceString& ns', 'BSONObjBuilder* builder'], + 'serialize', ['BSONObjBuilder* builder'], 'void', const=True) def get_to_bson_method(self): # type: () -> MethodInfo # Commands that require namespaces require it as a parameter to serialize() - return MethodInfo( - common.title_case(self._struct.name), - 'toBSON', ['const NamespaceString& ns'], - 'BSONObj', - const=True) + return MethodInfo(common.title_case(self._struct.name), 'toBSON', [], 'BSONObj', const=True) def get_deserializer_static_method(self): # type: () -> MethodInfo @@ -290,20 +296,16 @@ class _CommandWithNamespaceTypeInfo(_StructTypeInfo): def gen_getter_method(self, indented_writer): # type: (writer.IndentedTextWriter) -> None - indented_writer.write_line('const NamespaceString& getNamespace() const { return _ns; }') + indented_writer.write_line('const NamespaceString& getNamespace() const { return _nss; }') def gen_member(self, indented_writer): # type: (writer.IndentedTextWriter) -> None - indented_writer.write_line('NamespaceString _ns;') + indented_writer.write_line('NamespaceString _nss;') def gen_serializer(self, indented_writer): # type: (writer.IndentedTextWriter) -> None - indented_writer.write_line('builder->append("%s", ns.toString());' % (self._command.name)) - - def gen_namespace_check(self, indented_writer): - # type: (writer.IndentedTextWriter) -> None - # TODO: should the name of the first element be validated?? - indented_writer.write_line('_ns = ctxt.parseNSCollectionRequired(dbName, element);') + indented_writer.write_line('builder->append("%s", _nss.coll());' % (self._command.name)) + indented_writer.write_empty_line() def get_struct_info(struct): |