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 extension(".js"), 87 one_output_file_per_input_file(false), 88 annotate_code(false) {} 89 90 bool ParseFromOptions( 91 const std::vector<std::pair<std::string, std::string> >& options, 92 std::string* error); 93 94 // Returns the file name extension to use for generated code. GetFileNameExtensionGeneratorOptions95 std::string GetFileNameExtension() const { 96 return import_style == kImportClosure ? extension : "_pb.js"; 97 } 98 99 enum OutputMode { 100 // Create an output file for each input .proto file. 101 kOneOutputFilePerInputFile, 102 // Create an output file for each type. 103 kOneOutputFilePerSCC, 104 // Put everything in a single file named by the library option. 105 kEverythingInOneFile, 106 }; 107 108 // Indicates how to output the generated code based on the provided options. 109 OutputMode output_mode() const; 110 111 // The remaining options are only relevant when we are using kImportClosure. 112 113 // Add a `goog.requires()` call for each enum type used. If not set, a 114 // forward declaration with `goog.forwardDeclare` is produced instead. 115 bool add_require_for_enums; 116 // Set this as a test-only module via `goog.setTestOnly();`. 117 bool testonly; 118 // Create a library with name <name>_lib.js rather than a separate .js file 119 // per type? 120 std::string library; 121 // The extension to use for output file names. 122 std::string extension; 123 // Create a separate output file for each input file? 124 bool one_output_file_per_input_file; 125 // If true, we should append annotations as comments on the last line for 126 // generated .js file. Annotations used by tools like https://kythe.io 127 // to provide cross-references between .js and .proto files. Annotations 128 // are encoded as base64 proto of GeneratedCodeInfo message (see 129 // descriptor.proto). 130 bool annotate_code; 131 }; 132 133 // CodeGenerator implementation which generates a JavaScript source file and 134 // header. If you create your own protocol compiler binary and you want it to 135 // support JavaScript output, you can do so by registering an instance of this 136 // CodeGenerator with the CommandLineInterface in your main() function. 137 class PROTOC_EXPORT Generator : public CodeGenerator { 138 public: Generator()139 Generator() {} ~Generator()140 virtual ~Generator() {} 141 Generate(const FileDescriptor * file,const std::string & parameter,GeneratorContext * context,std::string * error)142 bool Generate(const FileDescriptor* file, const std::string& parameter, 143 GeneratorContext* context, std::string* error) const override { 144 *error = "Unimplemented Generate() method. Call GenerateAll() instead."; 145 return false; 146 } 147 HasGenerateAll()148 bool HasGenerateAll() const override { return true; } 149 150 bool GenerateAll(const std::vector<const FileDescriptor*>& files, 151 const std::string& parameter, GeneratorContext* context, 152 std::string* error) const override; 153 GetSupportedFeatures()154 uint64 GetSupportedFeatures() const override { 155 return FEATURE_PROTO3_OPTIONAL; 156 } 157 158 private: 159 void GenerateHeader(const GeneratorOptions& options, 160 const FileDescriptor* file, io::Printer* printer) const; 161 162 // Generate goog.provides() calls. 163 void FindProvides(const GeneratorOptions& options, io::Printer* printer, 164 const std::vector<const FileDescriptor*>& file, 165 std::set<std::string>* provided) const; 166 void FindProvidesForFile(const GeneratorOptions& options, 167 io::Printer* printer, const FileDescriptor* file, 168 std::set<std::string>* provided) const; 169 void FindProvidesForMessage(const GeneratorOptions& options, 170 io::Printer* printer, const Descriptor* desc, 171 std::set<std::string>* provided) const; 172 void FindProvidesForEnum(const GeneratorOptions& options, 173 io::Printer* printer, const EnumDescriptor* enumdesc, 174 std::set<std::string>* provided) const; 175 // For extension fields at file scope. 176 void FindProvidesForFields(const GeneratorOptions& options, 177 io::Printer* printer, 178 const std::vector<const FieldDescriptor*>& fields, 179 std::set<std::string>* provided) const; 180 // Print the goog.provides() found by the methods above. 181 void GenerateProvides(const GeneratorOptions& options, io::Printer* printer, 182 std::set<std::string>* provided) const; 183 184 // Generate goog.setTestOnly() if indicated. 185 void GenerateTestOnly(const GeneratorOptions& options, 186 io::Printer* printer) const; 187 188 // Generate goog.requires() calls. 189 void GenerateRequiresForLibrary( 190 const GeneratorOptions& options, io::Printer* printer, 191 const std::vector<const FileDescriptor*>& files, 192 std::set<std::string>* provided) const; 193 void GenerateRequiresForSCC(const GeneratorOptions& options, 194 io::Printer* printer, const SCC* scc, 195 std::set<std::string>* provided) const; 196 // For extension fields at file scope. 197 void GenerateRequiresForExtensions( 198 const GeneratorOptions& options, io::Printer* printer, 199 const std::vector<const FieldDescriptor*>& fields, 200 std::set<std::string>* provided) const; 201 void GenerateRequiresImpl(const GeneratorOptions& options, 202 io::Printer* printer, 203 std::set<std::string>* required, 204 std::set<std::string>* forwards, 205 std::set<std::string>* provided, bool require_jspb, 206 bool require_extension, bool require_map) const; 207 void FindRequiresForMessage(const GeneratorOptions& options, 208 const Descriptor* desc, 209 std::set<std::string>* required, 210 std::set<std::string>* forwards, 211 bool* have_message) const; 212 void FindRequiresForField(const GeneratorOptions& options, 213 const FieldDescriptor* field, 214 std::set<std::string>* required, 215 std::set<std::string>* forwards) const; 216 void FindRequiresForExtension(const GeneratorOptions& options, 217 const FieldDescriptor* field, 218 std::set<std::string>* required, 219 std::set<std::string>* forwards) const; 220 // Generate all things in a proto file into one file. 221 // If use_short_name is true, the generated file's name will only be short 222 // name that without directory, otherwise filename equals file->name() 223 bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options, 224 GeneratorContext* context, bool use_short_name) const; 225 void GenerateFile(const GeneratorOptions& options, io::Printer* printer, 226 const FileDescriptor* file) const; 227 228 // Generate definitions for all message classes and enums in all files, 229 // processing the files in dependence order. 230 void GenerateFilesInDepOrder( 231 const GeneratorOptions& options, io::Printer* printer, 232 const std::vector<const FileDescriptor*>& file) const; 233 // Helper for above. 234 void GenerateFileAndDeps(const GeneratorOptions& options, 235 io::Printer* printer, const FileDescriptor* root, 236 std::set<const FileDescriptor*>* all_files, 237 std::set<const FileDescriptor*>* generated) const; 238 239 // Generate definitions for all message classes and enums. 240 void GenerateClassesAndEnums(const GeneratorOptions& options, 241 io::Printer* printer, 242 const FileDescriptor* file) const; 243 244 void GenerateFieldValueExpression(io::Printer* printer, 245 const char* obj_reference, 246 const FieldDescriptor* field, 247 bool use_default) const; 248 249 // Generate definition for one class. 250 void GenerateClass(const GeneratorOptions& options, io::Printer* printer, 251 const Descriptor* desc) const; 252 void GenerateClassConstructor(const GeneratorOptions& options, 253 io::Printer* printer, 254 const Descriptor* desc) const; 255 void GenerateClassFieldInfo(const GeneratorOptions& options, 256 io::Printer* printer, 257 const Descriptor* desc) const; 258 void GenerateClassConstructorAndDeclareExtensionFieldInfo( 259 const GeneratorOptions& options, io::Printer* printer, 260 const Descriptor* desc) const; 261 void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer, 262 const Descriptor* desc) const; 263 void GenerateOneofCaseDefinition(const GeneratorOptions& options, 264 io::Printer* printer, 265 const OneofDescriptor* oneof) const; 266 void GenerateObjectTypedef(const GeneratorOptions& options, 267 io::Printer* printer, 268 const Descriptor* desc) const; 269 void GenerateClassToObject(const GeneratorOptions& options, 270 io::Printer* printer, 271 const Descriptor* desc) const; 272 void GenerateClassFieldToObject(const GeneratorOptions& options, 273 io::Printer* printer, 274 const FieldDescriptor* field) const; 275 void GenerateClassFromObject(const GeneratorOptions& options, 276 io::Printer* printer, 277 const Descriptor* desc) const; 278 void GenerateClassFieldFromObject(const GeneratorOptions& options, 279 io::Printer* printer, 280 const FieldDescriptor* field) const; 281 void GenerateClassRegistration(const GeneratorOptions& options, 282 io::Printer* printer, 283 const Descriptor* desc) const; 284 void GenerateClassFields(const GeneratorOptions& options, 285 io::Printer* printer, const Descriptor* desc) const; 286 void GenerateClassField(const GeneratorOptions& options, io::Printer* printer, 287 const FieldDescriptor* desc) const; 288 void GenerateClassExtensionFieldInfo(const GeneratorOptions& options, 289 io::Printer* printer, 290 const Descriptor* desc) const; 291 void GenerateClassDeserialize(const GeneratorOptions& options, 292 io::Printer* printer, 293 const Descriptor* desc) const; 294 void GenerateClassDeserializeBinary(const GeneratorOptions& options, 295 io::Printer* printer, 296 const Descriptor* desc) const; 297 void GenerateClassDeserializeBinaryField(const GeneratorOptions& options, 298 io::Printer* printer, 299 const FieldDescriptor* field) const; 300 void GenerateClassSerializeBinary(const GeneratorOptions& options, 301 io::Printer* printer, 302 const Descriptor* desc) const; 303 void GenerateClassSerializeBinaryField(const GeneratorOptions& options, 304 io::Printer* printer, 305 const FieldDescriptor* field) const; 306 307 // Generate definition for one enum. 308 void GenerateEnum(const GeneratorOptions& options, io::Printer* printer, 309 const EnumDescriptor* enumdesc) const; 310 311 // Generate an extension definition. 312 void GenerateExtension(const GeneratorOptions& options, io::Printer* printer, 313 const FieldDescriptor* field) const; 314 315 // Generate addFoo() method for repeated primitive fields. 316 void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options, 317 io::Printer* printer, 318 const FieldDescriptor* field, 319 bool untyped) const; 320 321 // Generate addFoo() method for repeated message fields. 322 void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options, 323 io::Printer* printer, 324 const FieldDescriptor* field) const; 325 326 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); 327 }; 328 329 } // namespace js 330 } // namespace compiler 331 } // namespace protobuf 332 } // namespace google 333 334 #include <google/protobuf/port_undef.inc> 335 336 #endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ 337