[ObjC] Go back from Printer::Emit() to Printer::Print()

PiperOrigin-RevId: 492559629
pull/11134/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 605c24e649
commit e535f95976
  1. 619
      src/google/protobuf/compiler/objectivec/file.cc
  2. 6
      src/google/protobuf/compiler/objectivec/file.h
  3. 149
      src/google/protobuf/compiler/objectivec/import_writer.cc
  4. 4
      src/google/protobuf/compiler/objectivec/import_writer.h

@ -44,6 +44,7 @@
#include "absl/container/btree_set.h" #include "absl/container/btree_set.h"
#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h" #include "absl/container/flat_hash_set.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h" #include "absl/strings/str_join.h"
#include "google/protobuf/compiler/objectivec/enum.h" #include "google/protobuf/compiler/objectivec/enum.h"
#include "google/protobuf/compiler/objectivec/extension.h" #include "google/protobuf/compiler/objectivec/extension.h"
@ -240,92 +241,71 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
void FileGenerator::GenerateHeader(io::Printer* p) const { void FileGenerator::GenerateHeader(io::Printer* p) const {
GenerateFile(p, GeneratedFileType::kHeader, [&] { GenerateFile(p, GeneratedFileType::kHeader, [&] {
p->Emit( p->Print("CF_EXTERN_C_BEGIN\n\n");
{
{"fwd_decls", absl::btree_set<std::string> fwd_decls;
[&] { for (const auto& generator : message_generators_) {
absl::btree_set<std::string> fwd_decls; generator->DetermineForwardDeclarations(&fwd_decls,
for (const auto& generator : message_generators_) { /* include_external_types = */
generator->DetermineForwardDeclarations( HeadersUseForwardDeclarations());
&fwd_decls, }
/* include_external_types = */ if (!fwd_decls.empty()) {
HeadersUseForwardDeclarations()); p->Print("$fwd_decls$\n\n", "fwd_decls", absl::StrJoin(fwd_decls, "\n"));
} }
if (!fwd_decls.empty()) { p->Print("NS_ASSUME_NONNULL_BEGIN\n\n");
p->Emit({{"decls", absl::StrJoin(fwd_decls, "\n")}},
R"objc( for (const auto& generator : enum_generators_) {
$decls$ generator->GenerateHeader(p);
}
)objc");
} // For extensions to chain together, the Root gets created even if there
}}, // are no extensions.
{"enums", p->Print(
[&] { // clang-format off
for (const auto& generator : enum_generators_) { "#pragma mark - $root_class_name$\n"
generator->GenerateHeader(p); "\n"
} "/**\n"
}}, " * Exposes the extension registry for this file.\n"
{"root_extensions", " *\n"
[&] { " * The base class provides:\n"
// The dynamic methods block is only needed if there are " * @code\n"
// extensions that are file level scoped (not message scoped). " * + (GPBExtensionRegistry *)extensionRegistry;\n"
// The first file_->extension_count() of extension_generators_ " * @endcode\n"
// are the file scoped ones. " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
if (file_->extension_count()) { " * this file and all files that it depends on.\n"
p->Emit( " **/\n"
{ "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
{"extension_methods", "@end\n"
[&] { "\n",
for (int i = 0; i < file_->extension_count(); i++) { // clang-format on
extension_generators_[i]->GenerateMembersHeader( "root_class_name", root_class_name_);
p);
} // 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
R"objc( // ones.
@interface $root_class_name$ (DynamicMethods) if (file_->extension_count()) {
$extension_methods$; p->Print("@interface $root_class_name$ (DynamicMethods)\n",
@end "root_class_name", root_class_name_);
)objc"); for (int i = 0; i < file_->extension_count(); i++) {
} // file_->extension_count() extension_generators_[i]->GenerateMembersHeader(p);
}}, }
{"messages",
[&] { p->Print("@end\n\n");
for (const auto& generator : message_generators_) { } // file_->extension_count()
generator->GenerateMessageHeader(p);
} for (const auto& generator : message_generators_) {
}}, generator->GenerateMessageHeader(p);
}, }
R"objc(
CF_EXTERN_C_BEGIN // clang-format off
p->Print(
$fwd_decls$; "NS_ASSUME_NONNULL_END\n"
NS_ASSUME_NONNULL_BEGIN "\n"
"CF_EXTERN_C_END\n");
$enums$; // clang-format on
#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
)objc");
}); });
} }
@ -368,44 +348,28 @@ void FileGenerator::GenerateSource(io::Printer* p) const {
GenerateFile( GenerateFile(
p, GeneratedFileType::kSource, ignored_warnings, extra_files, [&] { p, GeneratedFileType::kSource, ignored_warnings, extra_files, [&] {
p->Emit( if (!fwd_decls.empty()) {
{ p->Print(
{"fwd_decls", // clang-format off
[&] { "#pragma mark - Objective C Class declarations\n"
if (fwd_decls.empty()) { "// Forward declarations of Objective C classes that we can use as\n"
return; "// static values in struct initializers.\n"
} "// We don't use [Foo class] because it is not a static value.\n"
p->Emit({{"decls", absl::StrJoin(fwd_decls, "\n")}}, "$fwd_decls$\n"
R"objc( "\n",
#pragma mark - Objective C Class declarations // clang-format on
// Forward declarations of Objective C classes that we can use as "fwd_decls", absl::StrJoin(fwd_decls, "\n"));
// static values in struct initializers. }
// We don't use [Foo class] because it is not a static value.
$decls$ PrintRootImplementation(p, deps_with_extensions);
PrintFileDescriptorImplementation(p);
)objc");
}}, for (const auto& generator : enum_generators_) {
{"root_implementation", generator->GenerateSource(p);
[&] { EmitRootImplementation(p, deps_with_extensions); }}, }
{"file_descriptor_implementation", for (const auto& generator : message_generators_) {
[&] { EmitFileDescriptorImplementation(p); }}, generator->GenerateSource(p);
{"enums_and_messages", }
[&] {
for (const auto& generator : enum_generators_) {
generator->GenerateSource(p);
}
for (const auto& generator : message_generators_) {
generator->GenerateSource(p);
}
}},
},
R"objc(
$fwd_decls$;
$root_implementation$
$file_descriptor_implementation$;
$enums_and_messages$;
)objc");
}); });
} }
@ -468,245 +432,222 @@ void FileGenerator::GenerateFile(
import_writer.AddFile(dep, header_extension); import_writer.AddFile(dep, header_extension);
} }
p->Emit( p->Print(
{ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
// Avoid the directive within the string below being seen by the "// $clangfmt$ off\n"
// tool. "// source: $filename$\n"
{"clangfmt", "clang-format"}, "\n",
{"filename", file_->name()}, "filename", file_->name(), "clangfmt", "clang-format");
{"root_class_name", root_class_name_},
{"source_check", import_writer.PrintRuntimeImports(
[&] { p, /* default_cpp_symbol = */ !is_bundled_proto_);
if (file_type == GeneratedFileType::kHeader) {
// Add some verification that the generated code matches the p->Print("\n");
// source the code is being compiled with.
// if (file_type == GeneratedFileType::kHeader) {
// NOTE: Where used, this captures the raw numeric values at the // Add some verification that the generated code matches the source the
// time the generator was compiled, since that will be the // code is being compiled with.
// versions for the ObjC runtime at that time. The constants in // NOTE: This captures the raw numeric values at the time the generator was
// the generated code will then get their values at at compile // compiled, since that will be the versions for the ObjC runtime at that
// time (so checking against the headers being used to compile). // time. The constants in the generated code will then get their values at
p->Emit({{"google_protobuf_objc_version", // at compile time (so checking against the headers being used to compile).
GOOGLE_PROTOBUF_OBJC_VERSION}}, p->Print(
R"objc( // clang-format off
#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$ "#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. "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
#endif "#endif\n"
#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION "#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. "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
#endif "#endif\n"
"\n",
)objc"); // clang-format on
} "google_protobuf_objc_version",
}}, absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
{"runtime_imports", }
[&] {
import_writer.EmitRuntimeImports( // Enum implementation uses atomic in the generated code, so add
p, /* default_cpp_symbol = */ !is_bundled_proto_); // the system import as needed.
}}, if (file_type == GeneratedFileType::kSource && !enum_generators_.empty()) {
{"file_imports", [&] { import_writer.EmitFileImports(p); }}, p->Print("#import <stdatomic.h>\n\n");
{"extra_imports", }
[&] {
// Enum implementation uses atomic in the generated code, so add import_writer.PrintFileImports(p);
// the system import as needed.
if (file_type == GeneratedFileType::kSource && // clang-format off
!enum_generators_.empty()) { p->Print(
p->Emit("#import <stdatomic.h>\n\n"); "// @@protoc_insertion_point(imports)\n"
} "\n"
}}, "#pragma clang diagnostic push\n"
{"extra_warnings", "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
[&] { // clang-format on
for (const auto& warning : ignored_warnings) { for (const auto& warning : ignored_warnings) {
p->Emit({{"warning", warning}}, p->Print("#pragma clang diagnostic ignored \"-W$warning$\"\n", "warning",
R"objc( warning);
#pragma clang diagnostic ignored "-W$warning$" }
)objc"); p->Print("\n");
}
}}, body();
{"body", body},
}, p->Print(
R"objc( "\n"
// Generated by the protocol buffer compiler. DO NOT EDIT! "#pragma clang diagnostic pop\n"
// $clangfmt$ off "\n"
// source: $filename$ "// @@protoc_insertion_point(global_scope)\n"
"\n"
$runtime_imports$ "// $clangfmt$ on\n",
"clangfmt", "clang-format");
$source_check$;
$extra_imports$;
$file_imports$
// @@protoc_insertion_point(imports)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
$extra_warnings$;
$body$;
#pragma clang diagnostic pop
// @@protoc_insertion_point(global_scope)
// $clangfmt$ on
)objc");
} }
void FileGenerator::EmitRootImplementation( void FileGenerator::PrintRootImplementation(
io::Printer* p, io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const { const std::vector<const FileDescriptor*>& deps_with_extensions) const {
p->Emit( p->Print(
{ // clang-format off
{"root_extension_registry", "#pragma mark - $root_class_name$\n"
[&] { "\n"
// If there were any extensions or this file has any dependencies, "@implementation $root_class_name$\n"
// output a registry to override to create the file specific "\n",
// registry. // clang-format on
if (extension_generators_.empty() && "root_class_name", root_class_name_);
deps_with_extensions.empty()) {
if (file_->dependency_count() == 0) { // If there were any extensions or this file has any dependencies, output a
p->Emit(R"objc( // registry to override to create the file specific registry.
// No extensions in the file and no imports, so no need to generate if (extension_generators_.empty() && deps_with_extensions.empty()) {
// +extensionRegistry. if (file_->dependency_count() == 0) {
)objc"); // clang-format off
} else { p->Print(
p->Emit(R"objc( "// No extensions in the file and no imports, so no need to generate\n"
// No extensions in the file and none of the imports (direct or indirect) "// +extensionRegistry.\n");
// defined extensions, so no need to generate +extensionRegistry. // clang-format on
)objc"); } else {
} // clang-format off
} else { p->Print(
EmitRootExtensionRegistryImplementation(p, deps_with_extensions); "// No extensions in the file and none of the imports (direct or indirect)\n"
} "// defined extensions, so no need to generate +extensionRegistry.\n");
}}, // clang-format on
}, }
R"objc( } else {
#pragma mark - $root_class_name$ PrintRootExtensionRegistryImplementation(p, deps_with_extensions);
}
@implementation $root_class_name$
p->Print("\n@end\n\n");
$root_extension_registry$
@end
)objc");
} }
void FileGenerator::EmitRootExtensionRegistryImplementation( void FileGenerator::PrintRootExtensionRegistryImplementation(
io::Printer* p, io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const { const std::vector<const FileDescriptor*>& deps_with_extensions) const {
p->Emit( // clang-format off
{ p->Print(
{"register_local_extensions", "+ (GPBExtensionRegistry*)extensionRegistry {\n"
[&] { " // This is called by +initialize so there is no need to worry\n"
if (extension_generators_.empty()) { " // about thread safety and initialization of registry.\n"
return; " static GPBExtensionRegistry* registry = nil;\n"
} " if (!registry) {\n"
p->Emit(R"objc( " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
static GPBExtensionDescription descriptions[] = { " registry = [[GPBExtensionRegistry alloc] init];\n");
$register_local_extensions_variable_blocks$ // clang-format on
};
for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) { p->Indent();
GPBExtensionDescriptor *extension = p->Indent();
[[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]
usesClassRefs:YES]; if (!extension_generators_.empty()) {
[registry addExtension:extension]; p->Print("static GPBExtensionDescription descriptions[] = {\n");
[self globallyRegisterExtension:extension]; p->Indent();
[extension release]; for (const auto& generator : extension_generators_) {
} generator->GenerateStaticVariablesInitialization(p);
)objc"); }
}}, p->Outdent();
{"register_local_extensions_variable_blocks", // clang-format off
[&] { p->Print(
for (const auto& generator : extension_generators_) { "};\n"
generator->GenerateStaticVariablesInitialization(p); "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
} " GPBExtensionDescriptor *extension =\n"
}}, " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
{"register_imports", " usesClassRefs:YES];\n"
[&] { " [registry addExtension:extension];\n"
if (deps_with_extensions.empty()) { " [self globallyRegisterExtension:extension];\n"
p->Emit(R"objc( " [extension release];\n"
// None of the imports (direct or indirect) defined extensions, so no need to add "}\n");
// them to this registry. // clang-format on
)objc"); }
} else {
p->Emit(R"objc( if (deps_with_extensions.empty()) {
// Merge in the imports (direct or indirect) that defined extensions. // clang-format off
)objc"); p->Print(
for (const auto& dep : deps_with_extensions) { "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
p->Emit({{"dependency", FileClassName(dep)}}, "// them to this registry.\n");
R"objc( // clang-format on
[registry addExtensions:[$dependency$ extensionRegistry]]; } else {
)objc"); // clang-format off
} p->Print(
} "// Merge in the imports (direct or indirect) that defined extensions.\n");
}}, // clang-format on
}, for (const auto& dep : deps_with_extensions) {
R"objc( const std::string root_class_name(FileClassName((dep)));
+ (GPBExtensionRegistry*)extensionRegistry { p->Print("[registry addExtensions:[$dependency$ extensionRegistry]];\n",
// This is called by +initialize so there is no need to worry "dependency", root_class_name);
// about thread safety and initialization of registry. }
static GPBExtensionRegistry* registry = nil; }
if (!registry) {
GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); p->Outdent();
registry = [[GPBExtensionRegistry alloc] init]; p->Outdent();
$register_local_extensions$;
$register_imports$ // clang-format off
} p->Print(
return registry; " }\n"
} " return registry;\n"
)objc"); "}\n");
// clang-format on
} }
void FileGenerator::EmitFileDescriptorImplementation(io::Printer* p) const { void FileGenerator::PrintFileDescriptorImplementation(io::Printer* p) const {
// File descriptor only needed if there are messages to use it. // File descriptor only needed if there are messages to use it.
if (message_generators_.empty()) { if (message_generators_.empty()) {
return; return;
} }
std::string syntax; const std::string objc_prefix(FileClassPrefix(file_));
absl::flat_hash_map<absl::string_view, std::string> vars;
vars["root_class_name"] = root_class_name_;
vars["package"] = file_->package();
switch (file_->syntax()) { switch (file_->syntax()) {
case FileDescriptor::SYNTAX_UNKNOWN: case FileDescriptor::SYNTAX_UNKNOWN:
syntax = "GPBFileSyntaxUnknown"; vars["syntax"] = "GPBFileSyntaxUnknown";
break; break;
case FileDescriptor::SYNTAX_PROTO2: case FileDescriptor::SYNTAX_PROTO2:
syntax = "GPBFileSyntaxProto2"; vars["syntax"] = "GPBFileSyntaxProto2";
break; break;
case FileDescriptor::SYNTAX_PROTO3: case FileDescriptor::SYNTAX_PROTO3:
syntax = "GPBFileSyntaxProto3"; vars["syntax"] = "GPBFileSyntaxProto3";
break; break;
} }
const std::string objc_prefix(FileClassPrefix(file_)); if (objc_prefix.empty()) {
vars["prefix_arg"] = "";
p->Emit( } else {
{ vars["prefix_arg"] = absl::StrCat(
{"package", file_->package()}, " objcPrefix:@\"",
{"objc_prefix", objc_prefix}, objc_prefix, "\"\n");
{"objc_prefix_arg", }
[&] {
if (!objc_prefix.empty()) {
p->Emit(R"objc(
objcPrefix:@"$objc_prefix$"
)objc");
}
}},
{"syntax", syntax},
},
R"objc(
#pragma mark - $root_class_name$_FileDescriptor
static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {
// This is called by +initialize so there is no need to worry
// about thread safety of the singleton.
static GPBFileDescriptor *descriptor = NULL;
if (!descriptor) {
GPB_DEBUG_CHECK_RUNTIME_VERSIONS();
descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"$package$"
$objc_prefix_arg$;
syntax:$syntax$];
}
return descriptor;
}
)objc"); // clang-format off
p->Print(
vars,
"#pragma mark - $root_class_name$_FileDescriptor\n"
"\n"
"static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
" // This is called by +initialize so there is no need to worry\n"
" // about thread safety of the singleton.\n"
" static GPBFileDescriptor *descriptor = NULL;\n"
" if (!descriptor) {\n"
" GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
" descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
"$prefix_arg$"
" syntax:$syntax$];\n"
" }\n"
" return descriptor;\n"
"}\n"
"\n");
// clang-format on
} }
} // namespace objectivec } // namespace objectivec

@ -95,13 +95,13 @@ class FileGenerator {
GenerateFile(p, file_type, {}, {}, body); GenerateFile(p, file_type, {}, {}, body);
} }
void EmitRootImplementation( void PrintRootImplementation(
io::Printer* p, io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const; const std::vector<const FileDescriptor*>& deps_with_extensions) const;
void EmitRootExtensionRegistryImplementation( void PrintRootExtensionRegistryImplementation(
io::Printer* p, io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const; const std::vector<const FileDescriptor*>& deps_with_extensions) const;
void EmitFileDescriptorImplementation(io::Printer* p) const; void PrintFileDescriptorImplementation(io::Printer* p) const;
bool HeadersUseForwardDeclarations() const { bool HeadersUseForwardDeclarations() const {
// The bundled protos (WKTs) don't make use of forward declarations. // The bundled protos (WKTs) don't make use of forward declarations.

@ -166,125 +166,70 @@ void ImportWriter::AddRuntimeImport(const std::string& header_name) {
protobuf_imports_.push_back(header_name); protobuf_imports_.push_back(header_name);
} }
void ImportWriter::EmitFileImports(io::Printer* p) const { void ImportWriter::PrintFileImports(io::Printer* p) const {
p->Emit( if (!other_framework_imports_.empty()) {
{ for (const auto& header : other_framework_imports_) {
{"other_framework_imports", p->Print("#import <$header$>\n", "header", header);
[&] { }
for (const auto& header : other_framework_imports_) { }
p->Emit({{"header", header}},
R"objc( if (!other_imports_.empty()) {
#import <$header$> if (!other_framework_imports_.empty()) {
)objc"); p->Print("\n");
} }
}},
{"other_imports", for (const auto& header : other_imports_) {
[&] { p->Print("#import \"$header$\"\n", "header", header);
for (const auto& header : other_imports_) { }
p->Emit({{"header", header}}, }
R"objc(
#import "$header$"
)objc");
}
}},
},
R"objc(
$other_framework_imports$;
$other_imports$;
)objc");
} }
void ImportWriter::EmitRuntimeImports(io::Printer* p, void ImportWriter::PrintRuntimeImports(io::Printer* p,
bool default_cpp_symbol) const { bool default_cpp_symbol) const {
// Given an override, use that. // Given an override, use that.
if (!runtime_import_prefix_.empty()) { if (!runtime_import_prefix_.empty()) {
p->Emit( for (const auto& header : protobuf_imports_) {
{ p->Print("#import \"$import_prefix$/$header$\"\n", "header", header,
{"import_prefix", runtime_import_prefix_}, "import_prefix", runtime_import_prefix_);
{"imports", }
[&] {
for (const auto& header : protobuf_imports_) {
p->Emit({{"header", header}},
R"objc(
#import "$import_prefix$/$header$"
)objc");
}
}},
},
R"objc(
$imports$
)objc");
return; return;
} }
// If bundled, no need to do the framework support below. // If bundled, no need to do the framework support below.
if (for_bundled_proto_) { if (for_bundled_proto_) {
GOOGLE_DCHECK(!default_cpp_symbol); GOOGLE_DCHECK(!default_cpp_symbol);
p->Emit( for (const auto& header : protobuf_imports_) {
{ p->Print("#import \"$header$\"\n", "header", header);
{"imports", }
[&] {
for (const auto& header : protobuf_imports_) {
p->Emit({{"header", header}},
R"objc(
#import "$header$"
)objc");
}
}},
},
R"objc(
$imports$
)objc");
return; return;
} }
auto v = p->WithVars({ const std::string cpp_symbol(
{"cpp_symbol", ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName));
ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)},
});
if (default_cpp_symbol) { if (default_cpp_symbol) {
p->Emit( p->Print(
R"objc( // clang-format off
// This CPP symbol can be defined to use imports that match up to the framework "// This CPP symbol can be defined to use imports that match up to the framework\n"
// imports needed when using CocoaPods. "// imports needed when using CocoaPods.\n"
#if !defined($cpp_symbol$) "#if !defined($cpp_symbol$)\n"
#define $cpp_symbol$ 0 " #define $cpp_symbol$ 0\n"
#endif "#endif\n"
"\n",
)objc"); // clang-format on
"cpp_symbol", cpp_symbol);
} }
p->Emit( p->Print("#if $cpp_symbol$\n", "cpp_symbol", cpp_symbol);
{ for (const auto& header : protobuf_imports_) {
{"framework_name", ProtobufLibraryFrameworkName}, p->Print(" #import <$framework_name$/$header$>\n", "framework_name",
{"framework_imports", ProtobufLibraryFrameworkName, "header", header);
[&] { }
for (const auto& header : protobuf_imports_) { p->Print("#else\n");
p->Emit({{"header", header}}, for (const auto& header : protobuf_imports_) {
R"objc( p->Print(" #import \"$header$\"\n", "header", header);
#import <$framework_name$/$header$> }
)objc"); p->Print("#endif\n");
}
}},
{"raw_imports",
[&] {
for (const auto& header : protobuf_imports_) {
p->Emit({{"header", header}},
R"objc(
#import "$header$"
)objc");
}
}},
},
R"objc(
#if $cpp_symbol$
$framework_imports$
#else
$raw_imports$
#endif
)objc");
} }
void ImportWriter::ParseFrameworkMappings() { void ImportWriter::ParseFrameworkMappings() {

@ -56,8 +56,8 @@ class ImportWriter {
void AddFile(const FileDescriptor* file, const std::string& header_extension); void AddFile(const FileDescriptor* file, const std::string& header_extension);
void AddRuntimeImport(const std::string& header_name); void AddRuntimeImport(const std::string& header_name);
void EmitFileImports(io::Printer* p) const; void PrintFileImports(io::Printer* p) const;
void EmitRuntimeImports(io::Printer* p, bool default_cpp_symbol) const; void PrintRuntimeImports(io::Printer* p, bool default_cpp_symbol) const;
private: private:
void ParseFrameworkMappings(); void ParseFrameworkMappings();

Loading…
Cancel
Save