chromium/third_party/protobuf-javascript/src/generator/js_generator.cc

// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <assert.h>
#include "generator/well_known_types_embed.h"
#include <google/protobuf/compiler/scc.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>

#include <algorithm>
#include <limits>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "generator/js_generator.h"

namespace google {
namespace protobuf {
namespace compiler {
namespace js {

// Sorted list of JavaScript keywords. These cannot be used as names. If they
// appear, we prefix them with "pb_".
const char* kKeyword[] =;

static const int kNumKeyword =;

namespace {

// The mode of operation for bytes fields. Historically JSPB always carried
// bytes as JS {string}, containing base64 content by convention. With binary
// and proto3 serialization the new convention is to represent it as binary
// data in Uint8Array. See b/26173701 for background on the migration.
enum BytesMode {};

bool IsReserved(const std::string& ident) {}

std::string GetSnakeFilename(const std::string& filename) {}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// file foo/bar/baz.js.
std::string GetJSFilename(const GeneratorOptions& options,
                          const std::string& filename) {}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
std::string GetRootPath(const std::string& from_filename,
                        const std::string& to_filename) {}

// Returns the alias we assign to the module of the given .proto filename
// when importing.
std::string ModuleAlias(const std::string& filename) {}

// Returns the fully normalized JavaScript namespace for the given
// file descriptor's package.
std::string GetNamespace(const GeneratorOptions& options,
                         const FileDescriptor* file) {}

// Returns the name of the message with a leading dot and taking into account
// nesting, for example ".OuterMessage.InnerMessage", or returns empty if
// descriptor is null. This function does not handle namespacing, only message
// nesting.
std::string GetNestedMessageName(const Descriptor* descriptor) {}

// Returns the path prefix for a message or enumeration that
// lives under the given file and containing type.
std::string GetPrefix(const GeneratorOptions& options,
                      const FileDescriptor* file_descriptor,
                      const Descriptor* containing_type) {}

// Returns the fully normalized JavaScript path prefix for the given
// message descriptor.
std::string GetMessagePathPrefix(const GeneratorOptions& options,
                                 const Descriptor* descriptor) {}

// Returns the fully normalized JavaScript path for the given
// message descriptor.
std::string GetMessagePath(const GeneratorOptions& options,
                           const Descriptor* descriptor) {}

// Returns the fully normalized JavaScript path prefix for the given
// enumeration descriptor.
std::string GetEnumPathPrefix(const GeneratorOptions& options,
                              const EnumDescriptor* enum_descriptor) {}

// Returns the fully normalized JavaScript path for the given
// enumeration descriptor.
std::string GetEnumPath(const GeneratorOptions& options,
                        const EnumDescriptor* enum_descriptor) {}

std::string MaybeCrossFileRef(const GeneratorOptions& options,
                              const FileDescriptor* from_file,
                              const Descriptor* to_message) {}

std::string SubmessageTypeRef(const GeneratorOptions& options,
                              const FieldDescriptor* field) {}

// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields
// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate,
// and with reserved words triggering a "pb_" prefix.
// - Getters/setters: LOWER_UNDERSCORE -> UPPER_CAMEL, except for group fields
// (use the name directly), then append "List" if appropriate, then append "$"
// if resulting name is equal to a reserved word.
// - Enums: just uppercase.

// Locale-independent version of ToLower that deals only with ASCII A-Z.
char ToLowerASCII(char c) {}

std::vector<std::string> ParseLowerUnderscore(const std::string& input) {}

std::vector<std::string> ParseUpperCamel(const std::string& input) {}

std::string ToLowerCamel(const std::vector<std::string>& words) {}

std::string ToUpperCamel(const std::vector<std::string>& words) {}

// Based on code from descriptor.cc (Thanks Kenton!)
// Uppercases the entire string, turning ValueName into
// VALUENAME.
std::string ToEnumCase(const std::string& input) {}

std::string ToLower(const std::string& input) {}

// When we're generating one output file per SCC, this is the filename
// that top-level extensions should go in.
// e.g. one proto file (test.proto):
// package a;
// extends Foo {
//   ...
// }
// If "with_filename" equals true, the extension filename will be
// "proto.a_test_extensions.js", otherwise will be "proto.a.js"
std::string GetExtensionFileName(const GeneratorOptions& options,
                                 const FileDescriptor* file,
                                 bool with_filename) {}
// When we're generating one output file per SCC, this is the filename
// that all messages in the SCC should go in.
// If with_package equals true, filename will have package prefix,
// If the filename length is longer than 200, the filename will be the
// SCC's proto filename with suffix "_long_sccs_(index)" (if with_package equals
// true it still has package prefix)
std::string GetMessagesFileName(const GeneratorOptions& options, const SCC* scc,
                                bool with_package) {}

// When we're generating one output file per type name, this is the filename
// that a top-level enum should go in.
// If with_package equals true, filename will have package prefix.
std::string GetEnumFileName(const GeneratorOptions& options,
                            const EnumDescriptor* desc, bool with_package) {}

// Returns the message/response ID, if set.
std::string GetMessageId(const Descriptor* desc) {}

bool IgnoreExtensionField(const FieldDescriptor* field) {}

// Used inside Google only -- do not remove.
bool IsResponse(const Descriptor* desc) {}

bool IgnoreField(const FieldDescriptor* field) {}

// Do we ignore this message type?
bool IgnoreMessage(const Descriptor* d) {}

// Does JSPB ignore this entire oneof? True only if all fields are ignored.
bool IgnoreOneof(const OneofDescriptor* oneof) {}

std::string JSIdent(const GeneratorOptions& options,
                    const FieldDescriptor* field, bool is_upper_camel,
                    bool is_map, bool drop_list) {}

std::string JSObjectFieldName(const GeneratorOptions& options,
                              const FieldDescriptor* field) {}

std::string JSByteGetterSuffix(BytesMode bytes_mode) {}

// Returns the field name as a capitalized portion of a getter/setter method
// name, e.g. MyField for .getMyField().
std::string JSGetterName(const GeneratorOptions& options,
                         const FieldDescriptor* field,
                         BytesMode bytes_mode = BYTES_DEFAULT,
                         bool drop_list = false) {}

std::string JSOneofName(const OneofDescriptor* oneof) {}

// Returns the index corresponding to this field in the JSPB array (underlying
// data storage array).
std::string JSFieldIndex(const FieldDescriptor* field) {}

std::string JSOneofIndex(const OneofDescriptor* oneof) {}

// Decodes a codepoint in \x0000 -- \xFFFF.
uint16_t DecodeUTF8Codepoint(uint8_t* bytes, size_t* length) {}

// Escapes the contents of a string to be included within double-quotes ("") in
// JavaScript. The input data should be a UTF-8 encoded C++ string of chars.
// Returns false if |out| was truncated because |in| contained invalid UTF-8 or
// codepoints outside the BMP.
// TODO(b/115551870): Support codepoints outside the BMP.
bool EscapeJSString(const std::string& in, std::string* out) {}

std::string EscapeBase64(const std::string& in) {}

// Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the
// original codegen's formatting (which is just .toString() on java.lang.Double
// or java.lang.Float).
std::string PostProcessFloat(std::string result) {}

std::string FloatToString(float value) {}

std::string DoubleToString(double value) {}

bool InRealOneof(const FieldDescriptor* field) {}

// Return true if this is an integral field that should be represented as string
// in JS.
bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {}

std::string MaybeNumberString(const FieldDescriptor* field,
                              const std::string& orig) {}

std::string JSFieldDefault(const FieldDescriptor* field) {}

std::string ProtoTypeName(const GeneratorOptions& options,
                          const FieldDescriptor* field) {}

std::string JSIntegerTypeName(const FieldDescriptor* field) {}

std::string JSStringTypeName(const GeneratorOptions& options,
                             const FieldDescriptor* field,
                             BytesMode bytes_mode) {}

std::string JSTypeName(const GeneratorOptions& options,
                       const FieldDescriptor* field, BytesMode bytes_mode) {}

// Used inside Google only -- do not remove.
bool UseBrokenPresenceSemantics(const GeneratorOptions& options,
                                const FieldDescriptor* field) {}

// Returns true for fields that return "null" from accessors when they are
// unset. This should normally only be true for non-repeated submessages, but we
// have legacy users who relied on old behavior where accessors behaved this
// way.
bool ReturnsNullWhenUnset(const GeneratorOptions& options,
                          const FieldDescriptor* field) {}

// In a sane world, this would be the same as ReturnsNullWhenUnset().  But in
// the status quo, some fields declare that they never return null/undefined
// even though they actually do:
//   * required fields
//   * optional enum fields
//   * proto3 primitive fields.
bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options,
                                  const FieldDescriptor* field) {}

bool SetterAcceptsUndefined(const GeneratorOptions& options,
                            const FieldDescriptor* field) {}

bool SetterAcceptsNull(const GeneratorOptions& options,
                       const FieldDescriptor* field) {}

// Returns types which are known to by non-nullable by default.
// The style guide requires that we omit "!" in this case.
bool IsPrimitive(const std::string& type) {}

std::string JSFieldTypeAnnotation(const GeneratorOptions& options,
                                  const FieldDescriptor* field,
                                  bool is_setter_argument, bool force_present,
                                  bool singular_if_not_packed,
                                  BytesMode bytes_mode = BYTES_DEFAULT,
                                  bool force_singular = false) {}

std::string JSBinaryReaderMethodType(const FieldDescriptor* field) {}

std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
                                        bool is_writer) {}

std::string JSBinaryReaderMethodName(const GeneratorOptions& options,
                                     const FieldDescriptor* field) {}

std::string JSBinaryWriterMethodName(const GeneratorOptions& options,
                                     const FieldDescriptor* field) {}

std::string JSTypeTag(const FieldDescriptor* desc) {}

bool HasRepeatedFields(const GeneratorOptions& options,
                       const Descriptor* desc) {}

static const char* kRepeatedFieldArrayName =;

std::string RepeatedFieldsArrayName(const GeneratorOptions& options,
                                    const Descriptor* desc) {}

bool HasOneofFields(const Descriptor* desc) {}

static const char* kOneofGroupArrayName =;

std::string OneofFieldsArrayName(const GeneratorOptions& options,
                                 const Descriptor* desc) {}

std::string RepeatedFieldNumberList(const GeneratorOptions& options,
                                    const Descriptor* desc) {}

std::string OneofGroupList(const Descriptor* desc) {}

std::string JSOneofArray(const GeneratorOptions& options,
                         const FieldDescriptor* field) {}

std::string RelativeTypeName(const FieldDescriptor* field) {}

std::string JSExtensionsObjectName(const GeneratorOptions& options,
                                   const FileDescriptor* from_file,
                                   const Descriptor* desc) {}

static const int kMapKeyField =;
static const int kMapValueField =;

const FieldDescriptor* MapFieldKey(const FieldDescriptor* field) {}

const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) {}

std::string FieldDefinition(const GeneratorOptions& options,
                            const FieldDescriptor* field) {}

std::string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {}

bool ShouldGenerateExtension(const FieldDescriptor* field) {}

bool HasExtensions(const Descriptor* desc) {}

bool HasExtensions(const FileDescriptor* file) {}

bool HasMap(const GeneratorOptions& options, const Descriptor* desc) {}

bool FileHasMap(const GeneratorOptions& options, const FileDescriptor* desc) {}

bool IsExtendable(const Descriptor* desc) {}

// Returns the max index in the underlying data storage array beyond which the
// extension object is used.
std::string GetPivot(const Descriptor* desc) {}

// Whether this field represents presence.  For fields with presence, we
// generate extra methods (clearFoo() and hasFoo()) for this field.
bool HasFieldPresence(const GeneratorOptions& options,
                      const FieldDescriptor* field) {}

// We use this to implement the semantics that same file can be generated
// multiple times, but only the last one keep the short name. Others all use
// long name with extra information to distinguish (For message and enum, the
// extra information is package name, for file level extension, the extra
// information is proto's filename).
// We never actually write the files, but we keep a set of which descriptors
// were the final one for a given filename.
class FileDeduplicator {};

void DepthFirstSearch(const FileDescriptor* file,
                      std::vector<const FileDescriptor*>* list,
                      std::set<const FileDescriptor*>* seen) {}

// A functor for the predicate to remove_if() below.  Returns true if a given
// FileDescriptor is not in the given set.
class NotInSet {};

// This function generates an ordering of the input FileDescriptors that matches
// the logic of the old code generator.  The order is significant because two
// different input files can generate the same output file, and the last one
// needs to win.
void GenerateJspbFileOrder(const std::vector<const FileDescriptor*>& input,
                           std::vector<const FileDescriptor*>* ordered) {}

// If we're generating code in file-per-type mode, avoid overwriting files
// by choosing the last descriptor that writes each filename and permitting
// only those to generate code.

struct DepsGenerator {};

bool GenerateJspbAllowedMap(const GeneratorOptions& options,
                            const std::vector<const FileDescriptor*>& files,
                            std::map<const void*, std::string>* allowed_set,
                            SCCAnalyzer<DepsGenerator>* analyzer) {}

// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of
// file.
void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations,
                          io::Printer* printer) {}

bool IsWellKnownTypeFile(const FileDescriptor* file) {}

}  // anonymous namespace

