[ObjC] Move GenerateHeader over to Printer::Emit.

Update ImportWriter to have a second Emit api for the runtime files to
streamline things a bit better.

PiperOrigin-RevId: 492210147
pull/11087/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 75d31befc6
commit 4df096f1e9
  1. 2
      objectivec/GPBAny.pbobjc.h
  2. 2
      objectivec/GPBApi.pbobjc.h
  3. 2
      objectivec/GPBDuration.pbobjc.h
  4. 2
      objectivec/GPBEmpty.pbobjc.h
  5. 2
      objectivec/GPBFieldMask.pbobjc.h
  6. 2
      objectivec/GPBSourceContext.pbobjc.h
  7. 2
      objectivec/GPBStruct.pbobjc.h
  8. 2
      objectivec/GPBTimestamp.pbobjc.h
  9. 2
      objectivec/GPBType.pbobjc.h
  10. 2
      objectivec/GPBWrappers.pbobjc.h
  11. 2
      src/google/protobuf/compiler/objectivec/enum_field.cc
  12. 299
      src/google/protobuf/compiler/objectivec/file.cc
  13. 57
      src/google/protobuf/compiler/objectivec/import_writer.cc
  14. 13
      src/google/protobuf/compiler/objectivec/import_writer.h
  15. 2
      src/google/protobuf/compiler/objectivec/map_field.cc
  16. 4
      src/google/protobuf/compiler/objectivec/message_field.cc

@ -177,4 +177,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -298,4 +298,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -133,4 +133,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -60,4 +60,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -261,4 +261,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -65,4 +65,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -192,4 +192,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -162,4 +162,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -432,4 +432,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -207,4 +207,4 @@ CF_EXTERN_C_END
// @@protoc_insertion_point(global_scope)
// clange-format on
// clang-format on

@ -134,7 +134,7 @@ void EnumFieldGenerator::DetermineForwardDeclarations(
!IsProtobufLibraryBundledProtoFile(descriptor_->enum_type()->file())) {
// Enum name is already in "storage_type".
const std::string& name = variable("storage_type");
fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
fwd_decls->insert(absl::StrCat("GPB_ENUM_FWD_DECLARE(", name, ");"));
}
}

