summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2017-10-04 16:14:25 -0400
committerMathias Stearn <mathias@10gen.com>2017-11-02 14:25:21 -0400
commit9f8696b5ba4c9310749c5c3f1ee082c5f663b5b0 (patch)
tree53c3961ef1c4a68970d85dfc835951a00ec04b34
parentacdd51da0bda6f8bb723dd23096306a3453c8804 (diff)
downloadmongo-9f8696b5ba4c9310749c5c3f1ee082c5f663b5b0.tar.gz
SERVER-31390 Use a templating language to generate error_codes.{h,cpp,js}
-rw-r--r--.eslintignore1
-rw-r--r--buildscripts/requirements.txt2
-rw-r--r--src/mongo/base/SConscript27
-rw-r--r--src/mongo/base/error_codes.tpl.cpp77
-rw-r--r--src/mongo/base/error_codes.tpl.h82
-rw-r--r--src/mongo/base/generate_error_codes.py374
-rw-r--r--src/mongo/shell/SConscript8
-rw-r--r--src/mongo/shell/error_codes.tpl.js60
8 files changed, 320 insertions, 311 deletions
diff --git a/.eslintignore b/.eslintignore
index a1ded284b11..97755b3f9df 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1 +1,2 @@
src/mongo/gotools/*
+*.tpl.js
diff --git a/buildscripts/requirements.txt b/buildscripts/requirements.txt
index 1aef1166655..83242c053ff 100644
--- a/buildscripts/requirements.txt
+++ b/buildscripts/requirements.txt
@@ -10,3 +10,5 @@ pylint == 1.6.5
pydocstyle == 1.1.1
# resmoke.py
-r resmokelib/requirements.txt
+# generate_error_codes.py
+cheetah3 == 3.0.0; python_version < "3"
diff --git a/src/mongo/base/SConscript b/src/mongo/base/SConscript
index db569f842a5..80dc007a4bb 100644
--- a/src/mongo/base/SConscript
+++ b/src/mongo/base/SConscript
@@ -4,10 +4,29 @@ Import("env")
env = env.Clone()
-generateErrorCodes = env.Command(
- target=['error_codes.h', 'error_codes.cpp'],
- source=['generate_error_codes.py', 'error_codes.err'],
- action=['$PYTHON ${SOURCES[0]} cpp ${SOURCES[1]} --cpp-header=${TARGETS[0]} --cpp-source=${TARGETS[1]}'])
+
+# This needs to use its own env to tell scons to suppress scanning the .tpl.h and .tpl.cpp inputs
+# for #includes since they aren't directly preprocessed. Scons will still scan the generated files
+# to produce the correct implicit dependencies when they are compiled.
+env_for_error_codes = env.Clone()
+env_for_error_codes['SCANNERS'] = []
+generateErrorCodes = env_for_error_codes.Command(
+ target=[
+ 'error_codes.h',
+ 'error_codes.cpp'
+ ],
+ source=[
+ 'generate_error_codes.py',
+ 'error_codes.err',
+ 'error_codes.tpl.h',
+ 'error_codes.tpl.cpp',
+ ],
+ action=['$PYTHON ${SOURCES[0]} ${SOURCES[1]} '
+ '${SOURCES[2]}=${TARGETS[0]} '
+ '${SOURCES[3]}=${TARGETS[1]}'
+ ],
+)
+
env.Alias('generated-sources', generateErrorCodes)
env.CppUnitTest('base_test',
diff --git a/src/mongo/base/error_codes.tpl.cpp b/src/mongo/base/error_codes.tpl.cpp
new file mode 100644
index 00000000000..c1188c3bd15
--- /dev/null
+++ b/src/mongo/base/error_codes.tpl.cpp
@@ -0,0 +1,77 @@
+/**
+ * Copyright 2017 MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/base/error_codes.h"
+
+#include "mongo/base/static_assert.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+MONGO_STATIC_ASSERT(sizeof(ErrorCodes::Error) == sizeof(int));
+
+std::string ErrorCodes::errorString(Error err) {
+ switch (err) {
+ //#for $ec in $codes
+ case $ec.name:
+ return "$ec.name";
+ //#end for
+ default:
+ return mongoutils::str::stream() << "Location" << int(err);
+ }
+}
+
+ErrorCodes::Error ErrorCodes::fromString(StringData name) {
+ //#for $ec in $codes
+ if (name == "$ec.name"_sd)
+ return $ec.name;
+ //#end for
+ return UnknownError;
+}
+
+std::ostream& operator<<(std::ostream& stream, ErrorCodes::Error code) {
+ return stream << ErrorCodes::errorString(code);
+}
+
+//#for $cat in $categories
+bool ErrorCodes::is${cat.name}(Error err) {
+ switch (err) {
+ //#for $code in $cat.codes
+ case $code:
+ return true;
+ //#end for
+ default:
+ return false;
+ }
+}
+//#end for
+
+} // namespace mongo
diff --git a/src/mongo/base/error_codes.tpl.h b/src/mongo/base/error_codes.tpl.h
new file mode 100644
index 00000000000..a5ebd55042b
--- /dev/null
+++ b/src/mongo/base/error_codes.tpl.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright 2017 MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <iosfwd>
+#include <string>
+
+#include "mongo/base/string_data.h"
+
+namespace mongo {
+
+/**
+ * This is a generated class containing a table of error codes and their corresponding error
+ * strings. The class is derived from the definitions in src/mongo/base/error_codes.err file and the
+ * src/mongo/base/error_codes.tpl.h template.
+ *
+ * Do not update this file directly. Update src/mongo/base/error_codes.err instead.
+ */
+class ErrorCodes {
+public:
+ // Explicitly 32-bits wide so that non-symbolic values,
+ // like uassert codes, are valid.
+ enum Error : std::int32_t {
+ //#for $ec in $codes
+ $ec.name = $ec.code,
+ //#end for
+ MaxError
+ };
+
+ static std::string errorString(Error err);
+
+ /**
+ * Parses an Error from its "name". Returns UnknownError if "name" is unrecognized.
+ *
+ * NOTE: Also returns UnknownError for the string "UnknownError".
+ */
+ static Error fromString(StringData name);
+
+ /**
+ * Casts an integer "code" to an Error. Unrecognized codes are preserved, meaning
+ * that the result of a call to fromInt() may not be one of the values in the
+ * Error enumeration.
+ */
+ static Error fromInt(int code) {
+ return static_cast<Error>(code);
+ }
+
+ //#for $cat in $categories
+ static bool is${cat.name}(Error err);
+ //#end for
+};
+
+std::ostream& operator<<(std::ostream& stream, ErrorCodes::Error code);
+
+} // namespace mongo
diff --git a/src/mongo/base/generate_error_codes.py b/src/mongo/base/generate_error_codes.py
index b431cff415c..d3da9970692 100644
--- a/src/mongo/base/generate_error_codes.py
+++ b/src/mongo/base/generate_error_codes.py
@@ -36,29 +36,62 @@ error_code("symbol2", code2)
error_class("class1", ["symbol1", "symbol2, ..."])
Usage:
- python generate_error_codes.py <cpp|js> <path to error_codes.err> [options]
+ python generate_error_codes.py <path to error_codes.err> <template>=<output>...
"""
-usage_msg = "usage: %prog <cpp|js> /path/to/error_codes.err [options]"
+usage_msg = "usage: %prog /path/to/error_codes.err <template>=<output>..."
-from optparse import OptionParser
+from collections import namedtuple
+from Cheetah.Template import Template
import sys
+
+def render_template(template_path, **kw):
+ '''Renders the template file located at template_path, using the variables defined by kw, and
+ returns the result as a string'''
+
+ template = Template.compile(
+ file=template_path,
+ compilerSettings=dict(directiveStartToken="//#",directiveEndToken="//#"),
+ baseclass=dict,
+ useCache=False)
+ return str(template(**kw))
+
+ErrorCode = namedtuple('ErrorCode', ['name', 'code'])
+def makeErrorCode(name, code):
+ return ErrorCode(name, code)
+
+ErrorClass = namedtuple('ErrorClass', ['name', 'codes'])
+def makeErrorClass(name, codes):
+ return ErrorClass(name, codes)
+
def main(argv):
- generator = argv[1]
- error_codes, error_classes = parse_error_definitions_from_file(argv[2])
+ # Parse and validate argv.
+ if len(sys.argv) < 2:
+ usage("Must specify error_codes.err")
+ if len(sys.argv) < 3:
+ usage("Must specify at least one template=output pair")
+
+ template_outputs = []
+ for arg in sys.argv[2:]:
+ try:
+ template, output = arg.split('=', 1)
+ template_outputs.append((template, output))
+ except Exception:
+ usage("Error parsing template=output pair: " + arg)
+
+ # Parse and validate error_codes.err.
+ error_codes, error_classes = parse_error_definitions_from_file(argv[1])
check_for_conflicts(error_codes, error_classes)
- if (generator == 'cpp'):
- if (len(argv) != 5):
- usage('Wrong number of arguments')
- cpp_gen = cpp_generator(error_codes, error_classes)
- cpp_gen.generate()
- elif (generator == 'js'):
- if (len(argv) != 4):
- usage('Wrong number of arguments')
- js_gen = js_generator(error_codes, error_classes)
- js_gen.generate()
- else:
- usage('Must specify which generator(s) to use.')
+
+ # Render the templates to the output files.
+ for template, output in template_outputs:
+ text = render_template(template,
+ codes=error_codes,
+ categories=error_classes,
+ )
+
+ with open(output, 'wb') as outfile:
+ outfile.write(text)
def die(message=None):
sys.stderr.write(message or "Fatal error\n")
@@ -73,9 +106,10 @@ def parse_error_definitions_from_file(errors_filename):
errors_code = compile(errors_file.read(), errors_filename, 'exec')
error_codes = []
error_classes = []
- eval(errors_code, dict(error_code=lambda *args: error_codes.append(args),
- error_class=lambda *args: error_classes.append(args)))
- error_codes.sort(key=lambda x: x[1])
+ eval(errors_code,
+ dict(error_code=lambda *args, **kw: error_codes.append(makeErrorCode(*args, **kw)),
+ error_class=lambda *args: error_classes.append(makeErrorClass(*args))))
+ error_codes.sort(key=lambda x: x.code)
return error_codes, error_classes
def check_for_conflicts(error_codes, error_classes):
@@ -88,28 +122,30 @@ def check_for_conflicts(error_codes, error_classes):
die()
def has_duplicate_error_codes(error_codes):
- sorted_by_name = sorted(error_codes, key=lambda x: x[0])
- sorted_by_code = sorted(error_codes, key=lambda x: x[1])
+ sorted_by_name = sorted(error_codes, key=lambda x: x.name)
+ sorted_by_code = sorted(error_codes, key=lambda x: x.code)
failed = False
- prev_name, prev_code = sorted_by_name[0]
- for name, code in sorted_by_name[1:]:
- if name == prev_name:
- sys.stdout.write('Duplicate name %s with codes %s and %s\n' % (name, code, prev_code))
+ prev = sorted_by_name[0]
+ for curr in sorted_by_name[1:]:
+ if curr.name == prev.name:
+ sys.stdout.write('Duplicate name %s with codes %s and %s\n'
+ % (curr.name, curr.code, prev.code))
failed = True
- prev_name, prev_code = name, code
+ prev = curr
- prev_name, prev_code = sorted_by_code[0]
- for name, code in sorted_by_code[1:]:
- if code == prev_code:
- sys.stdout.write('Duplicate code %s with names %s and %s\n' % (code, name, prev_name))
+ prev = sorted_by_code[0]
+ for curr in sorted_by_code[1:]:
+ if curr.code == prev.code:
+ sys.stdout.write('Duplicate code %s with names %s and %s\n'
+ % (curr.code, curr.name, prev.name))
failed = True
- prev_name, prev_code = name, code
+ prev = curr
return failed
def has_duplicate_error_classes(error_classes):
- names = sorted(ec[0] for ec in error_classes)
+ names = sorted(ec.name for ec in error_classes)
failed = False
prev_name = names[0]
@@ -130,277 +166,5 @@ def has_missing_error_codes(error_codes, error_classes):
failed = True
return failed
-class base_generator(object):
- def __init__(self, error_codes, error_classes):
- self.error_codes = error_codes
- self.error_classes = error_classes
-
- def parseOptions(self, options, usage_msg):
- parser = OptionParser(usage=usage_msg)
- for (f,d,n,m,h) in options:
- parser.add_option(f,dest=d,nargs=n,metavar=m,help=h)
- (options, args) = parser.parse_args()
- return options
-
-
-class js_generator(base_generator):
- def __init__(self, error_codes, error_classes):
- super(js_generator, self).__init__(error_codes, error_classes)
- options = [('--js-source','js_source',1,'DEST_JS_SOURCE','specify dest JS source file to save to')]
- options = self.parseOptions(options, usage_msg)
- if (options.js_source):
- self.js_source = options.js_source
- else:
- usage('Must specify JS source files')
-
- def generate(self):
- self.generate_source()
-
- def generate_source(self):
- string_to_int_cases = ',\n '.join(
- '%s: %s' % (ec[0], ec[1]) for ec in self.error_codes)
- int_to_string_cases = ',\n '.join(
- '%s: \'%s\'' % (ec[1], ec[0]) for ec in self.error_codes)
- predicate_definitions = '\n\n'.join(
- self.generate_error_class_predicate_definition(*ec) for ec in self.error_classes)
- open(self.js_source, 'wb').write(self.source_template % dict(
- string_to_int_cases=string_to_int_cases,
- int_to_string_cases=int_to_string_cases
- ))
-
- def generate_error_class_predicate_definition(self, class_name, code_names):
- cases = '\n '.join('case \'%s\':' % c for c in code_names)
- return self.error_class_predicate_template % dict(class_name=class_name, cases=cases)
-
- source_template = '''// AUTO-GENERATED FILE DO NOT EDIT
-// See src/mongo/base/generate_error_codes.py
-/* Copyright 2015 MongoDB, Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* As a special exception, the copyright holders give permission to link the
-* code of portions of this program with the OpenSSL library under certain
-* conditions as described in each individual source file and distribute
-* linked combinations including the program with the OpenSSL library. You
-* must comply with the GNU Affero General Public License in all respects
-* for all of the code used other than as permitted herein. If you modify
-* file(s) with this exception, you may extend this exception to your
-* version of the file(s), but you are not obligated to do so. If you do not
-* wish to do so, delete this exception statement from your version. If you
-* delete this exception statement from all source files in the program,
-* then also delete it in the license file.
-*/
-
-var ErrorCodes = {
- %(string_to_int_cases)s
-};
-
-var ErrorCodeStrings = {
- %(int_to_string_cases)s
-};
-'''
-
- error_class_predicate_template = '''function is%(class_name)s(err) {
- if (typeof err === 'string') {
- error = err;
- } else if (typeof err === 'number') {
- error = ErrorCodeStrings[err];
- }
- switch (error) {
- %(cases)s
- return true;
- default:
- return false;
- }
-}
-'''
-
-class cpp_generator(base_generator):
- def __init__(self, error_codes, error_classes):
- super(cpp_generator, self).__init__(error_codes, error_classes)
- options = [('--cpp-header','cpp_header',1,'DEST_CPP_HEADER','specify dest CPP header file to save to'), ('--cpp-source','cpp_source',1,'DEST_CPP_SOURCE','specify dest CPP source file to save to')]
- options = self.parseOptions(options, usage_msg)
- if (options.cpp_header and options.cpp_source):
- self.cpp_header = options.cpp_header
- self.cpp_source = options.cpp_source
- else:
- usage('Must specify CPP header and source files')
-
- def generate(self):
- self.generate_header()
- self.generate_source()
-
- def generate_header(self):
-
- enum_declarations = ',\n '.join('%s = %s' % ec for ec in self.error_codes)
- predicate_declarations = ';\n '.join(
- 'static bool is%s(Error err)' % ec[0] for ec in self.error_classes)
-
- open(self.cpp_header, 'wb').write(self.header_template % dict(
- error_code_enum_declarations=enum_declarations,
- error_code_class_predicate_declarations=predicate_declarations))
-
- def generate_source(self):
- symbol_to_string_cases = ';\n '.join(
- 'case %s: return "%s"' % (ec[0], ec[0]) for ec in self.error_codes)
- string_to_symbol_cases = ';\n '.join(
- 'if (name == "%s") return %s' % (ec[0], ec[0])
- for ec in self.error_codes)
- int_to_symbol_cases = ';\n '.join(
- 'case %s: return %s' % (ec[0], ec[0]) for ec in self.error_codes)
- predicate_definitions = '\n '.join(
- self.generate_error_class_predicate_definition(*ec) for ec in self.error_classes)
- open(self.cpp_source, 'wb').write(self.source_template % dict(
- symbol_to_string_cases=symbol_to_string_cases,
- string_to_symbol_cases=string_to_symbol_cases,
- int_to_symbol_cases=int_to_symbol_cases,
- error_code_class_predicate_definitions=predicate_definitions))
-
- def generate_error_class_predicate_definition(self, class_name, code_names):
- cases = '\n '.join('case %s:' % c for c in code_names)
- return self.error_class_predicate_template % dict(class_name=class_name, cases=cases)
-
- header_template = '''// AUTO-GENERATED FILE DO NOT EDIT
-// See src/mongo/base/generate_error_codes.py
-/* Copyright 2014 MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-#pragma once
-#include <string>
-#include <cstdint>
-#include <iosfwd>
-#include "mongo/base/string_data.h"
-namespace mongo {
- /**
- * This is a generated class containing a table of error codes and their corresponding error
- * strings. The class is derived from the definitions in src/mongo/base/error_codes.err file.
- *
- * Do not update this file directly. Update src/mongo/base/error_codes.err instead.
- */
- class ErrorCodes {
- public:
- // Explicitly 32-bits wide so that non-symbolic values,
- // like uassert codes, are valid.
- enum Error : std::int32_t {
- %(error_code_enum_declarations)s,
- MaxError
- };
- static std::string errorString(Error err);
- /**
- * Parses an Error from its "name". Returns UnknownError if "name" is unrecognized.
- *
- * NOTE: Also returns UnknownError for the string "UnknownError".
- */
- static Error fromString(StringData name);
- /**
- * Casts an integer "code" to an Error. Unrecognized codes are preserved, meaning
- * that the result of a call to fromInt() may not be one of the values in the
- * Error enumeration.
- */
- static Error fromInt(int code) {
- return static_cast<Error>(code);
- }
- %(error_code_class_predicate_declarations)s;
- };
-
- std::ostream& operator<<(std::ostream& stream, ErrorCodes::Error code);
-} // namespace mongo
-'''
-
- source_template = '''// AUTO-GENERATED FILE DO NOT EDIT
-// See src/mongo/base/generate_error_codes.py
-/* Copyright 2014 MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-#include "mongo/base/error_codes.h"
-#include "mongo/util/mongoutils/str.h"
-namespace mongo {
- std::string ErrorCodes::errorString(Error err) {
- switch (err) {
- %(symbol_to_string_cases)s;
- default: return mongoutils::str::stream() << "Location" << int(err);
- }
- }
- ErrorCodes::Error ErrorCodes::fromString(StringData name) {
- %(string_to_symbol_cases)s;
- return UnknownError;
- }
- std::ostream& operator<<(std::ostream& stream, ErrorCodes::Error code) {
- return stream << ErrorCodes::errorString(code);
- }
- %(error_code_class_predicate_definitions)s
-namespace {
- static_assert(sizeof(ErrorCodes::Error) == sizeof(int), "sizeof(ErrorCodes::Error) == sizeof(int)");
-} // namespace
-} // namespace mongo
-'''
-
- error_class_predicate_template = '''bool ErrorCodes::is%(class_name)s(Error err) {
- switch (err) {
- %(cases)s
- return true;
- default:
- return false;
- }
- }
-'''
-
-
if __name__ == '__main__':
main(sys.argv)
diff --git a/src/mongo/shell/SConscript b/src/mongo/shell/SConscript
index d342f1edc68..090ec5b7cc6 100644
--- a/src/mongo/shell/SConscript
+++ b/src/mongo/shell/SConscript
@@ -6,8 +6,12 @@ env = env.Clone()
generateJSErrorCodes = env.Command(
target=['error_codes.js'],
- source=['$BUILD_DIR/mongo/base/generate_error_codes.py', '$BUILD_DIR/mongo/base/error_codes.err'],
- action=['$PYTHON ${SOURCES[0]} js ${SOURCES[1]} --js-source=${TARGETS[0]}'])
+ source=[
+ '$BUILD_DIR/mongo/base/generate_error_codes.py',
+ '$BUILD_DIR/mongo/base/error_codes.err',
+ 'error_codes.tpl.js',
+ ],
+ action=['$PYTHON ${SOURCES[0]} ${SOURCES[1]} ${SOURCES[2]}=${TARGETS[0]}'])
env.Alias('generated-sources', generateJSErrorCodes)
# Files added here need to be added in scripting/engine.cpp and buildscripts/vcxproj.header as well.
diff --git a/src/mongo/shell/error_codes.tpl.js b/src/mongo/shell/error_codes.tpl.js
new file mode 100644
index 00000000000..120c0626eb2
--- /dev/null
+++ b/src/mongo/shell/error_codes.tpl.js
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2017 MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+var ErrorCodes = {
+ //#for $ec in $codes
+ '$ec.name': $ec.code,
+ //#end for
+};
+
+var ErrorCodeStrings = {
+ //#for $ec in $codes
+ $ec.code: '$ec.name',
+ //#end for
+};
+
+//#for $cat in $categories
+ErrorCodes.is${cat.name} = function(err) {
+ 'use strict';
+
+ var error;
+ if (typeof err === 'string') {
+ error = err;
+ } else if (typeof err === 'number') {
+ error = ErrorCodeStrings[err];
+ }
+ switch (error) {
+ //#for $code in $cat.codes
+ case '$code':
+ return true;
+ //#end for
+ default:
+ return false;
+ }
+};
+//#end for