in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/js/js_generator.cc [3708:3936]
bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
const std::string& parameter,
GeneratorContext* context,
std::string* error) const {
std::vector<std::pair<std::string, std::string> > option_pairs;
ParseGeneratorParameter(parameter, &option_pairs);
GeneratorOptions options;
if (!options.ParseFromOptions(option_pairs, error)) {
return false;
}
if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
// All output should go in a single file.
std::string filename = options.output_dir + "/" + options.library +
options.GetFileNameExtension();
std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
io::Printer printer(
output.get(), '$',
options.annotate_code ? &annotation_collector : nullptr);
// Pull out all extensions -- we need these to generate all
// provides/requires.
std::vector<const FieldDescriptor*> extensions;
for (int i = 0; i < files.size(); i++) {
for (int j = 0; j < files[i]->extension_count(); j++) {
const FieldDescriptor* extension = files[i]->extension(j);
extensions.push_back(extension);
}
}
if (files.size() == 1) {
GenerateHeader(options, files[0], &printer);
} else {
GenerateHeader(options, nullptr, &printer);
}
std::set<std::string> provided;
FindProvides(options, &printer, files, &provided);
FindProvidesForFields(options, &printer, extensions, &provided);
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
GenerateRequiresForLibrary(options, &printer, files, &provided);
GenerateFilesInDepOrder(options, &printer, files);
for (int i = 0; i < extensions.size(); i++) {
if (ShouldGenerateExtension(extensions[i])) {
GenerateExtension(options, &printer, extensions[i]);
}
}
if (printer.failed()) {
return false;
}
if (options.annotate_code) {
EmbedCodeAnnotations(annotations, &printer);
}
} else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerSCC) {
std::set<const Descriptor*> have_printed;
SCCAnalyzer<DepsGenerator> analyzer;
std::map<const void*, std::string> allowed_map;
if (!GenerateJspbAllowedMap(options, files, &allowed_map, &analyzer)) {
return false;
}
bool generated = false;
for (int i = 0; i < files.size(); i++) {
const FileDescriptor* file = files[i];
// Force well known type to generate in a whole file.
if (IsWellKnownTypeFile(file)) {
if (!GenerateFile(file, options, context, true)) {
return false;
}
generated = true;
continue;
}
for (int j = 0; j < file->message_type_count(); j++) {
const Descriptor* desc = file->message_type(j);
if (have_printed.count(desc) ||
allowed_map.count(analyzer.GetSCC(desc)) == 0) {
continue;
}
generated = true;
const SCC* scc = analyzer.GetSCC(desc);
const std::string& filename = allowed_map[scc];
std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
io::Printer printer(
output.get(), '$',
options.annotate_code ? &annotation_collector : nullptr);
GenerateHeader(options, file, &printer);
std::set<std::string> provided;
for (auto one_desc : scc->descriptors) {
if (one_desc->containing_type() == nullptr) {
FindProvidesForMessage(options, &printer, one_desc, &provided);
}
}
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
GenerateRequiresForSCC(options, &printer, scc, &provided);
for (auto one_desc : scc->descriptors) {
if (one_desc->containing_type() == nullptr) {
GenerateClassConstructorAndDeclareExtensionFieldInfo(
options, &printer, one_desc);
}
}
for (auto one_desc : scc->descriptors) {
if (one_desc->containing_type() == nullptr) {
GenerateClass(options, &printer, one_desc);
}
}
for (auto one_desc : scc->descriptors) {
have_printed.insert(one_desc);
}
if (printer.failed()) {
return false;
}
if (options.annotate_code) {
EmbedCodeAnnotations(annotations, &printer);
}
}
for (int j = 0; j < file->enum_type_count(); j++) {
const EnumDescriptor* enumdesc = file->enum_type(j);
if (allowed_map.count(enumdesc) == 0) {
continue;
}
generated = true;
const std::string& filename = allowed_map[enumdesc];
std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
io::Printer printer(
output.get(), '$',
options.annotate_code ? &annotation_collector : nullptr);
GenerateHeader(options, file, &printer);
std::set<std::string> provided;
FindProvidesForEnum(options, &printer, enumdesc, &provided);
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
GenerateEnum(options, &printer, enumdesc);
if (printer.failed()) {
return false;
}
if (options.annotate_code) {
EmbedCodeAnnotations(annotations, &printer);
}
}
// File-level extensions (message-level extensions are generated under
// the enclosing message).
if (allowed_map.count(file) == 1) {
generated = true;
const std::string& filename = allowed_map[file];
std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
GeneratedCodeInfo annotations;
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
&annotations);
io::Printer printer(
output.get(), '$',
options.annotate_code ? &annotation_collector : nullptr);
GenerateHeader(options, file, &printer);
std::set<std::string> provided;
std::vector<const FieldDescriptor*> fields;
for (int j = 0; j < files[i]->extension_count(); j++) {
if (ShouldGenerateExtension(files[i]->extension(j))) {
fields.push_back(files[i]->extension(j));
}
}
FindProvidesForFields(options, &printer, fields, &provided);
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
GenerateRequiresForExtensions(options, &printer, fields, &provided);
for (int j = 0; j < files[i]->extension_count(); j++) {
if (ShouldGenerateExtension(files[i]->extension(j))) {
GenerateExtension(options, &printer, files[i]->extension(j));
}
}
if (options.annotate_code) {
EmbedCodeAnnotations(annotations, &printer);
}
}
}
if (!generated) {
std::string filename = options.output_dir + "/" +
"empty_no_content_void_file" +
options.GetFileNameExtension();
std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
}
} else /* options.output_mode() == kOneOutputFilePerInputFile */ {
// Generate one output file per input (.proto) file.
for (int i = 0; i < files.size(); i++) {
const FileDescriptor* file = files[i];
if (!GenerateFile(file, options, context, false)) {
return false;
}
}
}
return true;
}