1#include "google/protobuf/compiler/code_generator.h" 2#include "google/protobuf/io/zero_copy_stream.h" 3#include "google/protobuf/io/printer.h" 4#include "google/protobuf/descriptor.h" 5#include "google/protobuf/descriptor.pb.h" 6#include "schema_proto2_to_proto3_util.h" 7 8#include "google/protobuf/compiler/plugin.h" 9 10using google::protobuf::FileDescriptorProto; 11using google::protobuf::FileDescriptor; 12using google::protobuf::DescriptorPool; 13using google::protobuf::io::Printer; 14using google::protobuf::util::SchemaGroupStripper; 15using google::protobuf::util::EnumScrubber; 16using google::protobuf::util::ExtensionStripper; 17using google::protobuf::util::FieldScrubber; 18 19namespace google { 20namespace protobuf { 21namespace compiler { 22 23namespace { 24 25string StripProto(string filename) { 26 return filename.substr(0, filename.rfind(".proto")); 27} 28 29DescriptorPool* GetPool() { 30 static DescriptorPool *pool = new DescriptorPool(); 31 return pool; 32} 33 34} // namespace 35 36class Proto2ToProto3Generator final : public CodeGenerator { 37 public: 38 bool GenerateAll(const std::vector<const FileDescriptor*>& files, 39 const string& parameter, 40 GeneratorContext* context, 41 string* error) const { 42 for (int i = 0; i < files.size(); i++) { 43 for (auto file : files) { 44 if (CanGenerate(file)) { 45 Generate(file, parameter, context, error); 46 break; 47 } 48 } 49 } 50 51 return true; 52 } 53 54 bool Generate(const FileDescriptor* file, 55 const string& parameter, 56 GeneratorContext* context, 57 string* error) const { 58 FileDescriptorProto new_file; 59 file->CopyTo(&new_file); 60 SchemaGroupStripper::StripFile(file, &new_file); 61 62 EnumScrubber enum_scrubber; 63 enum_scrubber.ScrubFile(&new_file); 64 ExtensionStripper::StripFile(&new_file); 65 FieldScrubber::ScrubFile(&new_file); 66 new_file.set_syntax("proto3"); 67 68 string filename = file->name(); 69 string basename = StripProto(filename); 70 71 std::vector<std::pair<string,string>> option_pairs; 72 ParseGeneratorParameter(parameter, &option_pairs); 73 74 std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( 75 context->Open(basename + ".proto")); 76 string content = GetPool()->BuildFile(new_file)->DebugString(); 77 Printer printer(output.get(), '$'); 78 printer.WriteRaw(content.c_str(), content.size()); 79 80 return true; 81 } 82 private: 83 bool CanGenerate(const FileDescriptor* file) const { 84 if (GetPool()->FindFileByName(file->name()) != nullptr) { 85 return false; 86 } 87 for (int j = 0; j < file->dependency_count(); j++) { 88 if (GetPool()->FindFileByName(file->dependency(j)->name()) == nullptr) { 89 return false; 90 } 91 } 92 for (int j = 0; j < file->public_dependency_count(); j++) { 93 if (GetPool()->FindFileByName( 94 file->public_dependency(j)->name()) == nullptr) { 95 return false; 96 } 97 } 98 for (int j = 0; j < file->weak_dependency_count(); j++) { 99 if (GetPool()->FindFileByName( 100 file->weak_dependency(j)->name()) == nullptr) { 101 return false; 102 } 103 } 104 return true; 105 } 106}; 107 108} // namespace compiler 109} // namespace protobuf 110} // namespace google 111 112int main(int argc, char* argv[]) { 113 google::protobuf::compiler::Proto2ToProto3Generator generator; 114 return google::protobuf::compiler::PluginMain(argc, argv, &generator); 115} 116