You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.4 KiB

#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "schema_proto2_to_proto3_util.h"
#include "google/protobuf/compiler/plugin.h"
using google::protobuf::FileDescriptorProto;
using google::protobuf::FileDescriptor;
using google::protobuf::DescriptorPool;
using google::protobuf::io::Printer;
using google::protobuf::util::SchemaGroupStripper;
using google::protobuf::util::EnumScrubber;
using google::protobuf::util::ExtensionStripper;
using google::protobuf::util::FieldScrubber;
namespace google {
namespace protobuf {
namespace compiler {
namespace {
string StripProto(string filename) {
return filename.substr(0, filename.rfind(".proto"));
}
DescriptorPool* GetPool() {
static DescriptorPool *pool = new DescriptorPool();
return pool;
}
} // namespace
class Proto2ToProto3Generator final : public CodeGenerator {
public:
bool GenerateAll(const std::vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* context,
string* error) const {
for (int i = 0; i < files.size(); i++) {
for (auto file : files) {
if (CanGenerate(file)) {
Generate(file, parameter, context, error);
break;
}
}
}
return true;
}
bool Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* context,
string* error) const {
FileDescriptorProto new_file;
file->CopyTo(&new_file);
SchemaGroupStripper::StripFile(file, &new_file);
EnumScrubber enum_scrubber;
enum_scrubber.ScrubFile(&new_file);
ExtensionStripper::StripFile(&new_file);
FieldScrubber::ScrubFile(&new_file);
new_file.set_syntax("proto3");
string filename = file->name();
string basename = StripProto(filename);
std::vector<std::pair<string,string>> option_pairs;
ParseGeneratorParameter(parameter, &option_pairs);
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
context->Open(basename + ".proto"));
string content = GetPool()->BuildFile(new_file)->DebugString();
Printer printer(output.get(), '$');
printer.WriteRaw(content.c_str(), content.size());
return true;
}
private:
bool CanGenerate(const FileDescriptor* file) const {
if (GetPool()->FindFileByName(file->name()) != nullptr) {
return false;
}
for (int j = 0; j < file->dependency_count(); j++) {
if (GetPool()->FindFileByName(file->dependency(j)->name()) == nullptr) {
return false;
}
}
for (int j = 0; j < file->public_dependency_count(); j++) {
if (GetPool()->FindFileByName(
file->public_dependency(j)->name()) == nullptr) {
return false;
}
}
for (int j = 0; j < file->weak_dependency_count(); j++) {
if (GetPool()->FindFileByName(
file->weak_dependency(j)->name()) == nullptr) {
return false;
}
}
return true;
}
};
} // namespace compiler
} // namespace protobuf
} // namespace google
int main(int argc, char* argv[]) {
google::protobuf::compiler::Proto2ToProto3Generator generator;
return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}