aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt5
-rw-r--r--CONTRIBUTORS.txt2
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc40
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h7
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc53
5 files changed, 101 insertions, 6 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2a86a63c..94fe94e1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,11 @@
be normally except without a tag before each value (thus, they are
tightly "packed").
+ protoc
+ * --error_format=msvs option causes errors to be printed in Visual Studio
+ format, which should allow them to be clicked on in the build log to go
+ directly to the error location.
+
C++
* UnknownFieldSet now supports STL-like iteration.
* Message interface has method ParseFromBoundedZeroCopyStream() which parses
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index e212467e..3755f743 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -55,3 +55,5 @@ Non-Google patch contributors:
* Solaris 10 + Sun Studio fix.
Alek Storm <alek.storm@gmail.com>
* Slicing support for repeated scalar fields for the Python API.
+ Oleg Smolsky <oleg.smolsky@gmail.com>
+ * MS Visual Studio error format option.
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 09473ec7..3629f682 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -132,18 +132,29 @@ void SetFdToBinaryMode(int fd) {
class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
public io::ErrorCollector {
public:
- ErrorPrinter() {}
+ ErrorPrinter(ErrorFormat format) : format_(format) {}
~ErrorPrinter() {}
// implements MultiFileErrorCollector ------------------------------
void AddError(const string& filename, int line, int column,
const string& message) {
+
+ cerr << filename;
+
// Users typically expect 1-based line/column numbers, so we add 1
// to each here.
- cerr << filename;
if (line != -1) {
- cerr << ":" << (line + 1) << ":" << (column + 1);
+ // Allow for both GCC- and Visual-Studio-compatible output.
+ switch (format_) {
+ case CommandLineInterface::ERROR_FORMAT_GCC:
+ cerr << ":" << (line + 1) << ":" << (column + 1);
+ break;
+ case CommandLineInterface::ERROR_FORMAT_MSVS:
+ cerr << "(" << (line + 1) << ") : error in column=" << (column + 1);
+ break;
+ }
}
+
cerr << ": " << message << endl;
}
@@ -151,6 +162,9 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
void AddError(int line, int column, const string& message) {
AddError("input", line, column, message);
}
+
+ private:
+ const ErrorFormat format_;
};
// -------------------------------------------------------------------
@@ -294,6 +308,7 @@ CommandLineInterface::ErrorReportingFileOutput::~ErrorReportingFileOutput() {
CommandLineInterface::CommandLineInterface()
: mode_(MODE_COMPILE),
+ error_format_(ERROR_FORMAT_GCC),
imports_in_descriptor_set_(false),
disallow_services_(false),
inputs_are_proto_path_relative_(false) {}
@@ -326,7 +341,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
}
// Allocate the Importer.
- ErrorPrinter error_collector;
+ ErrorPrinter error_collector(error_format_);
Importer importer(&source_tree, &error_collector);
vector<const FileDescriptor*> parsed_files;
@@ -657,6 +672,16 @@ bool CommandLineInterface::InterpretArgument(const string& name,
codec_type_ = value;
+ } else if (name == "--error_format") {
+ if (value == "gcc") {
+ error_format_ = ERROR_FORMAT_GCC;
+ } else if (value == "msvs") {
+ error_format_ = ERROR_FORMAT_MSVS;
+ } else {
+ cerr << "Unknown error format: " << value << endl;
+ return false;
+ }
+
} else {
// Some other flag. Look it up in the generators list.
GeneratorMap::const_iterator iter = generators_.find(name);
@@ -722,7 +747,10 @@ void CommandLineInterface::PrintHelpText() {
" the input files to FILE.\n"
" --include_imports When using --descriptor_set_out, also include\n"
" all dependencies of the input files in the\n"
-" set, so that the set is self-contained." << endl;
+" set, so that the set is self-contained.\n"
+" --error_format=FORMAT Set the format in which to print errors.\n"
+" FORMAT may be 'gcc' (the default) or 'msvs'\n"
+" (Microsoft Visual Studio format)." << endl;
for (GeneratorMap::iterator iter = generators_.begin();
iter != generators_.end(); ++iter) {
@@ -788,7 +816,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
if (mode_ == MODE_ENCODE) {
// Input is text.
- ErrorPrinter error_collector;
+ ErrorPrinter error_collector(error_format_);
TextFormat::Parser parser;
parser.RecordErrorsTo(&error_collector);
parser.AllowPartialMessage(true);
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 86eeba53..ec658636 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -210,6 +210,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
Mode mode_;
+ enum ErrorFormat {
+ ERROR_FORMAT_GCC, // GCC error output format (default).
+ ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
+ };
+
+ ErrorFormat error_format_;
+
vector<pair<string, string> > proto_path_; // Search path for proto files.
vector<string> input_files_; // Names of the input proto files.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 0780729d..af765b87 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -1047,6 +1047,59 @@ TEST_F(CommandLineInterfaceTest, HelpText) {
ExpectErrorSubstring("Test error output.");
}
+TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
+ // Test --error_format=gcc (which is the default, but we want to verify
+ // that it can be set explicitly).
+
+ RegisterGenerator("test_generator", "--test_out",
+ "output.test", "Test output.");
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=gcc foo.proto");
+
+ ExpectErrorText(
+ "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
+ // Test --error_format=msvs
+
+ RegisterGenerator("test_generator", "--test_out",
+ "output.test", "Test output.");
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=msvs foo.proto");
+
+ ExpectErrorText(
+ "foo.proto(2) : error in column=1: Expected top-level statement "
+ "(e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
+ // Test --error_format=msvs
+
+ RegisterGenerator("test_generator", "--test_out",
+ "output.test", "Test output.");
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=invalid foo.proto");
+
+ ExpectErrorText(
+ "Unknown error format: invalid\n");
+}
+
// -------------------------------------------------------------------
// Flag parsing tests