void Generator::GenerateHeader(const GeneratorOptions& options,
                               const FileDescriptor* file,
                               io::Printer* printer) const {}

void Generator::FindProvidesForFile(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const FileDescriptor* file,
                                    std::set<std::string>* provided) const {}

void Generator::FindProvides(const GeneratorOptions& options,
                             io::Printer* printer,
                             const std::vector<const FileDescriptor*>& files,
                             std::set<std::string>* provided) const {}

void FindProvidesForOneOfEnum(const GeneratorOptions& options,
                              const OneofDescriptor* oneof,
                              std::set<std::string>* provided) {}

void FindProvidesForOneOfEnums(const GeneratorOptions& options,
                               io::Printer* printer, const Descriptor* desc,
                               std::set<std::string>* provided) {}

void Generator::FindProvidesForMessage(const GeneratorOptions& options,
                                       io::Printer* printer,
                                       const Descriptor* desc,
                                       std::set<std::string>* provided) const {}
void Generator::FindProvidesForEnum(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const EnumDescriptor* enumdesc,
                                    std::set<std::string>* provided) const {}

void Generator::FindProvidesForFields(
    const GeneratorOptions& options, io::Printer* printer,
    const std::vector<const FieldDescriptor*>& fields,
    std::set<std::string>* provided) const {}

