[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/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"
@ -240,92 +241,71 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
void FileGenerator::GenerateHeader(io::Printer* p) const {
GenerateFile(p, GeneratedFileType::kHeader, [&] {
p->Emit(
{
{"fwd_decls",
[&] {
absl::btree_set<std::string> fwd_decls;
for (const auto& generator : message_generators_) {
generator->DetermineForwardDeclarations(
&fwd_decls,
/* include_external_types = */
HeadersUseForwardDeclarations());
}
if (!fwd_decls.empty()) {
p->Emit({{"decls", absl::StrJoin(fwd_decls, "\n")}},
R"objc(
$decls$
)objc");
}
}},
{"enums",
[&] {
for (const auto& generator : enum_generators_) {
generator->GenerateHeader(p);
}
}},
{"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()) {
p->Emit(
{
{"extension_methods",
[&] {
for (int i = 0; i < file_->extension_count(); i++) {
extension_generators_[i]->GenerateMembersHeader(
p);
}
}},
},
R"objc(
@interface $root_class_name$ (DynamicMethods)
$extension_methods$;
@end
)objc");
} // file_->extension_count()
}},
{"messages",
[&] {
for (const auto& generator : message_generators_) {
generator->GenerateMessageHeader(p);
}
}},
},
R"objc(
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
)objc");
p->Print("CF_EXTERN_C_BEGIN\n\n");
absl::btree_set<std::string> fwd_decls;
for (const auto& generator : message_generators_) {
generator->DetermineForwardDeclarations(&fwd_decls,
/* include_external_types = */
HeadersUseForwardDeclarations());
}
if (!fwd_decls.empty()) {
p->Print("$fwd_decls$\n\n", "fwd_decls", absl::StrJoin(fwd_decls, "\n"));
}
p->Print("NS_ASSUME_NONNULL_BEGIN\n\n");
for (const auto& generator : enum_generators_) {
generator->GenerateHeader(p);
}
// For extensions to chain together, the Root gets created even if there
// are no extensions.
p->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 on
"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()) {
p->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(p);
}
p->Print("@end\n\n");
} // file_->extension_count()
for (const auto& generator : message_generators_) {
generator->GenerateMessageHeader(p);
}
// clang-format off
p->Print(
"NS_ASSUME_NONNULL_END\n"
"\n"
"CF_EXTERN_C_END\n");
// clang-format on
});
}
@ -368,44 +348,28 @@ void FileGenerator::GenerateSource(io::Printer* p) const {
GenerateFile(
p, GeneratedFileType::kSource, ignored_warnings, extra_files, [&] {
p->Emit(
{
{"fwd_decls",
[&] {
if (fwd_decls.empty()) {
return;
}
p->Emit({{"decls", absl::StrJoin(fwd_decls, "\n")}},
R"objc(
#pragma mark - Objective C Class declarations
// Forward declarations of Objective C classes that we can use as
// static values in struct initializers.
// We don't use [Foo class] because it is not a static value.
$decls$
)objc");
}},
{"root_implementation",
[&] { EmitRootImplementation(p, deps_with_extensions); }},
{"file_descriptor_implementation",
[&] { EmitFileDescriptorImplementation(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");
if (!fwd_decls.empty()) {
p->Print(
// clang-format off
"#pragma mark - Objective C Class declarations\n"
"// Forward declarations of Objective C classes that we can use as\n"
"// static values in struct initializers.\n"
"// We don't use [Foo class] because it is not a static value.\n"
"$fwd_decls$\n"
"\n",
// clang-format on
"fwd_decls", absl::StrJoin(fwd_decls, "\n"));
}
PrintRootImplementation(p, deps_with_extensions);
PrintFileDescriptorImplementation(p);
for (const auto& generator : enum_generators_) {
generator->GenerateSource(p);
}
for (const auto& generator : message_generators_) {
generator->GenerateSource(p);
}
});
}
@ -468,245 +432,222 @@ void FileGenerator::GenerateFile(
import_writer.AddFile(dep, header_extension);
}
p->Emit(
{
// Avoid the directive within the string below being seen by the
// tool.
{"clangfmt", "clang-format"},
{"filename", file_->name()},
{"root_class_name", root_class_name_},
{"source_check",
[&] {
if (file_type == GeneratedFileType::kHeader) {
// 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).
p->Emit({{"google_protobuf_objc_version",
GOOGLE_PROTOBUF_OBJC_VERSION}},
R"objc(
#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
)objc");
}
}},
{"runtime_imports",
[&] {
import_writer.EmitRuntimeImports(
p, /* default_cpp_symbol = */ !is_bundled_proto_);
}},
{"file_imports", [&] { import_writer.EmitFileImports(p); }},
{"extra_imports",
[&] {
// Enum implementation uses atomic in the generated code, so add
// the system import as needed.
if (file_type == GeneratedFileType::kSource &&
!enum_generators_.empty()) {
p->Emit("#import <stdatomic.h>\n\n");
}
}},
{"extra_warnings",
[&] {
for (const auto& warning : ignored_warnings) {
p->Emit({{"warning", warning}},
R"objc(
#pragma clang diagnostic ignored "-W$warning$"
)objc");
}
}},
{"body", body},
},
R"objc(
// Generated by the protocol buffer compiler. DO NOT EDIT!
// $clangfmt$ off
// source: $filename$
$runtime_imports$
$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");
p->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// $clangfmt$ off\n"
"// source: $filename$\n"
"\n",
"filename", file_->name(), "clangfmt", "clang-format");
import_writer.PrintRuntimeImports(
p, /* default_cpp_symbol = */ !is_bundled_proto_);
p->Print("\n");
if (file_type == GeneratedFileType::kHeader) {
// 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).
p->Print(
// clang-format off
"#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",
// clang-format on
"google_protobuf_objc_version",
absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
}
// Enum implementation uses atomic in the generated code, so add
// the system import as needed.
if (file_type == GeneratedFileType::kSource && !enum_generators_.empty()) {
p->Print("#import <stdatomic.h>\n\n");
}
import_writer.PrintFileImports(p);
// clang-format off
p->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
"#pragma clang diagnostic push\n"
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
// clang-format on
for (const auto& warning : ignored_warnings) {
p->Print("#pragma clang diagnostic ignored \"-W$warning$\"\n", "warning",
warning);
}
p->Print("\n");
body();
p->Print(
"\n"
"#pragma clang diagnostic pop\n"
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n"
"// $clangfmt$ on\n",
"clangfmt", "clang-format");
}
void FileGenerator::EmitRootImplementation(
void FileGenerator::PrintRootImplementation(
io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const {
p->Emit(
{
{"root_extension_registry",
[&] {
// If there were any extensions or this file has any dependencies,
// output a registry to override to create the file specific
// registry.
if (extension_generators_.empty() &&
deps_with_extensions.empty()) {
if (file_->dependency_count() == 0) {
p->Emit(R"objc(
// No extensions in the file and no imports, so no need to generate
// +extensionRegistry.
)objc");
} else {
p->Emit(R"objc(
// No extensions in the file and none of the imports (direct or indirect)
// defined extensions, so no need to generate +extensionRegistry.
)objc");
}
} else {
EmitRootExtensionRegistryImplementation(p, deps_with_extensions);
}
}},
},
R"objc(
#pragma mark - $root_class_name$
@implementation $root_class_name$
$root_extension_registry$
@end
)objc");
p->Print(
// clang-format off
"#pragma mark - $root_class_name$\n"
"\n"
"@implementation $root_class_name$\n"
"\n",
// clang-format on
"root_class_name", root_class_name_);
// If there were any extensions or this file has any dependencies, output a
// registry to override to create the file specific registry.
if (extension_generators_.empty() && deps_with_extensions.empty()) {
if (file_->dependency_count() == 0) {
// clang-format off
p->Print(
"// No extensions in the file and no imports, so no need to generate\n"
"// +extensionRegistry.\n");
// clang-format on
} else {
// clang-format off
p->Print(
"// 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
}
} else {
PrintRootExtensionRegistryImplementation(p, deps_with_extensions);
}
p->Print("\n@end\n\n");
}
void FileGenerator::EmitRootExtensionRegistryImplementation(
void FileGenerator::PrintRootExtensionRegistryImplementation(
io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const {
p->Emit(
{
{"register_local_extensions",
[&] {
if (extension_generators_.empty()) {
return;
}
p->Emit(R"objc(
static GPBExtensionDescription descriptions[] = {
$register_local_extensions_variable_blocks$
};
for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {
GPBExtensionDescriptor *extension =
[[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]
usesClassRefs:YES];
[registry addExtension:extension];
[self globallyRegisterExtension:extension];
[extension release];
}
)objc");
}},
{"register_local_extensions_variable_blocks",
[&] {
for (const auto& generator : extension_generators_) {
generator->GenerateStaticVariablesInitialization(p);
}
}},
{"register_imports",
[&] {
if (deps_with_extensions.empty()) {
p->Emit(R"objc(
// None of the imports (direct or indirect) defined extensions, so no need to add
// them to this registry.
)objc");
} else {
p->Emit(R"objc(
// Merge in the imports (direct or indirect) that defined extensions.
)objc");
for (const auto& dep : deps_with_extensions) {
p->Emit({{"dependency", FileClassName(dep)}},
R"objc(
[registry addExtensions:[$dependency$ extensionRegistry]];
)objc");
}
}
}},
},
R"objc(
+ (GPBExtensionRegistry*)extensionRegistry {
// This is called by +initialize so there is no need to worry
// about thread safety and initialization of registry.
static GPBExtensionRegistry* registry = nil;
if (!registry) {
GPB_DEBUG_CHECK_RUNTIME_VERSIONS();
registry = [[GPBExtensionRegistry alloc] init];
$register_local_extensions$;
$register_imports$
}
return registry;
}
)objc");
// clang-format off
p->Print(
"+ (GPBExtensionRegistry*)extensionRegistry {\n"
" // This is called by +initialize so there is no need to worry\n"
" // about thread safety and initialization of registry.\n"
" static GPBExtensionRegistry* registry = nil;\n"
" if (!registry) {\n"
" GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
" registry = [[GPBExtensionRegistry alloc] init];\n");
// clang-format on
p->Indent();
p->Indent();
if (!extension_generators_.empty()) {
p->Print("static GPBExtensionDescription descriptions[] = {\n");
p->Indent();
for (const auto& generator : extension_generators_) {
generator->GenerateStaticVariablesInitialization(p);
}
p->Outdent();
// clang-format off
p->Print(
"};\n"
"for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
" GPBExtensionDescriptor *extension =\n"
" [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
" usesClassRefs:YES];\n"
" [registry addExtension:extension];\n"
" [self globallyRegisterExtension:extension];\n"
" [extension release];\n"
"}\n");
// clang-format on
}
if (deps_with_extensions.empty()) {
// clang-format off
p->Print(
"// None of the imports (direct or indirect) defined extensions, so no need to add\n"
"// them to this registry.\n");
// clang-format on
} else {
// 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) {
const std::string root_class_name(FileClassName((dep)));
p->Print("[registry addExtensions:[$dependency$ extensionRegistry]];\n",
"dependency", root_class_name);
}
}
p->Outdent();
p->Outdent();
// clang-format off
p->Print(
" }\n"
" return registry;\n"
"}\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.
if (message_generators_.empty()) {
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()) {
case FileDescriptor::SYNTAX_UNKNOWN:
syntax = "GPBFileSyntaxUnknown";
vars["syntax"] = "GPBFileSyntaxUnknown";
break;
case FileDescriptor::SYNTAX_PROTO2:
syntax = "GPBFileSyntaxProto2";
vars["syntax"] = "GPBFileSyntaxProto2";
break;
case FileDescriptor::SYNTAX_PROTO3:
syntax = "GPBFileSyntaxProto3";
vars["syntax"] = "GPBFileSyntaxProto3";
break;
}
const std::string objc_prefix(FileClassPrefix(file_));
p->Emit(
{
{"package", file_->package()},
{"objc_prefix", objc_prefix},
{"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;
}
if (objc_prefix.empty()) {
vars["prefix_arg"] = "";
} else {
vars["prefix_arg"] = absl::StrCat(
" objcPrefix:@\"",
objc_prefix, "\"\n");
}
)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

@ -95,13 +95,13 @@ class FileGenerator {
GenerateFile(p, file_type, {}, {}, body);
}
void EmitRootImplementation(
void PrintRootImplementation(
io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const;
void EmitRootExtensionRegistryImplementation(
void PrintRootExtensionRegistryImplementation(
io::Printer* p,
const std::vector<const FileDescriptor*>& deps_with_extensions) const;
void EmitFileDescriptorImplementation(io::Printer* p) const;
void PrintFileDescriptorImplementation(io::Printer* p) const;
bool HeadersUseForwardDeclarations() const {
// 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);
}
void ImportWriter::EmitFileImports(io::Printer* p) const {
p->Emit(
{
{"other_framework_imports",
[&] {
for (const auto& header : other_framework_imports_) {
p->Emit({{"header", header}},
R"objc(
#import <$header$>
)objc");
}
}},
{"other_imports",
[&] {
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::PrintFileImports(io::Printer* p) const {
if (!other_framework_imports_.empty()) {
for (const auto& header : other_framework_imports_) {
p->Print("#import <$header$>\n", "header", header);
}
}
if (!other_imports_.empty()) {
if (!other_framework_imports_.empty()) {
p->Print("\n");
}
for (const auto& header : other_imports_) {
p->Print("#import \"$header$\"\n", "header", header);
}
}
}
void ImportWriter::EmitRuntimeImports(io::Printer* p,
bool default_cpp_symbol) const {
void ImportWriter::PrintRuntimeImports(io::Printer* p,
bool default_cpp_symbol) const {
// Given an override, use that.
if (!runtime_import_prefix_.empty()) {
p->Emit(
{
{"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");
for (const auto& header : protobuf_imports_) {
p->Print("#import \"$import_prefix$/$header$\"\n", "header", header,
"import_prefix", runtime_import_prefix_);
}
return;
}
// If bundled, no need to do the framework support below.
if (for_bundled_proto_) {
GOOGLE_DCHECK(!default_cpp_symbol);
p->Emit(
{
{"imports",
[&] {
for (const auto& header : protobuf_imports_) {
p->Emit({{"header", header}},
R"objc(
#import "$header$"
)objc");
}
}},
},
R"objc(
$imports$
)objc");
for (const auto& header : protobuf_imports_) {
p->Print("#import \"$header$\"\n", "header", header);
}
return;
}
auto v = p->WithVars({
{"cpp_symbol",
ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)},
});
const std::string cpp_symbol(
ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName));
if (default_cpp_symbol) {
p->Emit(
R"objc(
// This CPP symbol can be defined to use imports that match up to the framework
// imports needed when using CocoaPods.
#if !defined($cpp_symbol$)
#define $cpp_symbol$ 0
#endif
)objc");
p->Print(
// clang-format off
"// This CPP symbol can be defined to use imports that match up to the framework\n"
"// imports needed when using CocoaPods.\n"
"#if !defined($cpp_symbol$)\n"
" #define $cpp_symbol$ 0\n"
"#endif\n"
"\n",
// clang-format on
"cpp_symbol", cpp_symbol);
}
p->Emit(
{
{"framework_name", ProtobufLibraryFrameworkName},
{"framework_imports",
[&] {
for (const auto& header : protobuf_imports_) {
p->Emit({{"header", header}},
R"objc(
#import <$framework_name$/$header$>
)objc");
}
}},
{"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");
p->Print("#if $cpp_symbol$\n", "cpp_symbol", cpp_symbol);
for (const auto& header : protobuf_imports_) {
p->Print(" #import <$framework_name$/$header$>\n", "framework_name",
ProtobufLibraryFrameworkName, "header", header);
}
p->Print("#else\n");
for (const auto& header : protobuf_imports_) {
p->Print(" #import \"$header$\"\n", "header", header);
}
p->Print("#endif\n");
}
void ImportWriter::ParseFrameworkMappings() {

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

Loading…
Cancel
Save