bool Generator::GenerateAll()

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;
}