1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ 9 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ 10 11 #include <cstddef> 12 #include <functional> 13 #include <memory> 14 #include <string> 15 #include <vector> 16 17 #include "absl/container/flat_hash_map.h" 18 #include "absl/container/flat_hash_set.h" 19 #include "google/protobuf/compiler/objectivec/enum.h" 20 #include "google/protobuf/compiler/objectivec/extension.h" 21 #include "google/protobuf/compiler/objectivec/message.h" 22 #include "google/protobuf/compiler/objectivec/options.h" 23 #include "google/protobuf/descriptor.h" 24 #include "google/protobuf/io/printer.h" 25 26 namespace google { 27 namespace protobuf { 28 namespace compiler { 29 namespace objectivec { 30 31 class FileGenerator { 32 public: 33 // Wrapper for some common state that is shared between file generations to 34 // improve performance when more than one file is generated at a time. 35 struct CommonState { 36 // `include_custom_options` will cause any custom options to be included 37 // in the calculations around files defining extensions. CommonStateCommonState38 explicit CommonState(bool include_custom_options) 39 : include_custom_options(include_custom_options) {} 40 41 std::vector<const FileDescriptor*> 42 CollectMinimalFileDepsContainingExtensions(const FileDescriptor* file); 43 44 private: 45 struct MinDepsEntry { 46 bool has_extensions; 47 // The minimal dependencies that cover all the dependencies with 48 // extensions. 49 absl::flat_hash_set<const FileDescriptor*> min_deps; 50 absl::flat_hash_set<const FileDescriptor*> transitive_deps; 51 }; 52 const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal( 53 const FileDescriptor* file); 54 absl::flat_hash_map<const FileDescriptor*, MinDepsEntry> deps_info_cache; 55 const bool include_custom_options; 56 }; 57 58 FileGenerator(Edition edition, const FileDescriptor* file, 59 const GenerationOptions& generation_options, 60 CommonState& common_state); 61 ~FileGenerator() = default; 62 63 FileGenerator(const FileGenerator&) = delete; 64 FileGenerator& operator=(const FileGenerator&) = delete; 65 66 void GenerateHeader(io::Printer* p) const; 67 void GenerateSource(io::Printer* p) const; 68 NumEnums()69 int NumEnums() const { return enum_generators_.size(); } NumMessages()70 int NumMessages() const { return message_generators_.size(); } 71 72 void GenerateGlobalSource(io::Printer* p) const; 73 void GenerateSourceForMessage(int idx, io::Printer* p) const; 74 void GenerateSourceForEnums(io::Printer* p) const; 75 76 private: 77 enum class GeneratedFileType : int { kHeader, kSource }; 78 struct GeneratedFileOptions { 79 std::vector<std::string> ignored_warnings; 80 std::vector<const FileDescriptor*> forced_files_to_import; 81 std::vector<std::string> extra_system_headers; 82 }; 83 84 void GenerateFile(io::Printer* p, GeneratedFileType file_type, 85 const GeneratedFileOptions& file_options, 86 std::function<void()> body) const; GenerateFile(io::Printer * p,GeneratedFileType file_type,std::function<void ()> body)87 void GenerateFile(io::Printer* p, GeneratedFileType file_type, 88 std::function<void()> body) const { 89 GeneratedFileOptions file_options; 90 GenerateFile(p, file_type, file_options, body); 91 } 92 93 void EmitRootImplementation( 94 io::Printer* p, 95 const std::vector<const FileDescriptor*>& deps_with_extensions) const; 96 void EmitRootExtensionRegistryImplementation( 97 io::Printer* p, 98 const std::vector<const FileDescriptor*>& deps_with_extensions) const; 99 void EmitFileDescription(io::Printer* p) const; 100 101 enum class PublicDepsHandling : int { 102 kAsUsed, // No special handing, require references to import then. 103 kForceInclude, // Always treat them as needed. 104 kExclude, // Never treat them as needed. 105 }; 106 // `public_deps_handling` controls how the public imports in this file should 107 // be handed. 108 void DetermineNeededDeps(absl::flat_hash_set<const FileDescriptor*>* deps, 109 PublicDepsHandling public_deps_handling) const; 110 HeadersUseForwardDeclarations()111 bool HeadersUseForwardDeclarations() const { 112 // The bundled protos (WKTs) don't make use of forward declarations. 113 return !is_bundled_proto_ && 114 generation_options_.headers_use_forward_declarations; 115 } 116 117 const Edition edition_; 118 const FileDescriptor* file_; 119 const GenerationOptions& generation_options_; 120 mutable CommonState* common_state_; 121 const std::string root_class_name_; 122 const std::string file_description_name_; 123 const bool is_bundled_proto_; 124 125 std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; 126 std::vector<std::unique_ptr<MessageGenerator>> message_generators_; 127 // The first file_scoped_extension_count_ are the extensions at file level 128 // scope. This can be less than file_->extension_count() when custom options 129 // are being filtered away. 130 size_t file_scoped_extension_count_; 131 std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; 132 }; 133 134 } // namespace objectivec 135 } // namespace compiler 136 } // namespace protobuf 137 } // namespace google 138 139 #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ 140