Merge pull request #2284 from pherl/plugin_opt
Support extra parameters for plugins.
This commit is contained in:
commit
734930f919
@ -262,6 +262,12 @@ void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string PluginName(const string& plugin_prefix, const string& directive) {
|
||||
// Assuming the directive starts with "--" and ends with "_out" or "_opt",
|
||||
// strip the "--" and "_out/_opt" and add the plugin prefix.
|
||||
return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// A MultiFileErrorCollector that prints errors to stderr.
|
||||
@ -1007,6 +1013,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 +1353,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.
|
||||
@ -1462,12 +1487,16 @@ bool CommandLineInterface::GenerateOutput(
|
||||
HasSuffixString(output_directive.name, "_out"))
|
||||
<< "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;
|
||||
|
@ -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_;
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user