void Generator::GenerateProvides(const GeneratorOptions& options,
                                 io::Printer* printer,
                                 std::set<std::string>* provided) const {}

void Generator::GenerateRequiresForSCC(const GeneratorOptions& options,
                                       io::Printer* printer, const SCC* scc,
                                       std::set<std::string>* provided) const {}

void Generator::GenerateRequiresForLibrary(
    const GeneratorOptions& options, io::Printer* printer,
    const std::vector<const FileDescriptor*>& files,
    std::set<std::string>* provided) const {}

void Generator::GenerateRequiresForExtensions(
    const GeneratorOptions& options, io::Printer* printer,
    const std::vector<const FieldDescriptor*>& fields,
    std::set<std::string>* provided) const {}

void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
                                     io::Printer* printer,
                                     std::set<std::string>* required,
                                     std::set<std::string>* forwards,
                                     std::set<std::string>* provided,
                                     bool require_jspb, bool require_extension,
                                     bool require_map) const {}

bool NamespaceOnly(const Descriptor* desc) {}

void Generator::FindRequiresForMessage(const GeneratorOptions& options,
                                       const Descriptor* desc,
                                       std::set<std::string>* required,
                                       std::set<std::string>* forwards,
                                       bool* have_message) const {}

void Generator::FindRequiresForField(const GeneratorOptions& options,
                                     const FieldDescriptor* field,
                                     std::set<std::string>* required,
                                     std::set<std::string>* forwards) const {}