@ -44,6 +44,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "google/protobuf/compiler/objectivec/enum.h"
#include "google/protobuf/compiler/objectivec/extension.h"
#include "google/protobuf/compiler/objectivec/import_writer.h"
@ -242,155 +243,172 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
}
void FileGenerator::GenerateHeader(io::Printer* printer) const {
std::vector<std::string> headers;
// Generated files bundled with the library get minimal imports, everything
// else gets the wrapper so everything is usable.
if (is_bundled_proto_) {
headers.push_back("GPBDescriptor.h");
headers.push_back("GPBMessage.h");
headers.push_back("GPBRootObject.h");
for (int i = 0; i < file_->dependency_count(); i++) {
const std::string header_name = BundledFileName(file_->dependency(i));
headers.push_back(header_name);
}
} else {
headers.push_back("GPBProtocolBuffers.h");
}
PrintFileRuntimePreamble(printer, headers);
// Add some verification that the generated code matches the source the
// code is being compiled with.
// NOTE: This captures the raw numeric values at the time the generator was
// compiled, since that will be the versions for the ObjC runtime at that
// time. The constants in the generated code will then get their values at
// at compile time (so checking against the headers being used to compile).
// clang-format off
printer->Print(
"#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
"#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
"#endif\n"
"#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
"#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
"#endif\n"
"\n",
"google_protobuf_objc_version", absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
// clang-format on
// The bundled protos (WKTs) don't use of forward declarations.
bool headers_use_forward_declarations =
generation_options_.headers_use_forward_declarations &&
!is_bundled_proto_;
{
ImportWriter import_writer(
generation_options_.generate_for_named_framework,
generation_options_.named_framework_to_proto_path_mappings_path,
generation_options_.runtime_import_prefix,
/* include_wkt_imports = */ false);
const std::string header_extension(kHeaderExtension);
if (headers_use_forward_declarations) {
// #import any headers for "public imports" in the proto file.
for (int i = 0; i < file_->public_dependency_count(); i++) {
import_writer.AddFile(file_->public_dependency(i), header_extension);
}
} else {
for (int i = 0; i < file_->dependency_count(); i++) {
import_writer.AddFile(file_->dependency(i), header_extension);
}
}
import_writer.Emit(printer);
}
ImportWriter import_writer(
generation_options_.generate_for_named_framework,
generation_options_.named_framework_to_proto_path_mappings_path,
generation_options_.runtime_import_prefix,
/* for_bundled_proto = */ is_bundled_proto_);
const std::string header_extension(kHeaderExtension);
// Note:
// deprecated-declarations suppression is only needed if some place in this
// proto file is something deprecated or if it references something from
// another file that is deprecated.
// clang-format off
printer->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
"#pragma clang diagnostic push\n"
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
"\n"
"CF_EXTERN_C_BEGIN\n"
"\n");
// clang-format on
absl::btree_set<std::string> fwd_decls;
for (const auto& generator : message_generators_) {
generator->DetermineForwardDeclarations(
&fwd_decls,
/* include_external_types = */ headers_use_forward_declarations);
}
for (const auto& fwd_decl : fwd_decls) {
printer->Print("$value$;\n", "value", fwd_decl);
}
if (fwd_decls.begin() != fwd_decls.end()) {
printer->Print("\n");
}
printer->Print(
"NS_ASSUME_NONNULL_BEGIN\n"
"\n");
// need to write out all enums first
for (const auto& generator : enum_generators_) {
generator->GenerateHeader(printer);
// Generated files bundled with the library get minimal imports, everything
// else gets the wrapper so everything is usable.
if (is_bundled_proto_) {
import_writer.AddRuntimeImport("GPBDescriptor.h");
import_writer.AddRuntimeImport("GPBMessage.h");
import_writer.AddRuntimeImport("GPBRootObject.h");
} else {
import_writer.AddRuntimeImport("GPBProtocolBuffers.h");
}
// For extensions to chain together, the Root gets created even if there
// are no extensions.
printer->Print(
// clang-format off
"#pragma mark - $root_class_name$\n"
"\n"
"/**\n"
" * Exposes the extension registry for this file.\n"
" *\n"
" * The base class provides:\n"
" * @code\n"
" * + (GPBExtensionRegistry *)extensionRegistry;\n"
" * @endcode\n"
" * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
" * this file and all files that it depends on.\n"
" **/\n"
"GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
"@end\n"
"\n",
// clang-format off
"root_class_name", root_class_name_);
// The dynamic methods block is only needed if there are extensions that are
// file level scoped (not message scoped). The first file_->extension_count()
// of extension_generators_ are the file scoped ones.
if (file_->extension_count()) {
printer->Print(
"@interface $root_class_name$ (DynamicMethods)\n",
"root_class_name", root_class_name_);
for (int i = 0; i < file_->extension_count(); i++) {
extension_generators_[i]->GenerateMembersHeader(printer);
if (headers_use_forward_declarations) {
// #import any headers for "public imports" in the proto file.
for (int i = 0; i < file_->public_dependency_count(); i++) {
import_writer.AddFile(file_->public_dependency(i), header_extension);
}
} else {
for (int i = 0; i < file_->dependency_count(); i++) {
import_writer.AddFile(file_->dependency(i), header_extension);
}
printer->Print("@end\n\n");
} // file_->extension_count()
for (const auto& generator : message_generators_) {
generator->GenerateMessageHeader(printer);
}
// clang-format off
printer->Print(
"NS_ASSUME_NONNULL_END\n"
"\n"
"CF_EXTERN_C_END\n"
"\n"
"#pragma clang diagnostic pop\n"
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n"
"// clange-format on\n");
// clang-format on
printer->Emit(
{
// Avoid the directive within the string below being seen by the
// tool.
{"clangfmt", "clang-format"},
{"filename", file_->name()},
// For extensions to chain together, the Root gets created even if
// there are no extensions.
{"root_class_name", root_class_name_},
{"runtime_imports",
[&] {
import_writer.EmitRuntimeImports(
printer, /* default_cpp_symbol = */ !is_bundled_proto_);
}},
// Add some verification that the generated code matches the source
// the code is being compiled with.
//
// NOTE: Where used, this captures the raw numeric values at the
// time the generator was compiled, since that will be the versions
// for the ObjC runtime at that time. The constants in the
// generated code will then get their values at at compile time (so
// checking against the headers being used to compile).
{"google_protobuf_objc_version", GOOGLE_PROTOBUF_OBJC_VERSION},
{"file_imports", [&] { import_writer.EmitFileImports(printer); }},
{"fwd_decls",
[&] {
absl::btree_set<std::string> fwd_decls;
for (const auto& generator : message_generators_) {
generator->DetermineForwardDeclarations(
&fwd_decls,
/* include_external_types = */
headers_use_forward_declarations);
}
if (!fwd_decls.empty()) {
printer->Emit({{"decls", absl::StrJoin(fwd_decls, "\n")}},
R"objc(
$decls$
)objc");
}
}},
{"enums",
[&] {
for (const auto& generator : enum_generators_) {
generator->GenerateHeader(printer);
}
}},
{"root_extensions",
[&] {
// The dynamic methods block is only needed if there are
// extensions that are file level scoped (not message scoped).
// The first file_->extension_count() of extension_generators_
// are the file scoped ones.
if (file_->extension_count()) {
printer->Emit(
{
{"extension_methods",
[&] {
for (int i = 0; i < file_->extension_count(); i++) {
extension_generators_[i]->GenerateMembersHeader(
printer);
}
}},
},
R"objc(
@interface $root_class_name$ (DynamicMethods)
$extension_methods$;
@end
)objc");
} // file_->extension_count()
}},
{"messages",
[&] {
for (const auto& generator : message_generators_) {
generator->GenerateMessageHeader(printer);
}
}},
},
R"objc(
// Generated by the protocol buffer compiler. DO NOT EDIT!
// $clangfmt$ off
// source: $filename$
$runtime_imports$
#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
$file_imports$
// @@protoc_insertion_point(imports)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
CF_EXTERN_C_BEGIN
$fwd_decls$;
NS_ASSUME_NONNULL_BEGIN
$enums$;
#pragma mark - $root_class_name$
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
GPB_FINAL @interface $root_class_name$ : GPBRootObject
@end
$root_extensions$;
$messages$;
NS_ASSUME_NONNULL_END
CF_EXTERN_C_END
#pragma clang diagnostic pop
// @@protoc_insertion_point(global_scope)
// $clangfmt$ on
)objc");
}
void FileGenerator::GenerateSource(io::Printer* printer) const {
@ -455,7 +473,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) const {
}
}
import_writer.Emit(printer);
import_writer.EmitFileImports(printer);
}
bool includes_oneof = false;
@ -712,7 +730,8 @@ void FileGenerator::PrintFileRuntimePreamble(
} else {
ImportWriter::EmitRuntimeImports(printer, headers_to_import,
generation_options_.runtime_import_prefix,
true);
/* is_bundled_proto = */ false,
/* default_cpp_symbol = */ true);
}
printer->Print("\n");

