diff options
author | 2016-11-17 17:04:30 -0800 | |
---|---|---|
committer | 2016-11-17 17:04:30 -0800 | |
commit | 5d63097fc2b7f405f53d6ca4ad3c1ebd98d80ddd (patch) | |
tree | 50d8116271f024e16334785464c794da85f3ce12 /src/google/protobuf/compiler | |
parent | 5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74 (diff) | |
parent | cd315dcbadc02569e145bde16e3f66c2fbb08e31 (diff) |
Merge branch 'master' into down-integrate-with-msvc-fix
Diffstat (limited to 'src/google/protobuf/compiler')
5 files changed, 113 insertions, 23 deletions
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index c1243272..78ceb68c 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -263,6 +263,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. @@ -1008,6 +1014,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 @@ -1338,15 +1356,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. @@ -1465,12 +1490,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; diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index a1a6ab39..28471ee7 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -144,14 +144,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 @@ -159,6 +159,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. @@ -314,6 +321,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. std::map<string, string> generator_parameters_; + // Similar to generator_parameters_, but stores the parameters for plugins. + std::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 6600cc2f..d5b5b185 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. diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 156784b5..979814ec 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -61,7 +61,7 @@ namespace compiler { // comma-separated string. string CommaSeparatedList(const std::vector<const FileDescriptor*> all_files) { std::vector<string> names; - for (int i = 0; i < all_files.size(); i++) { + for (size_t i = 0; i < all_files.size(); i++) { names.push_back(all_files[i]->name()); } return Join(names, ","); @@ -98,7 +98,7 @@ void MockCodeGenerator::ExpectGenerated( while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } - for (int i = 0; i < lines.size(); i++) { + for (size_t i = 0; i < lines.size(); i++) { lines[i] += "\n"; } @@ -115,7 +115,7 @@ void MockCodeGenerator::ExpectGenerated( EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]); - for (int i = 0; i < insertion_list.size(); i++) { + for (size_t i = 0; i < insertion_list.size(); i++) { EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", file, file, first_message_name), lines[1 + i]); @@ -171,7 +171,7 @@ bool MockCodeGenerator::Generate( SplitStringUsing(StripPrefixString(parameter, "insert="), ",", &insert_into); - for (int i = 0; i < insert_into.size(); i++) { + for (size_t i = 0; i < insert_into.size(); i++) { { google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert( GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 75ddb405..83e629b9 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -70,6 +70,16 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en, void Indent(google::protobuf::io::Printer* printer); void Outdent(google::protobuf::io::Printer* printer); +std::string MessagePrefix(const google::protobuf::Descriptor* message) { + // Empty cannot be php class name. + if (message->name() == "Empty" && + message->file()->package() == "google.protobuf") { + return "GPB"; + } else { + return ""; + } +} + std::string MessageName(const google::protobuf::Descriptor* message, bool is_descriptor) { string message_name = message->name(); @@ -78,6 +88,8 @@ std::string MessageName(const google::protobuf::Descriptor* message, message_name = descriptor->name() + '_' + message_name; descriptor = descriptor->containing_type(); } + message_name = MessagePrefix(message) + message_name; + return PhpName(message->file()->package(), is_descriptor) + '\\' + message_name; } @@ -483,8 +495,10 @@ void GenerateMessage(const string& name_prefix, return; } - string message_name = name_prefix.empty()? - message->name() : name_prefix + "_" + message->name(); + string message_name = + name_prefix.empty() + ? message->name() + : name_prefix + "_" + MessagePrefix(message) + message->name(); printer->Print( "class @name@ extends \\Google\\Protobuf\\Internal\\Message\n" |