1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // Generates JavaScript code for a given .proto file. 32 // 33 #ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ 34 #define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ 35 36 #include <set> 37 #include <string> 38 39 #include <google/protobuf/stubs/logging.h> 40 #include <google/protobuf/stubs/common.h> 41 #include <google/protobuf/compiler/scc.h> 42 #include <google/protobuf/compiler/code_generator.h> 43 44 #include <google/protobuf/port_def.inc> 45 46 namespace google { 47 namespace protobuf { 48 49 class Descriptor; 50 class EnumDescriptor; 51 class FieldDescriptor; 52 class OneofDescriptor; 53 class FileDescriptor; 54 55 namespace io { 56 class Printer; 57 } 58 59 namespace compiler { 60 namespace js { 61 62 struct GeneratorOptions { 63 // Output path. 64 std::string output_dir; 65 // Namespace prefix. 66 std::string namespace_prefix; 67 // Enable binary-format support? 68 bool binary; 69 // What style of imports should be used. 70 enum ImportStyle { 71 kImportClosure, // goog.require() 72 kImportCommonJs, // require() 73 kImportCommonJsStrict, // require() with no global export 74 kImportBrowser, // no import statements 75 kImportEs6, // import { member } from '' 76 } import_style; 77 GeneratorOptionsGeneratorOptions78 GeneratorOptions() 79 : output_dir("."), 80 namespace_prefix(""), 81 binary(false), 82 import_style(kImportClosure), 83 add_require_for_enums(false), 84 testonly(false), 85 library(""), 86 error_on_name_conflict(false), 87 extension(".js"), 88 one_output_file_per_input_file(false), 89 annotate_code(false) {} 90 91 bool ParseFromOptions( 92 const std::vector<std::pair<std::string, std::string> >& options, 93 std::string* error); 94 95 // Returns the file name extension to use for generated code. GetFileNameExtensionGeneratorOptions96 std::string GetFileNameExtension() const { 97 return import_style == kImportClosure ? extension : "_pb.js"; 98 } 99 100 enum OutputMode { 101 // Create an output file for each input .proto file. 102 kOneOutputFilePerInputFile, 103 // Create an output file for each type. 104 kOneOutputFilePerSCC, 105 // Put everything in a single file named by the library option. 106 kEverythingInOneFile, 107 }; 108 109 // Indicates how to output the generated code based on the provided options. 110 OutputMode output_mode() const; 111 112 // The remaining options are only relevant when we are using kImportClosure. 113 114 // Add a `goog.requires()` call for each enum type used. If not set, a 115 // forward declaration with `goog.forwardDeclare` is produced instead. 116 bool add_require_for_enums; 117 // Set this as a test-only module via `goog.setTestOnly();`. 118 bool testonly; 119 // Create a library with name <name>_lib.js rather than a separate .js file 120 // per type? 121 std::string library; 122 // Error if there are two types that would generate the same output file? 123 bool error_on_name_conflict; 124 // The extension to use for output file names. 125 std::string extension; 126 // Create a separate output file for each input file? 127 bool one_output_file_per_input_file; 128 // If true, we should append annotations as commen on the last line for 129 // generated .js file. Annotations used by tools like https://kythe.io 130 // to provide cross-references between .js and .proto files. Annotations 131 // are enced as base64 proto of GeneratedCodeInfo message (see 132 // descriptor.proto). 133 bool annotate_code; 134 }; 135 136 // CodeGenerator implementation which generates a JavaScript source file and 137 // header. If you create your own protocol compiler binary and you want it to 138 // support JavaScript output, you can do so by registering an instance of this 139 // CodeGenerator with the CommandLineInterface in your main() function. 140 class PROTOC_EXPORT Generator : public CodeGenerator { 141 public: Generator()142 Generator() {} ~Generator()143 virtual ~Generator() {} 144 Generate(const FileDescriptor * file,const std::string & parameter,GeneratorContext * context,std::string * error)145 bool Generate(const FileDescriptor* file, const std::string& parameter, 146 GeneratorContext* context, std::string* error) const override { 147 *error = "Unimplemented Generate() method. Call GenerateAll() instead."; 148 return false; 149 } 150 HasGenerateAll()151 bool HasGenerateAll() const override { return true; } 152 153 bool GenerateAll(const std::vector<const FileDescriptor*>& files, 154 const std::string& parameter, GeneratorContext* context, 155 std::string* error) const override; 156 GetSupportedFeatures()157 uint64 GetSupportedFeatures() const override { 158 return FEATURE_PROTO3_OPTIONAL; 159 } 160 161 private: 162 void GenerateHeader(const GeneratorOptions& options, 163 const FileDescriptor* file, io::Printer* printer) const; 164 165 // Generate goog.provides() calls. 166 void FindProvides(const GeneratorOptions& options, io::Printer* printer, 167 const std::vector<const FileDescriptor*>& file, 168 std::set<std::string>* provided) const; 169 void FindProvidesForFile(const GeneratorOptions& options, 170 io::Printer* printer, const FileDescriptor* file, 171 std::set<std::string>* provided) const; 172 void FindProvidesForMessage(const GeneratorOptions& options, 173 io::Printer* printer, const Descriptor* desc, 174 std::set<std::string>* provided) const; 175 void FindProvidesForEnum(const GeneratorOptions& options, 176 io::Printer* printer, const EnumDescriptor* enumdesc, 177 std::set<std::string>* provided) const; 178 // For extension fields at file scope. 179 void FindProvidesForFields(const GeneratorOptions& options, 180 io::Printer* printer, 181 const std::vector<const FieldDescriptor*>& fields, 182 std::set<std::string>* provided) const; 183 // Print the goog.provides() found by the methods above. 184 void GenerateProvides(const GeneratorOptions& options, io::Printer* printer, 185 std::set<std::string>* provided) const; 186 187 // Generate goog.setTestOnly() if indicated. 188 void GenerateTestOnly(const GeneratorOptions& options, 189 io::Printer* printer) const; 190 191 // Generate goog.requires() calls. 192 void GenerateRequiresForLibrary( 193 const GeneratorOptions& options, io::Printer* printer, 194 const std::vector<const FileDescriptor*>& files, 195 std::set<std::string>* provided) const; 196 void GenerateRequiresForSCC(const GeneratorOptions& options, 197 io::Printer* printer, const SCC* scc, 198 std::set<std::string>* provided) const; 199 // For extension fields at file scope. 200 void GenerateRequiresForExtensions( 201 const GeneratorOptions& options, io::Printer* printer, 202 const std::vector<const FieldDescriptor*>& fields, 203 std::set<std::string>* provided) const; 204 void GenerateRequiresImpl(const GeneratorOptions& options, 205 io::Printer* printer, 206 std::set<std::string>* required, 207 std::set<std::string>* forwards, 208 std::set<std::string>* provided, bool require_jspb, 209 bool require_extension, bool require_map) const; 210 void FindRequiresForMessage(const GeneratorOptions& options, 211 const Descriptor* desc, 212 std::set<std::string>* required, 213 std::set<std::string>* forwards, 214 bool* have_message) const; 215 void FindRequiresForField(const GeneratorOptions& options, 216 const FieldDescriptor* field, 217 std::set<std::string>* required, 218 std::set<std::string>* forwards) const; 219 void FindRequiresForExtension(const GeneratorOptions& options, 220 const FieldDescriptor* field, 221 std::set<std::string>* required, 222 std::set<std::string>* forwards) const; 223 // Generate all things in a proto file into one file. 224 // If use_short_name is true, the generated file's name will only be short 225 // name that without directory, otherwise filename equals file->name() 226 bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options, 227 GeneratorContext* context, bool use_short_name) const; 228 void GenerateFile(const GeneratorOptions& options, io::Printer* printer, 229 const FileDescriptor* file) const; 230 231 // Generate definitions for all message classes and enums in all files, 232 // processing the files in dependence order. 233 void GenerateFilesInDepOrder( 234 const GeneratorOptions& options, io::Printer* printer, 235 const std::vector<const FileDescriptor*>& file) const; 236 // Helper for above. 237 void GenerateFileAndDeps(const GeneratorOptions& options, 238 io::Printer* printer, const FileDescriptor* root, 239 std::set<const FileDescriptor*>* all_files, 240 std::set<const FileDescriptor*>* generated) const; 241 242 // Generate definitions for all message classes and enums. 243 void GenerateClassesAndEnums(const GeneratorOptions& options, 244 io::Printer* printer, 245 const FileDescriptor* file) const; 246 247 void GenerateFieldValueExpression(io::Printer* printer, 248 const char* obj_reference, 249 const FieldDescriptor* field, 250 bool use_default) const; 251 252 // Generate definition for one class. 253 void GenerateClass(const GeneratorOptions& options, io::Printer* printer, 254 const Descriptor* desc) const; 255 void GenerateClassConstructor(const GeneratorOptions& options, 256 io::Printer* printer, 257 const Descriptor* desc) const; 258 void GenerateClassFieldInfo(const GeneratorOptions& options, 259 io::Printer* printer, 260 const Descriptor* desc) const; 261 void GenerateClassConstructorAndDeclareExtensionFieldInfo( 262 const GeneratorOptions& options, io::Printer* printer, 263 const Descriptor* desc) const; 264 void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer, 265 const Descriptor* desc) const; 266 void GenerateOneofCaseDefinition(const GeneratorOptions& options, 267 io::Printer* printer, 268 const OneofDescriptor* oneof) const; 269 void GenerateObjectTypedef(const GeneratorOptions& options, 270 io::Printer* printer, 271 const Descriptor* desc) const; 272 void GenerateClassToObject(const GeneratorOptions& options, 273 io::Printer* printer, 274 const Descriptor* desc) const; 275 void GenerateClassFieldToObject(const GeneratorOptions& options, 276 io::Printer* printer, 277 const FieldDescriptor* field) const; 278 void GenerateClassFromObject(const GeneratorOptions& options, 279 io::Printer* printer, 280 const Descriptor* desc) const; 281 void GenerateClassFieldFromObject(const GeneratorOptions& options, 282 io::Printer* printer, 283 const FieldDescriptor* field) const; 284 void GenerateClassRegistration(const GeneratorOptions& options, 285 io::Printer* printer, 286 const Descriptor* desc) const; 287 void GenerateClassFields(const GeneratorOptions& options, 288 io::Printer* printer, const Descriptor* desc) const; 289 void GenerateClassField(const GeneratorOptions& options, io::Printer* printer, 290 const FieldDescriptor* desc) const; 291 void GenerateClassExtensionFieldInfo(const GeneratorOptions& options, 292 io::Printer* printer, 293 const Descriptor* desc) const; 294 void GenerateClassDeserialize(const GeneratorOptions& options, 295 io::Printer* printer, 296 const Descriptor* desc) const; 297 void GenerateClassDeserializeBinary(const GeneratorOptions& options, 298 io::Printer* printer, 299 const Descriptor* desc) const; 300 void GenerateClassDeserializeBinaryField(const GeneratorOptions& options, 301 io::Printer* printer, 302 const FieldDescriptor* field) const; 303 void GenerateClassSerializeBinary(const GeneratorOptions& options, 304 io::Printer* printer, 305 const Descriptor* desc) const; 306 void GenerateClassSerializeBinaryField(const GeneratorOptions& options, 307 io::Printer* printer, 308 const FieldDescriptor* field) const; 309 310 // Generate definition for one enum. 311 void GenerateEnum(const GeneratorOptions& options, io::Printer* printer, 312 const EnumDescriptor* enumdesc) const; 313 314 // Generate an extension definition. 315 void GenerateExtension(const GeneratorOptions& options, io::Printer* printer, 316 const FieldDescriptor* field) const; 317 318 // Generate addFoo() method for repeated primitive fields. 319 void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options, 320 io::Printer* printer, 321 const FieldDescriptor* field, 322 bool untyped) const; 323 324 // Generate addFoo() method for repeated message fields. 325 void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options, 326 io::Printer* printer, 327 const FieldDescriptor* field) const; 328 329 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); 330 }; 331 332 } // namespace js 333 } // namespace compiler 334 } // namespace protobuf 335 } // namespace google 336 337 #include <google/protobuf/port_undef.inc> 338 339 #endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ 340