summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/idl/idl/ast.py1
-rw-r--r--buildscripts/idl/idl/binder.py34
-rw-r--r--buildscripts/idl/idl/common.py15
-rw-r--r--buildscripts/idl/idl/enum_types.py11
-rw-r--r--buildscripts/idl/idl/parser.py33
-rw-r--r--buildscripts/idl/idl/syntax.py6
-rw-r--r--src/mongo/db/session_txn_record.idl10
-rw-r--r--src/mongo/idl/idl_test.cpp6
-rw-r--r--src/mongo/idl/unittest.idl8
-rw-r--r--src/mongo/idl/unittest_import.idl12
-rw-r--r--src/mongo/util/uuid.h8
11 files changed, 117 insertions, 27 deletions
diff --git a/buildscripts/idl/idl/ast.py b/buildscripts/idl/idl/ast.py
index cd925d709a4..e0aa71d0b34 100644
--- a/buildscripts/idl/idl/ast.py
+++ b/buildscripts/idl/idl/ast.py
@@ -179,6 +179,7 @@ class Enum(common.SourceLocation):
"""Construct an Enum."""
self.name = None # type: unicode
self.description = None # type: unicode
+ self.cpp_namespace = None # type: unicode
self.type = None # type: unicode
self.values = [] # type: List[EnumValue]
diff --git a/buildscripts/idl/idl/binder.py b/buildscripts/idl/idl/binder.py
index 354acca9742..9addc6b6104 100644
--- a/buildscripts/idl/idl/binder.py
+++ b/buildscripts/idl/idl/binder.py
@@ -392,6 +392,31 @@ def _validate_doc_sequence_field(ctxt, ast_field):
ctxt.add_bad_non_object_as_doc_sequence_error(ast_field, ast_field.name)
+def _normalize_method_name(cpp_type_name, cpp_method_name):
+ # type: (unicode, unicode) -> unicode
+ """Normalize the method name to be fully-qualified with the type name."""
+ # Default deserializer
+ if not cpp_method_name:
+ return cpp_method_name
+
+ # Global function
+ if cpp_method_name.startswith('::'):
+ return cpp_method_name
+
+ # Method is full qualified already
+ if cpp_method_name.startswith(cpp_type_name):
+ return cpp_method_name
+
+ # Get the unqualified type name
+ type_name = cpp_type_name.split("::")[-1]
+
+ # Method is prefixed with just the type name
+ if cpp_method_name.startswith(type_name):
+ return '::'.join(cpp_type_name.split('::')[0:-1]) + "::" + cpp_method_name
+
+ return cpp_method_name
+
+
def _bind_field(ctxt, parsed_spec, field):
# type: (errors.ParserContext, syntax.IDLSpec, syntax.Field) -> ast.Field
"""
@@ -444,7 +469,7 @@ def _bind_field(ctxt, parsed_spec, field):
# Copy over only the needed information if this a struct or a type
if isinstance(syntax_symbol, syntax.Struct):
struct = cast(syntax.Struct, syntax_symbol)
- ast_field.struct_type = struct.name
+ ast_field.struct_type = common.qualify_cpp_name(struct.cpp_namespace, struct.name)
ast_field.bson_serialization_type = ["object"]
_validate_field_of_type_struct(ctxt, field)
@@ -452,7 +477,7 @@ def _bind_field(ctxt, parsed_spec, field):
enum_type_info = enum_types.get_type_info(cast(syntax.Enum, syntax_symbol))
ast_field.enum_type = True
- ast_field.cpp_type = enum_type_info.get_cpp_type_name()
+ ast_field.cpp_type = enum_type_info.get_qualified_cpp_type_name()
ast_field.bson_serialization_type = enum_type_info.get_bson_types()
ast_field.serializer = enum_type_info.get_enum_serializer_name()
ast_field.deserializer = enum_type_info.get_enum_deserializer_name()
@@ -466,8 +491,8 @@ def _bind_field(ctxt, parsed_spec, field):
ast_field.cpp_type = idltype.cpp_type
ast_field.bson_serialization_type = idltype.bson_serialization_type
ast_field.bindata_subtype = idltype.bindata_subtype
- ast_field.serializer = idltype.serializer
- ast_field.deserializer = idltype.deserializer
+ ast_field.serializer = _normalize_method_name(idltype.cpp_type, idltype.serializer)
+ ast_field.deserializer = _normalize_method_name(idltype.cpp_type, idltype.deserializer)
ast_field.default = idltype.default
if field.default:
@@ -627,6 +652,7 @@ def _bind_enum(ctxt, idl_enum):
ast_enum.name = idl_enum.name
ast_enum.description = idl_enum.description
ast_enum.type = idl_enum.type
+ ast_enum.cpp_namespace = idl_enum.cpp_namespace
enum_type_info = enum_types.get_type_info(idl_enum)
if not enum_type_info:
diff --git a/buildscripts/idl/idl/common.py b/buildscripts/idl/idl/common.py
index 7eb4bbe4e1e..1a52477998d 100644
--- a/buildscripts/idl/idl/common.py
+++ b/buildscripts/idl/idl/common.py
@@ -31,6 +31,12 @@ COMMAND_NAMESPACE_IGNORED = "ignored"
def title_case(name):
# type: (unicode) -> unicode
"""Return a CapitalCased version of a string."""
+
+ # Only capitalize the last part of a fully-qualified name
+ pos = name.rfind("::")
+ if pos > -1:
+ return name[:pos + 2] + name[pos + 2:pos + 3].upper() + name[pos + 3:]
+
return name[0:1].upper() + name[1:]
@@ -40,6 +46,15 @@ def camel_case(name):
return name[0:1].lower() + name[1:]
+def qualify_cpp_name(cpp_namespace, cpp_type_name):
+ # type: (unicode, unicode) -> unicode
+ """Preprend a type name with a C++ namespace if cpp_namespace is not None."""
+ if cpp_namespace:
+ return cpp_namespace + "::" + cpp_type_name
+
+ return cpp_type_name
+
+
def _escape_template_string(template):
# type: (unicode) -> unicode
"""Escape the '$' in template strings unless followed by '{'."""
diff --git a/buildscripts/idl/idl/enum_types.py b/buildscripts/idl/idl/enum_types.py
index 3caed6f67da..e9e7214d2ad 100644
--- a/buildscripts/idl/idl/enum_types.py
+++ b/buildscripts/idl/idl/enum_types.py
@@ -40,6 +40,11 @@ class EnumTypeInfoBase(object):
"""Construct a EnumTypeInfoBase."""
self._enum = idl_enum
+ def get_qualified_cpp_type_name(self):
+ # type: () -> unicode
+ """Get the fully qualified C++ type name for an enum."""
+ return common.qualify_cpp_name(self._enum.cpp_namespace, self.get_cpp_type_name())
+
@abstractmethod
def get_cpp_type_name(self):
# type: () -> unicode
@@ -61,7 +66,8 @@ class EnumTypeInfoBase(object):
def get_enum_deserializer_name(self):
# type: () -> unicode
"""Return the name of deserializer function with non-method prefix."""
- return "::" + self._get_enum_deserializer_name()
+ return "::" + common.qualify_cpp_name(self._enum.cpp_namespace,
+ self._get_enum_deserializer_name())
def _get_enum_serializer_name(self):
# type: () -> unicode
@@ -72,7 +78,8 @@ class EnumTypeInfoBase(object):
def get_enum_serializer_name(self):
# type: () -> unicode
"""Return the name of serializer function with non-method prefix."""
- return "::" + self._get_enum_serializer_name()
+ return "::" + common.qualify_cpp_name(self._enum.cpp_namespace,
+ self._get_enum_serializer_name())
@abstractmethod
def get_cpp_value_assignment(self, enum_value):
diff --git a/buildscripts/idl/idl/parser.py b/buildscripts/idl/idl/parser.py
index fd0af9b1445..0f45fe93255 100644
--- a/buildscripts/idl/idl/parser.py
+++ b/buildscripts/idl/idl/parser.py
@@ -27,6 +27,7 @@ from yaml import nodes
from typing import Any, Callable, Dict, List, Set, Tuple, Union
from . import common
+from . import cpp_types
from . import errors
from . import syntax
@@ -427,6 +428,36 @@ def _parse_command(ctxt, spec, name, node):
spec.symbols.add_command(ctxt, command)
+def _prefix_with_namespace(cpp_namespace, cpp_name):
+ # type: (unicode, unicode) -> unicode
+ """Preface a C++ type name with a namespace if not already qualified or a primitive type."""
+ if "::" in cpp_name or cpp_types.is_primitive_scalar_type(cpp_name):
+ return cpp_name
+
+ return cpp_namespace + "::" + cpp_name
+
+
+def _propagate_globals(spec):
+ # type: (syntax.IDLSpec) -> None
+ """Propagate the globals information to each type and struct as needed."""
+ if not spec.globals or not spec.globals.cpp_namespace:
+ return
+
+ cpp_namespace = spec.globals.cpp_namespace
+
+ for struct in spec.symbols.structs:
+ struct.cpp_namespace = cpp_namespace
+
+ for command in spec.symbols.commands:
+ command.cpp_namespace = cpp_namespace
+
+ for idlenum in spec.symbols.enums:
+ idlenum.cpp_namespace = cpp_namespace
+
+ for idltype in spec.symbols.types:
+ idltype.cpp_type = _prefix_with_namespace(cpp_namespace, idltype.cpp_type)
+
+
def _parse(stream, error_file_name):
# type: (Any, unicode) -> syntax.IDLParsedSpec
"""
@@ -483,6 +514,8 @@ def _parse(stream, error_file_name):
if ctxt.errors.has_errors():
return syntax.IDLParsedSpec(None, ctxt.errors)
else:
+ _propagate_globals(spec)
+
return syntax.IDLParsedSpec(spec, None)
diff --git a/buildscripts/idl/idl/syntax.py b/buildscripts/idl/idl/syntax.py
index 056d2e9dc3a..6ea14171f74 100644
--- a/buildscripts/idl/idl/syntax.py
+++ b/buildscripts/idl/idl/syntax.py
@@ -350,6 +350,9 @@ class Struct(common.SourceLocation):
# imported file, and no code is generated for it.
self.imported = False # type: bool
+ # Internal property: cpp_namespace from globals section
+ self.cpp_namespace = None # type: unicode
+
super(Struct, self).__init__(file_name, line, column)
@@ -403,4 +406,7 @@ class Enum(common.SourceLocation):
# imported file, and no code is generated for it.
self.imported = False # type: bool
+ # Internal property: cpp_namespace from globals section
+ self.cpp_namespace = None # type: unicode
+
super(Enum, self).__init__(file_name, line, column)
diff --git a/src/mongo/db/session_txn_record.idl b/src/mongo/db/session_txn_record.idl
index c9924a32a32..c7943d0964b 100644
--- a/src/mongo/db/session_txn_record.idl
+++ b/src/mongo/db/session_txn_record.idl
@@ -35,15 +35,7 @@ global:
imports:
- "mongo/idl/basic_types.idl"
- "mongo/db/logical_session_id.idl"
-
-# TODO: SERVER-31278 import from repl/replication_types.idl instead
-types:
- optime:
- bson_serialization_type: object
- description: A document representing an OpTime.
- cpp_type: "repl::OpTime"
- serializer: repl::OpTime::toBSON
- deserializer: repl::OpTime::parse
+ - "mongo/db/repl/replication_types.idl"
structs:
sessionTxnRecord:
diff --git a/src/mongo/idl/idl_test.cpp b/src/mongo/idl/idl_test.cpp
index 9f26f03633f..fe2a845aa3d 100644
--- a/src/mongo/idl/idl_test.cpp
+++ b/src/mongo/idl/idl_test.cpp
@@ -35,6 +35,7 @@
#include "mongo/util/net/op_msg.h"
using namespace mongo::idl::test;
+using namespace mongo::idl::import;
namespace mongo {
@@ -896,7 +897,8 @@ TEST(IDLArrayTests, TestArraysOfComplexTypes) {
assert_same_types<decltype(testStruct.getField4()),
const std::vector<mongo::ObjectBasicType>&>();
assert_same_types<decltype(testStruct.getField5()), const std::vector<mongo::BSONObj>&>();
- assert_same_types<decltype(testStruct.getField6()), const std::vector<mongo::One_string>&>();
+ assert_same_types<decltype(testStruct.getField6()),
+ const std::vector<mongo::idl::import::One_string>&>();
assert_same_types<decltype(testStruct.getField1o()),
const boost::optional<std::vector<std::int64_t>>&>();
@@ -909,7 +911,7 @@ TEST(IDLArrayTests, TestArraysOfComplexTypes) {
assert_same_types<decltype(testStruct.getField5o()),
const boost::optional<std::vector<mongo::BSONObj>>&>();
assert_same_types<decltype(testStruct.getField6o()),
- const boost::optional<std::vector<mongo::One_string>>&>();
+ const boost::optional<std::vector<mongo::idl::import::One_string>>&>();
std::vector<std::int64_t> field1{1, 2, 3};
ASSERT_TRUE(field1 == testStruct.getField1());
diff --git a/src/mongo/idl/unittest.idl b/src/mongo/idl/unittest.idl
index ccb16e86dca..159977fadeb 100644
--- a/src/mongo/idl/unittest.idl
+++ b/src/mongo/idl/unittest.idl
@@ -110,14 +110,6 @@ types:
##################################################################################################
enums:
- IntEnum:
- description: "An example int enum"
- type: int
- values:
- a0: 0
- b1: 1
- c2: 2
-
StringEnum:
description: "An example string enum"
type: string
diff --git a/src/mongo/idl/unittest_import.idl b/src/mongo/idl/unittest_import.idl
index 73e25833d67..9cf75014cd8 100644
--- a/src/mongo/idl/unittest_import.idl
+++ b/src/mongo/idl/unittest_import.idl
@@ -15,7 +15,7 @@
# IDL Unit Tests IDL file for testing imported structs
global:
- cpp_namespace: "mongo"
+ cpp_namespace: "mongo::idl::import"
imports:
- "mongo/idl/basic_types.idl"
@@ -97,3 +97,13 @@ structs:
description: UnitTest for a single UUID
fields:
value: uuid
+
+enums:
+
+ IntEnum:
+ description: "An example int enum"
+ type: int
+ values:
+ a0: 0
+ b1: 1
+ c2: 2
diff --git a/src/mongo/util/uuid.h b/src/mongo/util/uuid.h
index d5c3f7c71b3..61f55ab044c 100644
--- a/src/mongo/util/uuid.h
+++ b/src/mongo/util/uuid.h
@@ -45,6 +45,12 @@ namespace repl {
class OplogEntryBase;
} // namespace repl
+namespace idl {
+namespace import {
+class One_UUID;
+} // namespace import
+} // namespace idl
+
/**
* A UUID is a 128-bit unique identifier, per RFC 4122, v4, using
* a secure random number generator.
@@ -55,7 +61,7 @@ class UUID {
// Make the IDL generated parser a friend
friend class ConfigsvrShardCollectionResponse;
friend class DbCheckOplogCollection;
- friend class One_UUID;
+ friend class idl::import::One_UUID;
friend class LogicalSessionId;
friend class LogicalSessionToClient;
friend class LogicalSessionIdToClient;