@ -118,12 +118,12 @@ bool ProtoFrameworkCollector::ConsumeLine(absl::string_view line,
ImportWriter::ImportWriter(
const std::string& generate_for_named_framework,
const std::string& named_framework_to_proto_path_mappings_path,
const std::string& runtime_import_prefix, bool include_wkt_imports)
const std::string& runtime_import_prefix, bool for_bundled_proto)
: generate_for_named_framework_(generate_for_named_framework),
named_framework_to_proto_path_mappings_path_(
named_framework_to_proto_path_mappings_path),
runtime_import_prefix_(runtime_import_prefix),
include_wkt_imports_(include_wkt_imports),
for_bundled_proto_(for_bundled_proto),
need_to_parse_mapping_file_(true) {}
void ImportWriter::AddFile(const FileDescriptor* file,
@ -132,7 +132,7 @@ void ImportWriter::AddFile(const FileDescriptor* file,
// The imports of the WKTs are only needed within the library itself,
// in other cases, they get skipped because the generated code already
// import GPBProtocolBuffers.h and hence proves them.
if (include_wkt_imports_) {
if (for_bundled_proto_) {
const std::string header_name =
"GPB" + FilePathBasename(file) + header_extension;
protobuf_imports_.push_back(header_name);
@ -162,15 +162,13 @@ void ImportWriter::AddFile(const FileDescriptor* file,
other_imports_.push_back(FilePath(file) + header_extension);
}
void ImportWriter::Emit(io::Printer* p) const {
void ImportWriter::AddRuntimeImport(const std::string& header_name) {
protobuf_imports_.push_back(header_name);
}
void ImportWriter::EmitFileImports(io::Printer* p) const {
p->Emit(
{
{"runtime_import",
[&] {
if (!protobuf_imports_.empty()) {
EmitRuntimeImports(p, protobuf_imports_, runtime_import_prefix_);
}
}},
{"other_framework_imports",
[&] {
for (const auto& header : other_framework_imports_) {
@ -191,15 +189,21 @@ void ImportWriter::Emit(io::Printer* p) const {
}},
},
R"objc(
$runtime_import$;
$other_framework_imports$;
$other_imports$;
)objc");
}
void ImportWriter::EmitRuntimeImports(io::Printer* p,
bool default_cpp_symbol) const {
EmitRuntimeImports(p, protobuf_imports_, runtime_import_prefix_,
for_bundled_proto_, default_cpp_symbol);
}
void ImportWriter::EmitRuntimeImports(
io::Printer* p, const std::vector<std::string>& header_to_import,
const std::string& runtime_import_prefix, bool default_cpp_symbol) {
io::Printer* p, const std::vector<std::string>& headers_to_import,
const std::string& runtime_import_prefix, bool is_bundled_proto,
bool default_cpp_symbol) {
// Given an override, use that.
if (!runtime_import_prefix.empty()) {
p->Emit(
@ -207,7 +211,7 @@ void ImportWriter::EmitRuntimeImports(
{"import_prefix", runtime_import_prefix},
{"imports",
[&] {
for (const auto& header : header_to_import) {
for (const auto& header : headers_to_import) {
p->Emit({{"header", header}},
R"objc(
#import "$import_prefix$/$header$"
@ -222,6 +226,27 @@ void ImportWriter::EmitRuntimeImports(
return;
}
// If bundled, no need to do the framework support below.
if (is_bundled_proto) {
GOOGLE_CHECK(!default_cpp_symbol);
p->Emit(
{
{"imports",
[&] {
for (const auto& header : headers_to_import) {
p->Emit({{"header", header}},
R"objc(
#import "$header$"
)objc");
}
}},
},
R"objc(
$imports$;
)objc");
return;
}
auto v = p->WithVars({
{"cpp_symbol",
ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)},
@ -244,7 +269,7 @@ void ImportWriter::EmitRuntimeImports(
{"framework_name", ProtobufLibraryFrameworkName},
{"framework_imports",
[&] {
for (const auto& header : header_to_import) {
for (const auto& header : headers_to_import) {
p->Emit({{"header", header}},
R"objc(
#import <$framework_name$/$header$>
@ -253,7 +278,7 @@ void ImportWriter::EmitRuntimeImports(
}},
{"raw_imports",
[&] {
for (const auto& header : header_to_import) {
for (const auto& header : headers_to_import) {
p->Emit({{"header", header}},
R"objc(
#import "$header$"

@ -50,15 +50,18 @@ class ImportWriter {
ImportWriter(const std::string& generate_for_named_framework,
const std::string& named_framework_to_proto_path_mappings_path,
const std::string& runtime_import_prefix,
bool include_wkt_imports);
bool for_bundled_proto);
~ImportWriter() = default;
void AddFile(const FileDescriptor* file, const std::string& header_extension);
void Emit(io::Printer* p) const;
void AddRuntimeImport(const std::string& header_name);
void EmitFileImports(io::Printer* p) const;
void EmitRuntimeImports(io::Printer* p, bool default_cpp_symbol) const;
static void EmitRuntimeImports(
io::Printer* p, const std::vector<std::string>& header_to_import,
const std::string& runtime_import_prefix,
io::Printer* p, const std::vector<std::string>& headers_to_import,
const std::string& runtime_import_prefix, bool is_bundled_proto = false,
bool default_cpp_symbol = false);
private:
@ -67,8 +70,8 @@ class ImportWriter {
const std::string generate_for_named_framework_;
const std::string named_framework_to_proto_path_mappings_path_;
const std::string runtime_import_prefix_;
const bool include_wkt_imports_;
absl::flat_hash_map<std::string, std::string> proto_file_to_framework_name_;
bool for_bundled_proto_;
bool need_to_parse_mapping_file_;
std::vector<std::string> protobuf_imports_;

@ -187,7 +187,7 @@ void MapFieldGenerator::DetermineForwardDeclarations(
descriptor_->file() == value_msg_descriptor->file()) {
const std::string& value_storage_type =
value_field_generator_->variable("storage_type");
fwd_decls->insert("@class " + value_storage_type);
fwd_decls->insert(absl::StrCat("@class ", value_storage_type, ";"));
}
}

@ -77,7 +77,7 @@ void MessageFieldGenerator::DetermineForwardDeclarations(
descriptor_->message_type()->file())) ||
descriptor_->file() == descriptor_->message_type()->file()) {
// Class name is already in "storage_type".
fwd_decls->insert("@class " + variable("storage_type"));
fwd_decls->insert(absl::StrCat("@class ", variable("storage_type"), ";"));
}
}
@ -107,7 +107,7 @@ void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
descriptor_->message_type()->file())) ||
descriptor_->file() == descriptor_->message_type()->file()) {
// Class name is already in "storage_type".
fwd_decls->insert("@class " + variable("storage_type"));
fwd_decls->insert(absl::StrCat("@class ", variable("storage_type"), ";"));
}
}

Loading…
Cancel
Save