aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2016-10-25 17:43:59 -0700
committerGravatar Jisi Liu <jisi.liu@gmail.com>2016-10-25 17:43:59 -0700
commit59cd5d0e26c180117d9d5fe16be536e63d29e332 (patch)
tree39f93cc85796962cc78ccd72eed1fc017b43fda4 /src/google/protobuf/compiler
parent58580da37357941d502805be3ae520441be77728 (diff)
Support extra parameters for plugins.
Diffstat (limited to 'src/google/protobuf/compiler')
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc44
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h25
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc38
3 files changed, 91 insertions, 16 deletions
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 79d2dd66..584175bf 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -262,6 +262,10 @@ void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
return;
}
}
+
+string PluginName(const string& plugin_prefix, const string& directive) {
+ return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
+}
} // namespace
// A MultiFileErrorCollector that prints errors to stderr.
@@ -1007,6 +1011,18 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
return status;
}
+ // Make sure each plugin option has a matching plugin output.
+ for (map<string, string>::const_iterator i = plugin_parameters_.begin();
+ i != plugin_parameters_.end(); ++i) {
+ if (plugins_.find(i->first) == plugins_.end()) {
+ std::cerr << "Unknown flag: "
+ // strip prefix + "gen-" and add back "_opt"
+ << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt"
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ }
+
// If no --proto_path was given, use the current working directory.
if (proto_path_.empty()) {
// Don't use make_pair as the old/default standard library on Solaris
@@ -1335,15 +1351,22 @@ CommandLineInterface::InterpretArgument(const string& name,
(plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
// Check if it's a generator option flag.
generator_info = FindOrNull(generators_by_option_name_, name);
- if (generator_info == NULL) {
- std::cerr << "Unknown flag: " << name << std::endl;
- return PARSE_ARGUMENT_FAIL;
- } else {
+ if (generator_info != NULL) {
string* parameters = &generator_parameters_[generator_info->flag_name];
if (!parameters->empty()) {
parameters->append(",");
}
parameters->append(value);
+ } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) {
+ string* parameters =
+ &plugin_parameters_[PluginName(plugin_prefix_, name)];
+ if (!parameters->empty()) {
+ parameters->append(",");
+ }
+ parameters->append(value);
+ } else {
+ std::cerr << "Unknown flag: " << name << std::endl;
+ return PARSE_ARGUMENT_FAIL;
}
} else {
// It's an output flag. Add it to the output directives.
@@ -1463,11 +1486,16 @@ bool CommandLineInterface::GenerateOutput(
<< "Bad name for plugin generator: " << output_directive.name;
// Strip the "--" and "_out" and add the plugin prefix.
- string plugin_name = plugin_prefix_ + "gen-" +
- output_directive.name.substr(2, output_directive.name.size() - 6);
-
+ string plugin_name = PluginName(plugin_prefix_ , output_directive.name);
+ string parameters = output_directive.parameter;
+ if (!plugin_parameters_[plugin_name].empty()) {
+ if (!parameters.empty()) {
+ parameters.append(",");
+ }
+ parameters.append(plugin_parameters_[plugin_name]);
+ }
if (!GeneratePluginOutput(parsed_files, plugin_name,
- output_directive.parameter,
+ parameters,
generator_context, &error)) {
std::cerr << output_directive.name << ": " << error << std::endl;
return false;
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index c38e65a3..d779fc87 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -146,14 +146,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
// --out indicates the output directory (as passed to the --foo_out
// parameter); if omitted, the current directory should be used. --parameter
- // gives the generator parameter, if any was provided. The PROTO_FILES list
- // the .proto files which were given on the compiler command-line; these are
- // the files for which the plugin is expected to generate output code.
- // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
- // descriptor.proto). This is piped to the plugin's stdin. The set will
- // include descriptors for all the files listed in PROTO_FILES as well as
- // all files that they import. The plugin MUST NOT attempt to read the
- // PROTO_FILES directly -- it must use the FileDescriptorSet.
+ // gives the generator parameter, if any was provided (see below). The
+ // PROTO_FILES list the .proto files which were given on the compiler
+ // command-line; these are the files for which the plugin is expected to
+ // generate output code. Finally, DESCRIPTORS is an encoded FileDescriptorSet
+ // (as defined in descriptor.proto). This is piped to the plugin's stdin.
+ // The set will include descriptors for all the files listed in PROTO_FILES as
+ // well as all files that they import. The plugin MUST NOT attempt to read
+ // the PROTO_FILES directly -- it must use the FileDescriptorSet.
//
// The plugin should generate whatever files are necessary, as code generators
// normally do. It should write the names of all files it generates to
@@ -161,6 +161,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// names or relative to the current directory. If any errors occur, error
// messages should be written to stderr. If an error is fatal, the plugin
// should exit with a non-zero exit code.
+ //
+ // Plugins can have generator parameters similar to normal built-in
+ // generators. Extra generator parameters can be passed in via a matching
+ // "_opt" parameter. For example:
+ // protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
+ // This will pass "enable_bar,enable_baz" as the parameter to the plugin.
+ //
void AllowPlugins(const string& exe_name_prefix);
// Run the Protocol Compiler with the given command-line parameters.
@@ -316,6 +323,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
map<string, string> generator_parameters_;
+ // Similar to generator_parameters_, but stores the parameters for plugins.
+ map<string, string> plugin_parameters_;
// See AllowPlugins(). If this is empty, plugins aren't allowed.
string plugin_prefix_;
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 56a07dbf..dfbaa45a 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -653,6 +653,44 @@ TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
"test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
}
+TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) {
+ // Test that generator parameters specified with the option flag are
+ // correctly passed to the code generator.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ // Create the "a" and "b" sub-directories.
+ CreateTempDir("a");
+ CreateTempDir("b");
+
+ Run("protocol_compiler "
+ "--plug_opt=foo1 "
+ "--plug_out=bar:$tmpdir/a "
+ "--plug_opt=foo2 "
+ "--plug_out=baz:$tmpdir/b "
+ "--plug_opt=foo3 "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated(
+ "test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+ ExpectGenerated(
+ "test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--unknown_plug_opt=Foo "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Unknown flag: --unknown_plug_opt");
+}
+
TEST_F(CommandLineInterfaceTest, Insert) {
// Test running a generator that inserts code into another's output.