void Generator::FindRequiresForExtension(
    const GeneratorOptions& options, const FieldDescriptor* field,
    std::set<std::string>* required, std::set<std::string>* forwards) const {}

void Generator::GenerateTestOnly(const GeneratorOptions& options,
                                 io::Printer* printer) const {}

void Generator::GenerateClassesAndEnums(const GeneratorOptions& options,
                                        io::Printer* printer,
                                        const FileDescriptor* file) const {}

void Generator::GenerateClass(const GeneratorOptions& options,
                              io::Printer* printer,
                              const Descriptor* desc) const {}

void Generator::GenerateClassConstructor(const GeneratorOptions& options,
                                         io::Printer* printer,
                                         const Descriptor* desc) const {}

void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo(
    const GeneratorOptions& options, io::Printer* printer,
    const Descriptor* desc) const {}

void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
                                       io::Printer* printer,
                                       const Descriptor* desc) const {}

void Generator::GenerateClassXid(const GeneratorOptions& options,
                                 io::Printer* printer,
                                 const Descriptor* desc) const {}

void Generator::GenerateOneofCaseDefinition(
    const GeneratorOptions& options, io::Printer* printer,
    const OneofDescriptor* oneof) const {}

void Generator::GenerateClassToObject(const GeneratorOptions& options,
                                      io::Printer* printer,
                                      const Descriptor* desc) const {}

