• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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