From 70b076907397866a33a5f4d77a360808f8614a35 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Fri, 30 Jun 2023 10:23:09 -0700 Subject: [PATCH] Start conversion to use Printer::Emit() Move ImportWriter over and some of FileGenerator. PiperOrigin-RevId: 544690162 --- .../protobuf/compiler/objectivec/file.cc | 238 +++++++++--------- .../compiler/objectivec/import_writer.cc | 105 +++++--- 2 files changed, 178 insertions(+), 165 deletions(-) diff --git a/src/google/protobuf/compiler/objectivec/file.cc b/src/google/protobuf/compiler/objectivec/file.cc index 385c0ebd86..db5ac18bfa 100644 --- a/src/google/protobuf/compiler/objectivec/file.cc +++ b/src/google/protobuf/compiler/objectivec/file.cc @@ -32,10 +32,8 @@ #include #include -#include #include #include -#include #include #include @@ -50,12 +48,10 @@ #include "google/protobuf/compiler/objectivec/message.h" #include "google/protobuf/compiler/objectivec/names.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor_legacy.h" #include "google/protobuf/io/printer.h" -// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some -// error cases, so it seems to be ok to use as a back door for errors. - namespace google { namespace protobuf { namespace compiler { @@ -130,6 +126,23 @@ void MakeDescriptors( } } +void EmitSourceFwdDecls(const absl::btree_set& fwd_decls, + io::Printer* p) { + if (fwd_decls.empty()) { + return; + } + + p->Emit({{"fwd_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. + $fwd_decls$ + )objc"); + p->Emit("\n"); +} + } // namespace const FileGenerator::CommonState::MinDepsEntry& @@ -354,19 +367,7 @@ void FileGenerator::GenerateSource(io::Printer* p) const { } GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { - 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")); - } - + EmitSourceFwdDecls(fwd_decls, p); PrintRootImplementation(p, deps_with_extensions); PrintFileDescription(p); @@ -404,19 +405,7 @@ void FileGenerator::GenerateGlobalSource(io::Printer* p) const { } GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { - 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")); - } - + EmitSourceFwdDecls(fwd_decls, p); PrintRootImplementation(p, deps_with_extensions); }); } @@ -448,19 +437,7 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) const { } GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { - 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")); - } - + EmitSourceFwdDecls(fwd_decls, p); PrintFileDescription(p); generator->GenerateSource(p); }); @@ -523,69 +500,84 @@ void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type, import_writer.AddFile(dep, header_extension); } - 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_); + // Some things for all Emit() calls to have access too. + auto vars = p->WithVars({ + {// Avoid the directive within the template strings as the tool would + // then honor the directives within the generators sources. + "clangfmt", "clang-format"}, + {"root_class_name", root_class_name_}, + }); - p->Print("\n"); + p->Emit( + { + {"filename", file_->name()}, + {"google_protobuf_objc_version", GOOGLE_PROTOBUF_OBJC_VERSION}, + {"runtime_imports", + [&] { + import_writer.PrintRuntimeImports( + p, /* default_cpp_symbol = */ !is_bundled_proto_); + }}, + {"extra_system_imports", + [&] { + if (file_options.extra_system_headers.empty()) { + return; + } + for (const auto& system_header : + file_options.extra_system_headers) { + p->Emit({{"header", system_header}}, + R"objc( + #import <$header$> + )objc"); + } + p->Emit("\n"); + }}, + {"file_imports", [&] { import_writer.PrintFileImports(p); }}, + {"extra_warnings", + [&] { + for (const auto& warning : file_options.ignored_warnings) { + p->Emit({{"warning", warning}}, + R"objc( + #pragma clang diagnostic ignored "-W$warning$" + )objc"); + } + }}, + }, + 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 + + $extra_system_imports$ + $file_imports$ + // @@protoc_insertion_point(imports) + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + $extra_warnings$ + )objc"); + + p->Emit("\n"); - // 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 - // 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)); - - if (!file_options.extra_system_headers.empty()) { - for (const auto& system_header : file_options.extra_system_headers) { - p->Print("#import <$header$>\n", "header", system_header); - } - p->Print("\n"); - } + body(); - import_writer.PrintFileImports(p); + p->Emit("\n"); - // 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 : file_options.ignored_warnings) { - p->Print("#pragma clang diagnostic ignored \"-W$warning$\"\n", "warning", - warning); - } - p->Print("\n"); + p->Emit(R"objc( + #pragma clang diagnostic pop - body(); + // @@protoc_insertion_point(global_scope) - p->Print( - "\n" - "#pragma clang diagnostic pop\n" - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n" - "// $clangfmt$ on\n", - "clangfmt", "clang-format"); + // $clangfmt$ on + )objc"); } void FileGenerator::PrintRootImplementation( @@ -697,38 +689,36 @@ void FileGenerator::PrintFileDescription(io::Printer* p) const { } const std::string objc_prefix(FileClassPrefix(file_)); - absl::flat_hash_map vars; - vars["file_description_name"] = file_description_name_; - vars["package_value"] = file_->package().empty() - ? "NULL" - : absl::StrCat("\"", file_->package(), "\""); + std::string syntax; switch (FileDescriptorLegacy(file_).syntax()) { case FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN: - vars["syntax"] = "GPBFileSyntaxUnknown"; + syntax = "GPBFileSyntaxUnknown"; break; case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: - vars["syntax"] = "GPBFileSyntaxProto2"; + syntax = "GPBFileSyntaxProto2"; break; case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3: - vars["syntax"] = "GPBFileSyntaxProto3"; + syntax = "GPBFileSyntaxProto3"; break; } - if (objc_prefix.empty() && !file_->options().has_objc_class_prefix()) { - vars["prefix_value"] = "NULL"; - } else { - vars["prefix_value"] = absl::StrCat("\"", objc_prefix, "\""); - } - // clang-format off - p->Print( - vars, - "static GPBFileDescription $file_description_name$ = {\n" - " .package = $package_value$,\n" - " .prefix = $prefix_value$,\n" - " .syntax = $syntax$\n" - "};\n" - "\n"); - // clang-format on + p->Emit({{"file_description_name", file_description_name_}, + {"package_value", file_->package().empty() + ? "NULL" + : absl::StrCat("\"", file_->package(), "\"")}, + {"prefix_value", + objc_prefix.empty() && !file_->options().has_objc_class_prefix() + ? "NULL" + : absl::StrCat("\"", objc_prefix, "\"")}, + {"syntax", syntax}}, + R"objc( + static GPBFileDescription $file_description_name$ = { + .package = $package_value$, + .prefix = $prefix_value$, + .syntax = $syntax$ + }; + )objc"); + p->Emit("\n"); } } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/import_writer.cc b/src/google/protobuf/compiler/objectivec/import_writer.cc index ca0718bed6..2c7d264213 100644 --- a/src/google/protobuf/compiler/objectivec/import_writer.cc +++ b/src/google/protobuf/compiler/objectivec/import_writer.cc @@ -180,20 +180,18 @@ std::string ImportWriter::ModuleForFile(const FileDescriptor* file) { } 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); - } + for (const auto& header : other_framework_imports_) { + p->Emit({{"header", header}}, + R"objc( + #import <$header$> + )objc"); } - 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); - } + for (const auto& header : other_imports_) { + p->Emit({{"header", header}}, + R"objc( + #import "$header$" + )objc"); } } @@ -202,8 +200,10 @@ void ImportWriter::PrintRuntimeImports(io::Printer* p, // Given an override, use that. if (!runtime_import_prefix_.empty()) { for (const auto& header : protobuf_imports_) { - p->Print("#import \"$import_prefix$/$header$\"\n", "header", header, - "import_prefix", runtime_import_prefix_); + p->Emit({{"import_prefix", runtime_import_prefix_}, {"header", header}}, + R"objc( + #import "$import_prefix$/$header$" + )objc"); } return; } @@ -212,37 +212,60 @@ void ImportWriter::PrintRuntimeImports(io::Printer* p, if (for_bundled_proto_) { ABSL_DCHECK(!default_cpp_symbol); for (const auto& header : protobuf_imports_) { - p->Print("#import \"$header$\"\n", "header", header); + p->Emit({{"header", header}}, + R"objc( + #import "$header$" + )objc"); } return; } - const std::string cpp_symbol( - ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)); - - if (default_cpp_symbol) { - 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->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"); + p->Emit( + { + {"cpp_symbol", + ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)}, + {"maybe_default_cpp_symbol", + [&] { + 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"); + } + }}, + {"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( + $maybe_default_cpp_symbol$ + + #if $cpp_symbol$ + $framework_imports$ + #else + $raw_imports$ + #endif + )objc"); } void ImportWriter::ParseFrameworkMappings() {