void Generator::GenerateFieldValueExpression(io::Printer* printer,
                                             const char* obj_reference,
                                             const FieldDescriptor* field,
                                             bool use_default) const {}

void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
                                           io::Printer* printer,
                                           const FieldDescriptor* field) const {}

void Generator::GenerateObjectTypedef(const GeneratorOptions& options,
                                      io::Printer* printer,
                                      const Descriptor* desc) const {}

void Generator::GenerateClassFromObject(const GeneratorOptions& options,
                                        io::Printer* printer,
                                        const Descriptor* desc) const {}

void Generator::GenerateClassFieldFromObject(
    const GeneratorOptions& options, io::Printer* printer,
    const FieldDescriptor* field) const {}

void Generator::GenerateClassRegistration(const GeneratorOptions& options,
                                          io::Printer* printer,
                                          const Descriptor* desc) const {}

void Generator::GenerateClassFields(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const Descriptor* desc) const {}

void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer,
                          const FieldDescriptor* field, BytesMode bytes_mode) {}

void Generator::GenerateClassField(const GeneratorOptions& options,
                                   io::Printer* printer,
                                   const FieldDescriptor* field) const {}

void Generator::GenerateRepeatedPrimitiveHelperMethods(
    const GeneratorOptions& options, io::Printer* printer,
    const FieldDescriptor* field, bool untyped) const {}

void Generator::GenerateRepeatedMessageHelperMethods(
    const GeneratorOptions& options, io::Printer* printer,
    const FieldDescriptor* field) const {}

void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
                                                io::Printer* printer,
                                                const Descriptor* desc) const {}

void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
                                               io::Printer* printer,
                                               const Descriptor* desc) const {}

void Generator::GenerateClassDeserializeBinaryField(
    const GeneratorOptions& options, io::Printer* printer,
    const FieldDescriptor* field) const {}

void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
                                             io::Printer* printer,
                                             const Descriptor* desc) const {}

void Generator::GenerateClassSerializeBinaryField(
    const GeneratorOptions& options, io::Printer* printer,
    const FieldDescriptor* field) const {}

void Generator::GenerateEnum(const GeneratorOptions& options,
                             io::Printer* printer,
                             const EnumDescriptor* enumdesc) const {}

void Generator::GenerateExtension(const GeneratorOptions& options,
                                  io::Printer* printer,
                                  const FieldDescriptor* field) const {}

bool GeneratorOptions::ParseFromOptions(
    const std::vector<std::pair<std::string, std::string> >& options,
    std::string* error) {}

GeneratorOptions::OutputMode GeneratorOptions::output_mode() const {}

void Generator::GenerateFilesInDepOrder(
    const GeneratorOptions& options, io::Printer* printer,
    const std::vector<const FileDescriptor*>& files) const {}

void Generator::GenerateFileAndDeps(
    const GeneratorOptions& options, io::Printer* printer,
    const FileDescriptor* root, std::set<const FileDescriptor*>* all_files,
    std::set<const FileDescriptor*>* generated) const {}

bool Generator::GenerateFile(const FileDescriptor* file,
                             const GeneratorOptions& options,
                             GeneratorContext* context,
                             bool use_short_name) const {}

void Generator::GenerateFile(const GeneratorOptions& options,
                             io::Printer* printer,
                             const FileDescriptor* file) const {}

bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
                            const std::string& parameter,
                            GeneratorContext* context,
                            std::string* error) const {}

}  // namespace js
}  // namespace compiler
}  // namespace protobuf
}  // namespace google