js_generator.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. // Generates JavaScript code for a given .proto file.
  31. //
  32. #ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
  33. #define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
  34. #include <set>
  35. #include <string>
  36. #include <google/protobuf/stubs/logging.h>
  37. #include <google/protobuf/stubs/common.h>
  38. #include <google/protobuf/compiler/scc.h>
  39. #include <google/protobuf/compiler/code_generator.h>
  40. #include <google/protobuf/port_def.inc>
  41. namespace google {
  42. namespace protobuf {
  43. class Descriptor;
  44. class EnumDescriptor;
  45. class FieldDescriptor;
  46. class OneofDescriptor;
  47. class FileDescriptor;
  48. namespace io {
  49. class Printer;
  50. }
  51. namespace compiler {
  52. namespace js {
  53. struct GeneratorOptions {
  54. // Output path.
  55. std::string output_dir;
  56. // Namespace prefix.
  57. std::string namespace_prefix;
  58. // Enable binary-format support?
  59. bool binary;
  60. // What style of imports should be used.
  61. enum ImportStyle {
  62. kImportClosure, // goog.require()
  63. kImportCommonJs, // require()
  64. kImportCommonJsStrict, // require() with no global export
  65. kImportBrowser, // no import statements
  66. kImportEs6, // import { member } from ''
  67. } import_style;
  68. GeneratorOptions()
  69. : output_dir("."),
  70. namespace_prefix(""),
  71. binary(false),
  72. import_style(kImportClosure),
  73. add_require_for_enums(false),
  74. testonly(false),
  75. library(""),
  76. error_on_name_conflict(false),
  77. extension(".js"),
  78. one_output_file_per_input_file(false),
  79. annotate_code(false) {}
  80. bool ParseFromOptions(
  81. const std::vector<std::pair<std::string, std::string> >& options,
  82. std::string* error);
  83. // Returns the file name extension to use for generated code.
  84. std::string GetFileNameExtension() const {
  85. return import_style == kImportClosure ? extension : "_pb.js";
  86. }
  87. enum OutputMode {
  88. // Create an output file for each input .proto file.
  89. kOneOutputFilePerInputFile,
  90. // Create an output file for each type.
  91. kOneOutputFilePerSCC,
  92. // Put everything in a single file named by the library option.
  93. kEverythingInOneFile,
  94. };
  95. // Indicates how to output the generated code based on the provided options.
  96. OutputMode output_mode() const;
  97. // The remaining options are only relevant when we are using kImportClosure.
  98. // Add a `goog.requires()` call for each enum type used. If not set, a
  99. // forward declaration with `goog.forwardDeclare` is produced instead.
  100. bool add_require_for_enums;
  101. // Set this as a test-only module via `goog.setTestOnly();`.
  102. bool testonly;
  103. // Create a library with name <name>_lib.js rather than a separate .js file
  104. // per type?
  105. std::string library;
  106. // Error if there are two types that would generate the same output file?
  107. bool error_on_name_conflict;
  108. // The extension to use for output file names.
  109. std::string extension;
  110. // Create a separate output file for each input file?
  111. bool one_output_file_per_input_file;
  112. // If true, we should append annotations as comments on the last line for
  113. // generated .js file. Annotations used by tools like https://kythe.io
  114. // to provide cross-references between .js and .proto files. Annotations
  115. // are encoded as base64 proto of GeneratedCodeInfo message (see
  116. // descriptor.proto).
  117. bool annotate_code;
  118. };
  119. // CodeGenerator implementation which generates a JavaScript source file and
  120. // header. If you create your own protocol compiler binary and you want it to
  121. // support JavaScript output, you can do so by registering an instance of this
  122. // CodeGenerator with the CommandLineInterface in your main() function.
  123. class PROTOC_EXPORT Generator : public CodeGenerator {
  124. public:
  125. Generator() {}
  126. virtual ~Generator() {}
  127. bool Generate(const FileDescriptor* file, const std::string& parameter,
  128. GeneratorContext* context, std::string* error) const override {
  129. *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
  130. return false;
  131. }
  132. bool HasGenerateAll() const override { return true; }
  133. bool GenerateAll(const std::vector<const FileDescriptor*>& files,
  134. const std::string& parameter, GeneratorContext* context,
  135. std::string* error) const override;
  136. uint64 GetSupportedFeatures() const override {
  137. return FEATURE_PROTO3_OPTIONAL;
  138. }
  139. private:
  140. void GenerateHeader(const GeneratorOptions& options,
  141. const FileDescriptor* file, io::Printer* printer) const;
  142. // Generate goog.provides() calls.
  143. void FindProvides(const GeneratorOptions& options, io::Printer* printer,
  144. const std::vector<const FileDescriptor*>& file,
  145. std::set<std::string>* provided) const;
  146. void FindProvidesForFile(const GeneratorOptions& options,
  147. io::Printer* printer, const FileDescriptor* file,
  148. std::set<std::string>* provided) const;
  149. void FindProvidesForMessage(const GeneratorOptions& options,
  150. io::Printer* printer, const Descriptor* desc,
  151. std::set<std::string>* provided) const;
  152. void FindProvidesForEnum(const GeneratorOptions& options,
  153. io::Printer* printer, const EnumDescriptor* enumdesc,
  154. std::set<std::string>* provided) const;
  155. // For extension fields at file scope.
  156. void FindProvidesForFields(const GeneratorOptions& options,
  157. io::Printer* printer,
  158. const std::vector<const FieldDescriptor*>& fields,
  159. std::set<std::string>* provided) const;
  160. // Print the goog.provides() found by the methods above.
  161. void GenerateProvides(const GeneratorOptions& options, io::Printer* printer,
  162. std::set<std::string>* provided) const;
  163. // Generate goog.setTestOnly() if indicated.
  164. void GenerateTestOnly(const GeneratorOptions& options,
  165. io::Printer* printer) const;
  166. // Generate goog.requires() calls.
  167. void GenerateRequiresForLibrary(
  168. const GeneratorOptions& options, io::Printer* printer,
  169. const std::vector<const FileDescriptor*>& files,
  170. std::set<std::string>* provided) const;
  171. void GenerateRequiresForSCC(const GeneratorOptions& options,
  172. io::Printer* printer, const SCC* scc,
  173. std::set<std::string>* provided) const;
  174. // For extension fields at file scope.
  175. void GenerateRequiresForExtensions(
  176. const GeneratorOptions& options, io::Printer* printer,
  177. const std::vector<const FieldDescriptor*>& fields,
  178. std::set<std::string>* provided) const;
  179. void GenerateRequiresImpl(const GeneratorOptions& options,
  180. io::Printer* printer,
  181. std::set<std::string>* required,
  182. std::set<std::string>* forwards,
  183. std::set<std::string>* provided, bool require_jspb,
  184. bool require_extension, bool require_map) const;
  185. void FindRequiresForMessage(const GeneratorOptions& options,
  186. const Descriptor* desc,
  187. std::set<std::string>* required,
  188. std::set<std::string>* forwards,
  189. bool* have_message) const;
  190. void FindRequiresForField(const GeneratorOptions& options,
  191. const FieldDescriptor* field,
  192. std::set<std::string>* required,
  193. std::set<std::string>* forwards) const;
  194. void FindRequiresForExtension(const GeneratorOptions& options,
  195. const FieldDescriptor* field,
  196. std::set<std::string>* required,
  197. std::set<std::string>* forwards) const;
  198. // Generate all things in a proto file into one file.
  199. // If use_short_name is true, the generated file's name will only be short
  200. // name that without directory, otherwise filename equals file->name()
  201. bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options,
  202. GeneratorContext* context, bool use_short_name) const;
  203. void GenerateFile(const GeneratorOptions& options, io::Printer* printer,
  204. const FileDescriptor* file) const;
  205. // Generate definitions for all message classes and enums in all files,
  206. // processing the files in dependence order.
  207. void GenerateFilesInDepOrder(
  208. const GeneratorOptions& options, io::Printer* printer,
  209. const std::vector<const FileDescriptor*>& file) const;
  210. // Helper for above.
  211. void GenerateFileAndDeps(const GeneratorOptions& options,
  212. io::Printer* printer, const FileDescriptor* root,
  213. std::set<const FileDescriptor*>* all_files,
  214. std::set<const FileDescriptor*>* generated) const;
  215. // Generate definitions for all message classes and enums.
  216. void GenerateClassesAndEnums(const GeneratorOptions& options,
  217. io::Printer* printer,
  218. const FileDescriptor* file) const;
  219. void GenerateFieldValueExpression(io::Printer* printer,
  220. const char* obj_reference,
  221. const FieldDescriptor* field,
  222. bool use_default) const;
  223. // Generate definition for one class.
  224. void GenerateClass(const GeneratorOptions& options, io::Printer* printer,
  225. const Descriptor* desc) const;
  226. void GenerateClassConstructor(const GeneratorOptions& options,
  227. io::Printer* printer,
  228. const Descriptor* desc) const;
  229. void GenerateClassFieldInfo(const GeneratorOptions& options,
  230. io::Printer* printer,
  231. const Descriptor* desc) const;
  232. void GenerateClassConstructorAndDeclareExtensionFieldInfo(
  233. const GeneratorOptions& options, io::Printer* printer,
  234. const Descriptor* desc) const;
  235. void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer,
  236. const Descriptor* desc) const;
  237. void GenerateOneofCaseDefinition(const GeneratorOptions& options,
  238. io::Printer* printer,
  239. const OneofDescriptor* oneof) const;
  240. void GenerateObjectTypedef(const GeneratorOptions& options,
  241. io::Printer* printer,
  242. const Descriptor* desc) const;
  243. void GenerateClassToObject(const GeneratorOptions& options,
  244. io::Printer* printer,
  245. const Descriptor* desc) const;
  246. void GenerateClassFieldToObject(const GeneratorOptions& options,
  247. io::Printer* printer,
  248. const FieldDescriptor* field) const;
  249. void GenerateClassFromObject(const GeneratorOptions& options,
  250. io::Printer* printer,
  251. const Descriptor* desc) const;
  252. void GenerateClassFieldFromObject(const GeneratorOptions& options,
  253. io::Printer* printer,
  254. const FieldDescriptor* field) const;
  255. void GenerateClassRegistration(const GeneratorOptions& options,
  256. io::Printer* printer,
  257. const Descriptor* desc) const;
  258. void GenerateClassFields(const GeneratorOptions& options,
  259. io::Printer* printer, const Descriptor* desc) const;
  260. void GenerateClassField(const GeneratorOptions& options, io::Printer* printer,
  261. const FieldDescriptor* desc) const;
  262. void GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
  263. io::Printer* printer,
  264. const Descriptor* desc) const;
  265. void GenerateClassDeserialize(const GeneratorOptions& options,
  266. io::Printer* printer,
  267. const Descriptor* desc) const;
  268. void GenerateClassDeserializeBinary(const GeneratorOptions& options,
  269. io::Printer* printer,
  270. const Descriptor* desc) const;
  271. void GenerateClassDeserializeBinaryField(const GeneratorOptions& options,
  272. io::Printer* printer,
  273. const FieldDescriptor* field) const;
  274. void GenerateClassSerializeBinary(const GeneratorOptions& options,
  275. io::Printer* printer,
  276. const Descriptor* desc) const;
  277. void GenerateClassSerializeBinaryField(const GeneratorOptions& options,
  278. io::Printer* printer,
  279. const FieldDescriptor* field) const;
  280. // Generate definition for one enum.
  281. void GenerateEnum(const GeneratorOptions& options, io::Printer* printer,
  282. const EnumDescriptor* enumdesc) const;
  283. // Generate an extension definition.
  284. void GenerateExtension(const GeneratorOptions& options, io::Printer* printer,
  285. const FieldDescriptor* field) const;
  286. // Generate addFoo() method for repeated primitive fields.
  287. void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options,
  288. io::Printer* printer,
  289. const FieldDescriptor* field,
  290. bool untyped) const;
  291. // Generate addFoo() method for repeated message fields.
  292. void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options,
  293. io::Printer* printer,
  294. const FieldDescriptor* field) const;
  295. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
  296. };
  297. } // namespace js
  298. } // namespace compiler
  299. } // namespace protobuf
  300. } // namespace google
  301. #include <google/protobuf/port_undef.inc>
  302. #endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__