diff options
Diffstat (limited to 'src/google/protobuf/compiler')
113 files changed, 3065 insertions, 16953 deletions
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 0039b00..3413a36 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -42,28 +42,19 @@ namespace protobuf { namespace compiler { CodeGenerator::~CodeGenerator() {} -GeneratorContext::~GeneratorContext() {} +OutputDirectory::~OutputDirectory() {} -io::ZeroCopyOutputStream* -GeneratorContext::OpenForAppend(const string& filename) { - return NULL; -} - -io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( +io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert( const string& filename, const string& insertion_point) { - GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; + GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion."; return NULL; // make compiler happy } -void GeneratorContext::ListParsedFiles( - vector<const FileDescriptor*>* output) { - GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; -} - // Parses a set of comma-delimited name/value pairs. void ParseGeneratorParameter(const string& text, vector<pair<string, string> >* output) { - vector<string> parts = Split(text, ",", true); + vector<string> parts; + SplitStringUsing(text, ",", &parts); for (int i = 0; i < parts.size(); i++) { string::size_type equals_pos = parts[i].find_first_of('='); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 321a8cc..ea094cd 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -53,7 +53,7 @@ namespace compiler { // Defined in this file. class CodeGenerator; -class GeneratorContext; +class OutputDirectory; // The abstract interface to a class which generates code implementing a // particular proto file in a particular language. A number of these may @@ -76,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGenerator { // the problem (e.g. "invalid parameter") and returns false. virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error) const = 0; private: @@ -85,12 +85,11 @@ class LIBPROTOC_EXPORT CodeGenerator { // CodeGenerators generate one or more files in a given directory. This // abstract interface represents the directory to which the CodeGenerator is -// to write and other information about the context in which the Generator -// runs. -class LIBPROTOC_EXPORT GeneratorContext { +// to write. +class LIBPROTOC_EXPORT OutputDirectory { public: - inline GeneratorContext() {} - virtual ~GeneratorContext(); + inline OutputDirectory() {} + virtual ~OutputDirectory(); // Opens the given file, truncating it if it exists, and returns a // ZeroCopyOutputStream that writes to the file. The caller takes ownership @@ -104,9 +103,6 @@ class LIBPROTOC_EXPORT GeneratorContext { // contain "." or ".." components. virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; - // Similar to Open() but the output will be appended to the file if exists - virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename); - // Creates a ZeroCopyOutputStream which will insert code into the given file // at the given insertion point. See plugin.proto (plugin.pb.h) for more // information on insertion points. The default implementation @@ -116,19 +112,10 @@ class LIBPROTOC_EXPORT GeneratorContext { virtual io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); - // Returns a vector of FileDescriptors for all the files being compiled - // in this run. Useful for languages, such as Go, that treat files - // differently when compiled as a set rather than individually. - virtual void ListParsedFiles(vector<const FileDescriptor*>* output); - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory); }; -// The type GeneratorContext was once called OutputDirectory. This typedef -// provides backward compatibility. -typedef GeneratorContext OutputDirectory; - // Several code generators treat the parameter argument as holding a // list of options separated by commas. This helper function parses // a set of comma-delimited name/value pairs: e.g., diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index f9f27bd..d3495ca 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -48,11 +48,6 @@ #include <iostream> #include <ctype.h> -#include <google/protobuf/stubs/hash.h> -#include <memory> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/compiler/importer.h> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/plugin.pb.h> @@ -61,13 +56,14 @@ #include <google/protobuf/descriptor.h> #include <google/protobuf/text_format.h> #include <google/protobuf/dynamic_message.h> -#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/map-util.h> +#include <google/protobuf/stubs/stl_util-inl.h> +#include <google/protobuf/stubs/hash.h> namespace google { @@ -148,7 +144,7 @@ void AddTrailingSlash(string* path) { bool VerifyDirectoryExists(const string& path) { if (path.empty()) return true; - if (access(path.c_str(), F_OK) == -1) { + if (access(path.c_str(), W_OK) == -1) { cerr << path << ": " << strerror(errno) << endl; return false; } else { @@ -162,7 +158,8 @@ bool VerifyDirectoryExists(const string& path) { // directories listed in |filename|. bool TryCreateParentDirectory(const string& prefix, const string& filename) { // Recursively create parent directories to the output file. - vector<string> parts = Split(filename, "/", true); + vector<string> parts; + SplitStringUsing(filename, "/", &parts); string path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; @@ -185,23 +182,14 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, public io::ErrorCollector { public: - ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) - : format_(format), tree_(tree) {} + ErrorPrinter(ErrorFormat format) : format_(format) {} ~ErrorPrinter() {} // implements MultiFileErrorCollector ------------------------------ void AddError(const string& filename, int line, int column, const string& message) { - // Print full path when running under MSVS - string dfile; - if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && - tree_ != NULL && - tree_->VirtualFileToDiskFile(filename, &dfile)) { - cerr << dfile; - } else { - cerr << filename; - } + cerr << filename; // Users typically expect 1-based line/column numbers, so we add 1 // to each here. @@ -227,17 +215,16 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, private: const ErrorFormat format_; - DiskSourceTree *tree_; }; // ------------------------------------------------------------------- -// A GeneratorContext implementation that buffers files in memory, then dumps +// An OutputDirectory implementation that buffers files in memory, then dumps // them all to disk on demand. -class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { +class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { public: - GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files); - ~GeneratorContextImpl(); + MemoryOutputDirectory(); + ~MemoryOutputDirectory(); // Write all files in the directory to disk at the given output location, // which must end in a '/'. @@ -251,14 +238,10 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // format, unless one has already been written. void AddJarManifest(); - // implements GeneratorContext -------------------------------------- + // implements OutputDirectory -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); - io::ZeroCopyOutputStream* OpenForAppend(const string& filename); io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); - void ListParsedFiles(vector<const FileDescriptor*>* output) { - *output = parsed_files_; - } private: friend class MemoryOutputStream; @@ -266,16 +249,14 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // map instead of hash_map so that files are written in order (good when // writing zips). map<string, string*> files_; - const vector<const FileDescriptor*>& parsed_files_; bool had_error_; }; class CommandLineInterface::MemoryOutputStream : public io::ZeroCopyOutputStream { public: - MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, - bool append_mode); - MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, + MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename); + MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename, const string& insertion_point); virtual ~MemoryOutputStream(); @@ -286,33 +267,27 @@ class CommandLineInterface::MemoryOutputStream private: // Where to insert the string when it's done. - GeneratorContextImpl* directory_; + MemoryOutputDirectory* directory_; string filename_; string insertion_point_; // The string we're building. string data_; - // Whether we should append the output stream to the existing file. - bool append_mode_; - // StringOutputStream writing to data_. scoped_ptr<io::StringOutputStream> inner_; }; // ------------------------------------------------------------------- -CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( - const vector<const FileDescriptor*>& parsed_files) - : parsed_files_(parsed_files), - had_error_(false) { -} +CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory() + : had_error_(false) {} -CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { +CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() { STLDeleteValues(&files_); } -bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( +bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( const string& prefix) { if (had_error_) { return false; @@ -387,7 +362,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( return true; } -bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( +bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( const string& filename) { if (had_error_) { return false; @@ -428,7 +403,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( return true; } -void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { +void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { string** map_slot = &files_["META-INF/MANIFEST.MF"]; if (*map_slot == NULL) { *map_slot = new string( @@ -438,19 +413,13 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { } } -io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( +io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open( const string& filename) { - return new MemoryOutputStream(this, filename, false); + return new MemoryOutputStream(this, filename); } io::ZeroCopyOutputStream* -CommandLineInterface::GeneratorContextImpl::OpenForAppend( - const string& filename) { - return new MemoryOutputStream(this, filename, true); -} - -io::ZeroCopyOutputStream* -CommandLineInterface::GeneratorContextImpl::OpenForInsert( +CommandLineInterface::MemoryOutputDirectory::OpenForInsert( const string& filename, const string& insertion_point) { return new MemoryOutputStream(this, filename, insertion_point); } @@ -458,15 +427,14 @@ CommandLineInterface::GeneratorContextImpl::OpenForInsert( // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - GeneratorContextImpl* directory, const string& filename, bool append_mode) + MemoryOutputDirectory* directory, const string& filename) : directory_(directory), filename_(filename), - append_mode_(append_mode), inner_(new io::StringOutputStream(&data_)) { } CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - GeneratorContextImpl* directory, const string& filename, + MemoryOutputDirectory* directory, const string& filename, const string& insertion_point) : directory_(directory), filename_(filename), @@ -484,12 +452,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (insertion_point_.empty()) { // This was just a regular Open(). if (*map_slot != NULL) { - if (append_mode_) { - (*map_slot)->append(data_); - } else { - cerr << filename_ << ": Tried to write the same file twice." << endl; - directory_->had_error_ = true; - } + cerr << filename_ << ": Tried to write the same file twice." << endl; + directory_->had_error_ = true; return; } @@ -582,10 +546,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { CommandLineInterface::CommandLineInterface() : mode_(MODE_COMPILE), - print_mode_(PRINT_NONE), error_format_(ERROR_FORMAT_GCC), imports_in_descriptor_set_(false), - source_info_in_descriptor_set_(false), disallow_services_(false), inputs_are_proto_path_relative_(false) {} CommandLineInterface::~CommandLineInterface() {} @@ -594,23 +556,9 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name, CodeGenerator* generator, const string& help_text) { GeneratorInfo info; - info.flag_name = flag_name; - info.generator = generator; - info.help_text = help_text; - generators_by_flag_name_[flag_name] = info; -} - -void CommandLineInterface::RegisterGenerator(const string& flag_name, - const string& option_flag_name, - CodeGenerator* generator, - const string& help_text) { - GeneratorInfo info; - info.flag_name = flag_name; - info.option_flag_name = option_flag_name; info.generator = generator; info.help_text = help_text; - generators_by_flag_name_[flag_name] = info; - generators_by_option_name_[option_flag_name] = info; + generators_[flag_name] = info; } void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { @@ -619,14 +567,7 @@ void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { int CommandLineInterface::Run(int argc, const char* const argv[]) { Clear(); - switch (ParseArguments(argc, argv)) { - case PARSE_ARGUMENT_DONE_AND_EXIT: - return 0; - case PARSE_ARGUMENT_FAIL: - return 1; - case PARSE_ARGUMENT_DONE_AND_CONTINUE: - break; - } + if (!ParseArguments(argc, argv)) return 1; // Set up the source tree. DiskSourceTree source_tree; @@ -642,7 +583,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } // Allocate the Importer. - ErrorPrinter error_collector(error_format_, &source_tree); + ErrorPrinter error_collector(error_format_); Importer importer(&source_tree, &error_collector); vector<const FileDescriptor*> parsed_files; @@ -650,9 +591,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // Parse each file. for (int i = 0; i < input_files_.size(); i++) { // Import the file. - importer.AddUnusedImportTrackFile(input_files_[i]); const FileDescriptor* parsed_file = importer.Import(input_files_[i]); - importer.ClearUnusedImportTrackFiles(); if (parsed_file == NULL) return 1; parsed_files.push_back(parsed_file); @@ -664,11 +603,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - // We construct a separate GeneratorContext for each output location. Note + // We construct a separate OutputDirectory for each output location. Note // that two code generators may output to the same location, in which case - // they should share a single GeneratorContext so that OpenForInsert() works. - typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap; - GeneratorContextMap output_directories; + // they should share a single OutputDirectory (so that OpenForInsert() works). + typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap; + OutputDirectoryMap output_directories; // Generate output. if (mode_ == MODE_COMPILE) { @@ -678,11 +617,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { !HasSuffixString(output_location, ".jar")) { AddTrailingSlash(&output_location); } - GeneratorContextImpl** map_slot = &output_directories[output_location]; + MemoryOutputDirectory** map_slot = &output_directories[output_location]; if (*map_slot == NULL) { // First time we've seen this output location. - *map_slot = new GeneratorContextImpl(parsed_files); + *map_slot = new MemoryOutputDirectory; } if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { @@ -693,10 +632,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } // Write all output to disk. - for (GeneratorContextMap::iterator iter = output_directories.begin(); + for (OutputDirectoryMap::iterator iter = output_directories.begin(); iter != output_directories.end(); ++iter) { const string& location = iter->first; - GeneratorContextImpl* directory = iter->second; + MemoryOutputDirectory* directory = iter->second; if (HasSuffixString(location, "/")) { if (!directory->WriteAllToDisk(location)) { STLDeleteValues(&output_directories); @@ -741,25 +680,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - if (mode_ == MODE_PRINT) { - switch (print_mode_) { - case PRINT_FREE_FIELDS: - for (int i = 0; i < parsed_files.size(); ++i) { - const FileDescriptor* fd = parsed_files[i]; - for (int j = 0; j < fd->message_type_count(); ++j) { - PrintFreeFieldNumbers(fd->message_type(j)); - } - } - break; - case PRINT_NONE: - GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of " - "flag parsing in the CommonadLineInterface."; - return 1; - - // Do not add a default case. - } - } - return 0; } @@ -774,9 +694,7 @@ void CommandLineInterface::Clear() { descriptor_set_name_.clear(); mode_ = MODE_COMPILE; - print_mode_ = PRINT_NONE; imports_in_descriptor_set_ = false; - source_info_in_descriptor_set_ = false; disallow_services_ = false; } @@ -819,8 +737,7 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( return true; } -CommandLineInterface::ParseArgumentStatus -CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { +bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { executable_name_ = argv[0]; // Iterate through all arguments and parse them. @@ -834,50 +751,41 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { if (name == "--decode") { cerr << "To decode an unknown message, use --decode_raw." << endl; } - return PARSE_ARGUMENT_FAIL; + return false; } else { ++i; value = argv[i]; } } - ParseArgumentStatus status = InterpretArgument(name, value); - if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) - return status; + if (!InterpretArgument(name, value)) return false; } // If no --proto_path was given, use the current working directory. if (proto_path_.empty()) { - // Don't use make_pair as the old/default standard library on Solaris - // doesn't support it without explicit template parameters, which are - // incompatible with C++0x's make_pair. - proto_path_.push_back(pair<string, string>("", ".")); + proto_path_.push_back(make_pair("", ".")); } // Check some errror cases. bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); if (decoding_raw && !input_files_.empty()) { cerr << "When using --decode_raw, no input files should be given." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } else if (!decoding_raw && input_files_.empty()) { cerr << "Missing input file." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } if (mode_ == MODE_COMPILE && output_directives_.empty() && descriptor_set_name_.empty()) { cerr << "Missing output directives." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { cerr << "--include_imports only makes sense when combined with " "--descriptor_set_out." << endl; } - if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { - cerr << "--include_source_info only makes sense when combined with " - "--descriptor_set_out." << endl; - } - return PARSE_ARGUMENT_DONE_AND_CONTINUE; + return true; } bool CommandLineInterface::ParseArgument(const char* arg, @@ -927,10 +835,8 @@ bool CommandLineInterface::ParseArgument(const char* arg, if (*name == "-h" || *name == "--help" || *name == "--disallow_services" || *name == "--include_imports" || - *name == "--include_source_info" || *name == "--version" || - *name == "--decode_raw" || - *name == "--print_free_field_numbers") { + *name == "--decode_raw") { // HACK: These are the only flags that don't take a value. // They probably should not be hard-coded like this but for now it's // not worth doing better. @@ -941,9 +847,8 @@ bool CommandLineInterface::ParseArgument(const char* arg, return true; } -CommandLineInterface::ParseArgumentStatus -CommandLineInterface::InterpretArgument(const string& name, - const string& value) { +bool CommandLineInterface::InterpretArgument(const string& name, + const string& value) { if (name.empty()) { // Not a flag. Just a filename. if (value.empty()) { @@ -951,7 +856,7 @@ CommandLineInterface::InterpretArgument(const string& name, "arguments to " << executable_name_ << ". This is actually " "sort of hard to do. Congrats. Unfortunately it is not valid " "input so the program is going to die now." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } input_files_.push_back(value); @@ -960,14 +865,14 @@ CommandLineInterface::InterpretArgument(const string& name, // Java's -classpath (and some other languages) delimits path components // with colons. Let's accept that syntax too just to make things more // intuitive. - vector<string> parts = Split( - value, kPathSeparator, true); + vector<string> parts; + SplitStringUsing(value, kPathSeparator, &parts); for (int i = 0; i < parts.size(); i++) { string virtual_path; string disk_path; - string::size_type equals_pos = parts[i].find_first_of('='); + int equals_pos = parts[i].find_first_of('='); if (equals_pos == string::npos) { virtual_path = ""; disk_path = parts[i]; @@ -979,7 +884,7 @@ CommandLineInterface::InterpretArgument(const string& name, if (disk_path.empty()) { cerr << "--proto_path passed empty directory name. (Use \".\" for " "current directory.)" << endl; - return PARSE_ARGUMENT_FAIL; + return false; } // Make sure disk path exists, warn otherwise. @@ -987,45 +892,35 @@ CommandLineInterface::InterpretArgument(const string& name, cerr << disk_path << ": warning: directory does not exist." << endl; } - // Don't use make_pair as the old/default standard library on Solaris - // doesn't support it without explicit template parameters, which are - // incompatible with C++0x's make_pair. - proto_path_.push_back(pair<string, string>(virtual_path, disk_path)); + proto_path_.push_back(make_pair(virtual_path, disk_path)); } } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_name_.empty()) { cerr << name << " may only be passed once." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } if (value.empty()) { cerr << name << " requires a non-empty value." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } if (mode_ != MODE_COMPILE) { cerr << "Cannot use --encode or --decode and generate descriptors at the " "same time." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } descriptor_set_name_ = value; } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { cerr << name << " may only be passed once." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } imports_in_descriptor_set_ = true; - } else if (name == "--include_source_info") { - if (source_info_in_descriptor_set_) { - cerr << name << " may only be passed once." << endl; - return PARSE_ARGUMENT_FAIL; - } - source_info_in_descriptor_set_ = true; - } else if (name == "-h" || name == "--help") { PrintHelpText(); - return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. + return false; // Exit without running compiler. } else if (name == "--version") { if (!version_info_.empty()) { @@ -1034,7 +929,7 @@ CommandLineInterface::InterpretArgument(const string& name, cout << "libprotoc " << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) << endl; - return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. + return false; // Exit without running compiler. } else if (name == "--disallow_services") { disallow_services_ = true; @@ -1043,12 +938,12 @@ CommandLineInterface::InterpretArgument(const string& name, name == "--decode_raw") { if (mode_ != MODE_COMPILE) { cerr << "Only one of --encode and --decode can be specified." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { cerr << "Cannot use " << name << " and generate code or descriptors at the same time." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; @@ -1058,10 +953,10 @@ CommandLineInterface::InterpretArgument(const string& name, if (name == "--decode") { cerr << "To decode an unknown message, use --decode_raw." << endl; } - return PARSE_ARGUMENT_FAIL; + return false; } else if (!value.empty() && name == "--decode_raw") { cerr << "--decode_raw does not take a parameter." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } codec_type_ = value; @@ -1073,16 +968,16 @@ CommandLineInterface::InterpretArgument(const string& name, error_format_ = ERROR_FORMAT_MSVS; } else { cerr << "Unknown error format: " << value << endl; - return PARSE_ARGUMENT_FAIL; + return false; } } else if (name == "--plugin") { if (plugin_prefix_.empty()) { cerr << "This compiler does not support plugins." << endl; - return PARSE_ARGUMENT_FAIL; + return false; } - string plugin_name; + string name; string path; string::size_type equals_pos = value.find_first_of('='); @@ -1090,81 +985,57 @@ CommandLineInterface::InterpretArgument(const string& name, // Use the basename of the file. string::size_type slash_pos = value.find_last_of('/'); if (slash_pos == string::npos) { - plugin_name = value; + name = value; } else { - plugin_name = value.substr(slash_pos + 1); + name = value.substr(slash_pos + 1); } path = value; } else { - plugin_name = value.substr(0, equals_pos); + name = value.substr(0, equals_pos); path = value.substr(equals_pos + 1); } - plugins_[plugin_name] = path; + plugins_[name] = path; - } else if (name == "--print_free_field_numbers") { - if (mode_ != MODE_COMPILE) { - cerr << "Cannot use " << name << " and use --encode, --decode or print " - << "other info at the same time." << endl; - return PARSE_ARGUMENT_FAIL; - } - if (!output_directives_.empty() || !descriptor_set_name_.empty()) { - cerr << "Cannot use " << name - << " and generate code or descriptors at the same time." << endl; - return PARSE_ARGUMENT_FAIL; - } - mode_ = MODE_PRINT; - print_mode_ = PRINT_FREE_FIELDS; } else { // Some other flag. Look it up in the generators list. - const GeneratorInfo* generator_info = - FindOrNull(generators_by_flag_name_, name); + const GeneratorInfo* generator_info = FindOrNull(generators_, name); if (generator_info == NULL && (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { - // Check if it's a generator option flag. - generator_info = FindOrNull(generators_by_option_name_, name); - if (generator_info == NULL) { - cerr << "Unknown flag: " << name << endl; - return PARSE_ARGUMENT_FAIL; - } else { - string* parameters = &generator_parameters_[generator_info->flag_name]; - if (!parameters->empty()) { - parameters->append(","); - } - parameters->append(value); - } - } else { - // It's an output flag. Add it to the output directives. - if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode, --decode or print .proto info and " - "generate code at the same time." << endl; - return PARSE_ARGUMENT_FAIL; - } + cerr << "Unknown flag: " << name << endl; + return false; + } - OutputDirective directive; - directive.name = name; - if (generator_info == NULL) { - directive.generator = NULL; - } else { - directive.generator = generator_info->generator; - } + // It's an output flag. Add it to the output directives. + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use --encode or --decode and generate code at the " + "same time." << endl; + return false; + } - // Split value at ':' to separate the generator parameter from the - // filename. However, avoid doing this if the colon is part of a valid - // Windows-style absolute path. - string::size_type colon_pos = value.find_first_of(':'); - if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { - directive.output_location = value; - } else { - directive.parameter = value.substr(0, colon_pos); - directive.output_location = value.substr(colon_pos + 1); - } + OutputDirective directive; + directive.name = name; + if (generator_info == NULL) { + directive.generator = NULL; + } else { + directive.generator = generator_info->generator; + } - output_directives_.push_back(directive); + // Split value at ':' to separate the generator parameter from the + // filename. However, avoid doing this if the colon is part of a valid + // Windows-style absolute path. + string::size_type colon_pos = value.find_first_of(':'); + if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { + directive.output_location = value; + } else { + directive.parameter = value.substr(0, colon_pos); + directive.output_location = value.substr(colon_pos + 1); } + + output_directives_.push_back(directive); } - return PARSE_ARGUMENT_DONE_AND_CONTINUE; + return true; } void CommandLineInterface::PrintHelpText() { @@ -1197,20 +1068,9 @@ void CommandLineInterface::PrintHelpText() { " --include_imports When using --descriptor_set_out, also include\n" " all dependencies of the input files in the\n" " set, so that the set is self-contained.\n" -" --include_source_info When using --descriptor_set_out, do not strip\n" -" SourceCodeInfo from the FileDescriptorProto.\n" -" This results in vastly larger descriptors that\n" -" include information about the original\n" -" location of each decl in the source file as\n" -" well as surrounding comments.\n" " --error_format=FORMAT Set the format in which to print errors.\n" " FORMAT may be 'gcc' (the default) or 'msvs'\n" -" (Microsoft Visual Studio format).\n" -" --print_free_field_numbers Print the free field numbers of the messages\n" -" defined in the given proto files. Groups share\n" -" the same field number space with the parent \n" -" message. Extension ranges are counted as \n" -" occupied fields numbers." << endl; +" (Microsoft Visual Studio format)." << endl; if (!plugin_prefix_.empty()) { cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" @@ -1223,8 +1083,8 @@ void CommandLineInterface::PrintHelpText() { " the executable's own name differs." << endl; } - for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); - iter != generators_by_flag_name_.end(); ++iter) { + for (GeneratorMap::iterator iter = generators_.begin(); + iter != generators_.end(); ++iter) { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. @@ -1237,7 +1097,7 @@ void CommandLineInterface::PrintHelpText() { bool CommandLineInterface::GenerateOutput( const vector<const FileDescriptor*>& parsed_files, const OutputDirective& output_directive, - GeneratorContext* generator_context) { + OutputDirectory* output_directory) { // Call the generator. string error; if (output_directive.generator == NULL) { @@ -1252,22 +1112,16 @@ bool CommandLineInterface::GenerateOutput( if (!GeneratePluginOutput(parsed_files, plugin_name, output_directive.parameter, - generator_context, &error)) { + output_directory, &error)) { cerr << output_directive.name << ": " << error << endl; return false; } } else { // Regular generator. - string parameters = output_directive.parameter; - if (!generator_parameters_[output_directive.name].empty()) { - if (!parameters.empty()) { - parameters.append(","); - } - parameters.append(generator_parameters_[output_directive.name]); - } for (int i = 0; i < parsed_files.size(); i++) { - if (!output_directive.generator->Generate(parsed_files[i], parameters, - generator_context, &error)) { + if (!output_directive.generator->Generate( + parsed_files[i], output_directive.parameter, + output_directory, &error)) { // Generator returned an error. cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " << error << endl; @@ -1283,7 +1137,7 @@ bool CommandLineInterface::GeneratePluginOutput( const vector<const FileDescriptor*>& parsed_files, const string& plugin_name, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error) { CodeGeneratorRequest request; CodeGeneratorResponse response; @@ -1296,9 +1150,8 @@ bool CommandLineInterface::GeneratePluginOutput( set<const FileDescriptor*> already_seen; for (int i = 0; i < parsed_files.size(); i++) { request.add_file_to_generate(parsed_files[i]->name()); - GetTransitiveDependencies(parsed_files[i], - true, // Include source code info. - &already_seen, request.mutable_proto_file()); + GetTransitiveDependencies(parsed_files[i], &already_seen, + request.mutable_proto_file()); } // Invoke the plugin. @@ -1327,14 +1180,14 @@ bool CommandLineInterface::GeneratePluginOutput( // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(generator_context->OpenForInsert( + current_output.reset(output_directory->OpenForInsert( output_file.name(), output_file.insertion_point())); } else if (!output_file.name().empty()) { // Starting a new file. Open it. // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(generator_context->Open(output_file.name())); + current_output.reset(output_directory->Open(output_file.name())); } else if (current_output == NULL) { *error = strings::Substitute( "$0: First file chunk returned by plugin did not specify a file name.", @@ -1428,17 +1281,12 @@ bool CommandLineInterface::WriteDescriptorSet( if (imports_in_descriptor_set_) { set<const FileDescriptor*> already_seen; for (int i = 0; i < parsed_files.size(); i++) { - GetTransitiveDependencies(parsed_files[i], - source_info_in_descriptor_set_, - &already_seen, file_set.mutable_file()); + GetTransitiveDependencies( + parsed_files[i], &already_seen, file_set.mutable_file()); } } else { for (int i = 0; i < parsed_files.size(); i++) { - FileDescriptorProto* file_proto = file_set.add_file(); - parsed_files[i]->CopyTo(file_proto); - if (source_info_in_descriptor_set_) { - parsed_files[i]->CopySourceCodeInfoTo(file_proto); - } + parsed_files[i]->CopyTo(file_set.add_file()); } } @@ -1468,7 +1316,7 @@ bool CommandLineInterface::WriteDescriptorSet( } void CommandLineInterface::GetTransitiveDependencies( - const FileDescriptor* file, bool include_source_code_info, + const FileDescriptor* file, set<const FileDescriptor*>* already_seen, RepeatedPtrField<FileDescriptorProto>* output) { if (!already_seen->insert(file).second) { @@ -1478,125 +1326,13 @@ void CommandLineInterface::GetTransitiveDependencies( // Add all dependencies. for (int i = 0; i < file->dependency_count(); i++) { - GetTransitiveDependencies(file->dependency(i), include_source_code_info, - already_seen, output); + GetTransitiveDependencies(file->dependency(i), already_seen, output); } // Add this file. - FileDescriptorProto* new_descriptor = output->Add(); - file->CopyTo(new_descriptor); - if (include_source_code_info) { - file->CopySourceCodeInfoTo(new_descriptor); - } -} - -namespace { - -// Utility function for PrintFreeFieldNumbers. -// Stores occupied ranges into the ranges parameter, and next level of sub -// message types into the nested_messages parameter. The FieldRange is left -// inclusive, right exclusive. i.e. [a, b). -// -// Nested Messages: -// Note that it only stores the nested message type, iff the nested type is -// either a direct child of the given descriptor, or the nested type is a -// decendent of the given descriptor and all the nodes between the -// nested type and the given descriptor are group types. e.g. -// -// message Foo { -// message Bar { -// message NestedBar {} -// } -// group Baz = 1 { -// group NestedBazGroup = 2 { -// message Quz { -// message NestedQuz {} -// } -// } -// message NestedBaz {} -// } -// } -// -// In this case, Bar, Quz and NestedBaz will be added into the nested types. -// Since free field numbers of group types will not be printed, this makes sure -// the nested message types in groups will not be dropped. The nested_messages -// parameter will contain the direct children (when groups are ignored in the -// tree) of the given descriptor for the caller to traverse. The declaration -// order of the nested messages is also preserved. -typedef pair<int, int> FieldRange; -void GatherOccupiedFieldRanges(const Descriptor* descriptor, - set<FieldRange>* ranges, - vector<const Descriptor*>* nested_messages) { - set<const Descriptor*> groups; - for (int i = 0; i < descriptor->field_count(); ++i) { - const FieldDescriptor* fd = descriptor->field(i); - ranges->insert(FieldRange(fd->number(), fd->number() + 1)); - if (fd->type() == FieldDescriptor::TYPE_GROUP) { - groups.insert(fd->message_type()); - } - } - for (int i = 0; i < descriptor->extension_range_count(); ++i) { - ranges->insert(FieldRange(descriptor->extension_range(i)->start, - descriptor->extension_range(i)->end)); - } - // Handle the nested messages/groups in declaration order to make it - // post-order strict. - for (int i = 0; i < descriptor->nested_type_count(); ++i) { - const Descriptor* nested_desc = descriptor->nested_type(i); - if (groups.find(nested_desc) != groups.end()) { - GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages); - } else { - nested_messages->push_back(nested_desc); - } - } + file->CopyTo(output->Add()); } -// Utility function for PrintFreeFieldNumbers. -// Actually prints the formatted free field numbers for given message name and -// occupied ranges. -void FormatFreeFieldNumbers(const string& name, - const set<FieldRange>& ranges) { - string output; - StringAppendF(&output, "%-35s free:", name.c_str()); - int next_free_number = 1; - for (set<FieldRange>::const_iterator i = ranges.begin(); - i != ranges.end(); ++i) { - // This happens when groups re-use parent field numbers, in which - // case we skip the FieldRange entirely. - if (next_free_number >= i->second) continue; - - if (next_free_number < i->first) { - if (next_free_number + 1 == i->first) { - // Singleton - StringAppendF(&output, " %d", next_free_number); - } else { - // Range - StringAppendF(&output, " %d-%d", next_free_number, i->first - 1); - } - } - next_free_number = i->second; - } - if (next_free_number <= FieldDescriptor::kMaxNumber) { - StringAppendF(&output, " %d-INF", next_free_number); - } - cout << output << endl; -} - -} // namespace - -void CommandLineInterface::PrintFreeFieldNumbers( - const Descriptor* descriptor) { - set<FieldRange> ranges; - vector<const Descriptor*> nested_messages; - GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); - - for (int i = 0; i < nested_messages.size(); ++i) { - PrintFreeFieldNumbers(nested_messages[i]); - } - FormatFreeFieldNumbers(descriptor->full_name(), ranges); -} - - } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 47f2891..d25a50e 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -48,16 +48,15 @@ namespace google { namespace protobuf { -class Descriptor; // descriptor.h -class DescriptorPool; // descriptor.h class FileDescriptor; // descriptor.h +class DescriptorPool; // descriptor.h class FileDescriptorProto; // descriptor.pb.h template<typename T> class RepeatedPtrField; // repeated_field.h namespace compiler { class CodeGenerator; // code_generator.h -class GeneratorContext; // code_generator.h +class OutputDirectory; // code_generator.h class DiskSourceTree; // importer.h // This class implements the command-line interface to the protocol compiler. @@ -113,19 +112,6 @@ class LIBPROTOC_EXPORT CommandLineInterface { CodeGenerator* generator, const string& help_text); - // Register a code generator for a language. - // Besides flag_name you can specify another option_flag_name that could be - // used to pass extra parameters to the registered code generator. - // Suppose you have registered a generator by calling: - // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...) - // Then you could invoke the compiler with a command like: - // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz - // This will pass "enable_bar,enable_baz" as the parameter to the generator. - void RegisterGenerator(const string& flag_name, - const string& option_flag_name, - CodeGenerator* generator, - const string& help_text); - // Enables "plugins". In this mode, if a command-line flag ends with "_out" // but does not match any registered generator, the compiler will attempt to // find a "plugin" to implement the generator. Plugins are just executables. @@ -188,7 +174,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // ----------------------------------------------------------------- class ErrorPrinter; - class GeneratorContextImpl; + class MemoryOutputDirectory; class MemoryOutputStream; // Clear state from previous Run(). @@ -200,15 +186,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { bool MakeInputsBeProtoPathRelative( DiskSourceTree* source_tree); - // Return status for ParseArguments() and InterpretArgument(). - enum ParseArgumentStatus { - PARSE_ARGUMENT_DONE_AND_CONTINUE, - PARSE_ARGUMENT_DONE_AND_EXIT, - PARSE_ARGUMENT_FAIL - }; - // Parse all command-line arguments. - ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); + bool ParseArguments(int argc, const char* const argv[]); // Parses a command-line argument into a name/value pair. Returns // true if the next argument in the argv should be used as the value, @@ -224,8 +203,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { bool ParseArgument(const char* arg, string* name, string* value); // Interprets arguments parsed with ParseArgument. - ParseArgumentStatus InterpretArgument(const string& name, - const string& value); + bool InterpretArgument(const string& name, const string& value); // Print the --help text to stderr. void PrintHelpText(); @@ -234,11 +212,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { struct OutputDirective; // see below bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files, const OutputDirective& output_directive, - GeneratorContext* generator_context); + OutputDirectory* output_directory); bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files, const string& plugin_name, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error); // Implements --encode and --decode. @@ -252,30 +230,12 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protos will be ordered such that every file is listed before any file that // depends on it, so that you can call DescriptorPool::BuildFile() on them // in order. Any files in *already_seen will not be added, and each file - // added will be inserted into *already_seen. If include_source_code_info is - // true then include the source code information in the FileDescriptorProtos. + // added will be inserted into *already_seen. static void GetTransitiveDependencies( const FileDescriptor* file, - bool include_source_code_info, set<const FileDescriptor*>* already_seen, RepeatedPtrField<FileDescriptorProto>* output); - // Implements the --print_free_field_numbers. This function prints free field - // numbers into stdout for the message and it's nested message types in - // post-order, i.e. nested types first. Printed range are left-right - // inclusive, i.e. [a, b]. - // - // Groups: - // For historical reasons, groups are considered to share the same - // field number space with the parent message, thus it will not print free - // field numbers for groups. The field numbers used in the groups are - // excluded in the free field numbers of the parent message. - // - // Extension Ranges: - // Extension ranges are considered ocuppied field numbers and they will not be - // listed as free numbers in the output. - void PrintFreeFieldNumbers(const Descriptor* descriptor); - // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). @@ -284,21 +244,13 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Version info set with SetVersionInfo(). string version_info_; - // Registered generators. + // Map from flag names to registered generators. struct GeneratorInfo { - string flag_name; - string option_flag_name; CodeGenerator* generator; string help_text; }; typedef map<string, GeneratorInfo> GeneratorMap; - GeneratorMap generators_by_flag_name_; - GeneratorMap generators_by_option_name_; - // A map from generator names to the parameters specified using the option - // flag. For example, if the user invokes the compiler with: - // protoc --foo_out=outputdir --foo_opt=enable_bar ... - // Then there will be an entry ("--foo_out", "enable_bar") in this map. - map<string, string> generator_parameters_; + GeneratorMap generators_; // See AllowPlugins(). If this is empty, plugins aren't allowed. string plugin_prefix_; @@ -312,19 +264,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { enum Mode { MODE_COMPILE, // Normal mode: parse .proto files and compile them. MODE_ENCODE, // --encode: read text from stdin, write binary to stdout. - MODE_DECODE, // --decode: read binary from stdin, write text to stdout. - MODE_PRINT, // Print mode: print info of the given .proto files and exit. + MODE_DECODE // --decode: read binary from stdin, write text to stdout. }; Mode mode_; - enum PrintMode { - PRINT_NONE, // Not in MODE_PRINT - PRINT_FREE_FIELDS, // --print_free_fields - }; - - PrintMode print_mode_; - enum ErrorFormat { ERROR_FORMAT_GCC, // GCC error output format (default). ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). @@ -358,10 +302,6 @@ class LIBPROTOC_EXPORT CommandLineInterface { // the .proto files listed on the command-line are added. bool imports_in_descriptor_set_; - // True if --include_source_info was given, meaning that we should not strip - // SourceCodeInfo from the DescriptorSet. - bool source_info_in_descriptor_set_; - // Was the --disallow_services flag used? bool disallow_services_; diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 6bf7357..9129ebf 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -40,7 +40,6 @@ #else #include <unistd.h> #endif -#include <memory> #include <vector> #include <google/protobuf/descriptor.pb.h> @@ -49,7 +48,6 @@ #include <google/protobuf/compiler/command_line_interface.h> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/mock_code_generator.h> -#include <google/protobuf/compiler/subprocess.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/testing/file.h> @@ -123,13 +121,6 @@ class CommandLineInterfaceTest : public testing::Test { // substring. void ExpectErrorSubstring(const string& expected_substring); - // Like ExpectErrorSubstring, but checks that Run() returned zero. - void ExpectErrorSubstringWithZeroReturnCode( - const string& expected_substring); - - // Checks that the captured stdout is the same as the expected_text. - void ExpectCapturedStdout(const string& expected_text); - // Returns true if ExpectErrorSubstring(expected_substring) would pass, but // does not fail otherwise. bool HasAlternateErrorSubstring(const string& expected_substring); @@ -152,10 +143,6 @@ class CommandLineInterfaceTest : public testing::Test { const string& proto_name, const string& message_name, const string& output_directory); - void ExpectGeneratedWithMultipleInputs(const string& generator_name, - const string& all_proto_names, - const string& proto_name, - const string& message_name); void ExpectGeneratedWithInsertions(const string& generator_name, const string& parameter, const string& insertions, @@ -186,9 +173,6 @@ class CommandLineInterfaceTest : public testing::Test { // The captured stderr output. string error_text_; - // The captured stdout. - string captured_stdout_; - // Pointers which need to be deleted later. vector<CodeGenerator*> mock_generators_to_delete_; @@ -206,7 +190,7 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { called_ = true; parameter_ = parameter; @@ -231,12 +215,12 @@ void CommandLineInterfaceTest::SetUp() { } // Create the temp directory. - GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777)); + GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE)); // Register generators. CodeGenerator* generator = new MockCodeGenerator("test_generator"); mock_generators_to_delete_.push_back(generator); - cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output."); + cli_.RegisterGenerator("--test_out", generator, "Test output."); cli_.RegisterGenerator("-t", generator, "Test output."); generator = new MockCodeGenerator("alt_generator"); @@ -262,10 +246,12 @@ void CommandLineInterfaceTest::TearDown() { } void CommandLineInterfaceTest::Run(const string& command) { - vector<string> args = Split(command, " ", true); + vector<string> args; + SplitStringUsing(command, " ", &args); if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); + const char* possible_paths[] = { // When building with shared libraries, libtool hides the real executable // in .libs and puts a fake wrapper in the current directory. @@ -301,27 +287,18 @@ void CommandLineInterfaceTest::Run(const string& command) { } } - scoped_array<const char*> argv(new const char* [args.size()]); + scoped_array<const char*> argv(new const char*[args.size()]); for (int i = 0; i < args.size(); i++) { args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); argv[i] = args[i].c_str(); } - // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and - // stdout at the same time. Need to figure out why and add this capture back - // for Cygwin. -#if !defined(__CYGWIN__) - CaptureTestStdout(); -#endif CaptureTestStderr(); return_code_ = cli_.Run(args.size(), argv.get()); error_text_ = GetCapturedTestStderr(); -#if !defined(__CYGWIN__) - captured_stdout_ = GetCapturedTestStdout(); -#endif } // ------------------------------------------------------------------- @@ -333,20 +310,16 @@ void CommandLineInterfaceTest::CreateTempFile( string::size_type slash_pos = name.find_last_of('/'); if (slash_pos != string::npos) { string dir = name.substr(0, slash_pos); - if (!File::Exists(temp_directory_ + "/" + dir)) { - GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir, - 0777)); - } + File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777); } // Write file. string full_name = temp_directory_ + "/" + name; - GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true)); + File::WriteStringToFileOrDie(contents, full_name); } void CommandLineInterfaceTest::CreateTempDir(const string& name) { - GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name, - 0777)); + File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777); } // ------------------------------------------------------------------- @@ -368,12 +341,6 @@ void CommandLineInterfaceTest::ExpectErrorSubstring( EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); } -void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode( - const string& expected_substring) { - EXPECT_EQ(0, return_code_); - EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); -} - bool CommandLineInterfaceTest::HasAlternateErrorSubstring( const string& expected_substring) { EXPECT_NE(0, return_code_); @@ -386,8 +353,7 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& proto_name, const string& message_name) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, proto_name, - temp_directory_); + generator_name, parameter, "", proto_name, message_name, temp_directory_); } void CommandLineInterfaceTest::ExpectGenerated( @@ -397,21 +363,10 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& message_name, const string& output_directory) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, proto_name, + generator_name, parameter, "", proto_name, message_name, temp_directory_ + "/" + output_directory); } -void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( - const string& generator_name, - const string& all_proto_names, - const string& proto_name, - const string& message_name) { - MockCodeGenerator::ExpectGenerated( - generator_name, "", "", proto_name, message_name, - all_proto_names, - temp_directory_); -} - void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& generator_name, const string& parameter, @@ -420,7 +375,7 @@ void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& message_name) { MockCodeGenerator::ExpectGenerated( generator_name, parameter, insertions, proto_name, message_name, - proto_name, temp_directory_); + temp_directory_); } void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( @@ -433,18 +388,14 @@ void CommandLineInterfaceTest::ReadDescriptorSet( const string& filename, FileDescriptorSet* descriptor_set) { string path = temp_directory_ + "/" + filename; string file_contents; - GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); - + if (!File::ReadFileToString(path, &file_contents)) { + FAIL() << "File not found: " << path; + } if (!descriptor_set->ParseFromString(file_contents)) { FAIL() << "Could not parse file contents: " << path; } } -void CommandLineInterfaceTest::ExpectCapturedStdout( - const string& expected_text) { - EXPECT_EQ(expected_text, captured_stdout_); -} - // =================================================================== TEST_F(CommandLineInterfaceTest, BasicOutput) { @@ -504,44 +455,8 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) { "--proto_path=$tmpdir foo.proto bar.proto"); ExpectNoErrors(); - ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", - "foo.proto", "Foo"); - ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", - "bar.proto", "Bar"); - ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", - "foo.proto", "Foo"); - ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", - "bar.proto", "Bar"); -} - -TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { - // Test parsing multiple input files with an import of a separate file. - - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); - CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"baz.proto\";\n" - "message Bar {\n" - " optional Baz a = 1;\n" - "}\n"); - CreateTempFile("baz.proto", - "syntax = \"proto2\";\n" - "message Baz {}\n"); - - Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " - "--proto_path=$tmpdir foo.proto bar.proto"); - - ExpectNoErrors(); - ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", - "foo.proto", "Foo"); - ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", - "bar.proto", "Bar"); - ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", - "foo.proto", "Foo"); - ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", - "bar.proto", "Bar"); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); + ExpectGenerated("test_generator", "", "bar.proto", "Bar"); } TEST_F(CommandLineInterfaceTest, CreateDirectory) { @@ -577,32 +492,6 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) { ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo"); } -TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { - // Test that generator parameters specified with the option flag are - // correctly passed to the code generator. - - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); - // Create the "a" and "b" sub-directories. - CreateTempDir("a"); - CreateTempDir("b"); - - Run("protocol_compiler " - "--test_opt=foo1 " - "--test_out=bar:$tmpdir/a " - "--test_opt=foo2 " - "--test_out=baz:$tmpdir/b " - "--test_opt=foo3 " - "--proto_path=$tmpdir foo.proto"); - - ExpectNoErrors(); - ExpectGenerated( - "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); - ExpectGenerated( - "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); -} - TEST_F(CommandLineInterfaceTest, Insert) { // Test running a generator that inserts code into another's output. @@ -626,7 +515,7 @@ TEST_F(CommandLineInterfaceTest, Insert) { "foo.proto", "Foo"); } -#if defined(_WIN32) +#if defined(_WIN32) || defined(__CYGWIN__) TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { // Test that the output path can be a Windows-style path. @@ -836,35 +725,8 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - EXPECT_EQ(1, descriptor_set.file_size()); + ASSERT_EQ(1, descriptor_set.file_size()); EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); - // Descriptor set should not have source code info. - EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); -} - -TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); - CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); - - Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " - "--include_source_info --proto_path=$tmpdir bar.proto"); - - ExpectNoErrors(); - - FileDescriptorSet descriptor_set; - ReadDescriptorSet("descriptor_set", &descriptor_set); - if (HasFatalFailure()) return; - EXPECT_EQ(1, descriptor_set.file_size()); - EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); - // Source code info included. - EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); } TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { @@ -886,47 +748,13 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - EXPECT_EQ(2, descriptor_set.file_size()); + ASSERT_EQ(2, descriptor_set.file_size()); if (descriptor_set.file(0).name() == "bar.proto") { std::swap(descriptor_set.mutable_file()->mutable_data()[0], descriptor_set.mutable_file()->mutable_data()[1]); } EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); - // Descriptor set should not have source code info. - EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); - EXPECT_FALSE(descriptor_set.file(1).has_source_code_info()); -} - -TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); - CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); - - Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " - "--include_imports --include_source_info --proto_path=$tmpdir bar.proto"); - - ExpectNoErrors(); - - FileDescriptorSet descriptor_set; - ReadDescriptorSet("descriptor_set", &descriptor_set); - if (HasFatalFailure()) return; - EXPECT_EQ(2, descriptor_set.file_size()); - if (descriptor_set.file(0).name() == "bar.proto") { - std::swap(descriptor_set.mutable_file()->mutable_data()[0], - descriptor_set.mutable_file()->mutable_data()[1]); - } - EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); - EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); - // Source code info included. - EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); - EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } // ------------------------------------------------------------------- @@ -1249,17 +1077,6 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { #endif } -TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_HasSourceCodeInfo {}\n"); - - Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); - - ExpectErrorSubstring( - "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1."); -} - TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { // Test what happens if the plugin isn't found. @@ -1272,8 +1089,9 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { "--proto_path=$tmpdir error.proto"); #ifdef _WIN32 - ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " + - Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); + ExpectErrorSubstring( + "--badplug_out: prefix-gen-badplug: The system cannot find the file " + "specified."); #else // Error written to stdout by child process after exec() fails. ExpectErrorSubstring( @@ -1302,11 +1120,11 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) { TEST_F(CommandLineInterfaceTest, HelpText) { Run("test_exec_name --help"); - ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name "); - ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR"); - ExpectErrorSubstringWithZeroReturnCode("Test output."); - ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR"); - ExpectErrorSubstringWithZeroReturnCode("Alt output."); + ExpectErrorSubstring("Usage: test_exec_name "); + ExpectErrorSubstring("--test_out=OUT_DIR"); + ExpectErrorSubstring("Test output."); + ExpectErrorSubstring("--alt_out=OUT_DIR"); + ExpectErrorSubstring("Alt output."); } TEST_F(CommandLineInterfaceTest, GccFormatErrors) { @@ -1335,7 +1153,7 @@ TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) { "--proto_path=$tmpdir --error_format=msvs foo.proto"); ExpectErrorText( - "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " + "foo.proto(2) : error in column=1: Expected top-level statement " "(e.g. \"message\").\n"); } @@ -1416,76 +1234,6 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { ExpectErrorText("Missing value for flag: --test_out\n"); } -TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { - CreateTempFile( - "foo.proto", - "syntax = \"proto2\";\n" - "package foo;\n" - "message Foo {\n" - " optional int32 a = 2;\n" - " optional string b = 4;\n" - " optional string c = 5;\n" - " optional int64 d = 8;\n" - " optional double e = 10;\n" - "}\n"); - CreateTempFile( - "bar.proto", - "syntax = \"proto2\";\n" - "message Bar {\n" - " optional int32 a = 2;\n" - " extensions 4 to 5;\n" - " optional int64 d = 8;\n" - " extensions 10;\n" - "}\n"); - CreateTempFile( - "baz.proto", - "syntax = \"proto2\";\n" - "message Baz {\n" - " optional int32 a = 2;\n" - " optional int64 d = 8;\n" - " extensions 15 to max;\n" // unordered. - " extensions 13;\n" - " extensions 10 to 12;\n" - " extensions 5;\n" - " extensions 4;\n" - "}\n"); - CreateTempFile( - "quz.proto", - "syntax = \"proto2\";\n" - "message Quz {\n" - " message Foo {}\n" // nested message - " optional int32 a = 2;\n" - " optional group C = 4 {\n" - " optional int32 d = 5;\n" - " }\n" - " extensions 8 to 10;\n" - " optional group E = 11 {\n" - " optional int32 f = 9;\n" // explicitly reuse extension range 8-10 - " optional group G = 15 {\n" // nested group - " message Foo {}\n" // nested message inside nested group - " }\n" - " }\n" - "}\n"); - - Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir " - "foo.proto bar.proto baz.proto quz.proto"); - - ExpectNoErrors(); - - // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and - // stdout at the same time. Need to figure out why and add this test back - // for Cygwin. -#if !defined(__CYGWIN__) - ExpectCapturedStdout( - "foo.Foo free: 1 3 6-7 9 11-INF\n" - "Bar free: 1 3 6-7 9 11-INF\n" - "Baz free: 1 3 6-7 9 14\n" - "Quz.Foo free: 1-INF\n" - "Quz.E.G.Foo free: 1-INF\n" - "Quz free: 1 3 6-7 12-14 16-INF\n"); -#endif -} - // =================================================================== // Test for --encode and --decode. Note that it would be easier to do this @@ -1505,7 +1253,7 @@ class EncodeDecodeTest : public testing::Test { void RedirectStdinFromText(const string& input) { string filename = TestTempDir() + "/test_stdin"; - GOOGLE_CHECK_OK(File::SetContents(filename, input, true)); + File::WriteStringToFileOrDie(input, filename); GOOGLE_CHECK(RedirectStdinFromFile(filename)); } @@ -1539,7 +1287,7 @@ class EncodeDecodeTest : public testing::Test { SplitStringUsing(command, " ", &args); args.push_back("--proto_path=" + TestSourceDir()); - scoped_array<const char*> argv(new const char* [args.size()]); + scoped_array<const char*> argv(new const char*[args.size()]); for (int i = 0; i < args.size(); i++) { argv[i] = args[i].c_str(); } @@ -1560,7 +1308,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesBinaryFile(const string& filename) { string expected_output; - GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); + ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); // Don't use EXPECT_EQ because we don't want to print raw binary data to // stdout on failure. @@ -1569,7 +1317,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesTextFile(const string& filename) { string expected_output; - GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); + ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); ExpectStdoutMatchesText(expected_output); } @@ -1589,23 +1337,22 @@ class EncodeDecodeTest : public testing::Test { }; TEST_F(EncodeDecodeTest, Encode) { - RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); + RedirectStdinFromFile(TestSourceDir() + + "/google/protobuf/testdata/text_format_unittest_data.txt"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--encode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesBinaryFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); + "/google/protobuf/testdata/golden_message"); ExpectStderrMatchesText(""); } TEST_F(EncodeDecodeTest, Decode) { RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); + "/google/protobuf/testdata/golden_message"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--decode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesTextFile(TestSourceDir() + - "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); + "/google/protobuf/testdata/text_format_unittest_data.txt"); ExpectStderrMatchesText(""); } diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 4878819..30b1d2b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -48,8 +48,8 @@ #include <google/protobuf/compiler/importer.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/stl_util-inl.h> +#include <google/protobuf/stubs/map-util.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> @@ -79,10 +79,10 @@ class MockErrorCollector : public MultiFileErrorCollector { } }; -class MockGeneratorContext : public GeneratorContext { +class MockOutputDirectory : public OutputDirectory { public: - MockGeneratorContext() {} - ~MockGeneratorContext() { + MockOutputDirectory() {} + ~MockOutputDirectory() { STLDeleteValues(&files_); } @@ -93,16 +93,16 @@ class MockGeneratorContext : public GeneratorContext { << "Generator failed to generate file: " << virtual_filename; string actual_contents; - GOOGLE_CHECK_OK( - File::GetContents(TestSourceDir() + "/" + physical_filename, - &actual_contents, true)); + File::ReadFileToStringOrDie( + TestSourceDir() + "/" + physical_filename, + &actual_contents); EXPECT_TRUE(actual_contents == *expected_contents) << physical_filename << " needs to be regenerated. Please run " "generate_descriptor_proto.sh and add this file " "to your CL."; } - // implements GeneratorContext -------------------------------------- + // implements OutputDirectory -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { string** map_slot = &files_[filename]; @@ -130,24 +130,24 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) { ASSERT_TRUE(plugin_proto_file != NULL); CppGenerator generator; - MockGeneratorContext context; + MockOutputDirectory output_directory; string error; string parameter; parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; ASSERT_TRUE(generator.Generate(proto_file, parameter, - &context, &error)); + &output_directory, &error)); parameter = "dllexport_decl=LIBPROTOC_EXPORT"; ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, - &context, &error)); - - context.ExpectFileMatches("google/protobuf/descriptor.pb.h", - "google/protobuf/descriptor.pb.h"); - context.ExpectFileMatches("google/protobuf/descriptor.pb.cc", - "google/protobuf/descriptor.pb.cc"); - context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", - "google/protobuf/compiler/plugin.pb.h"); - context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", - "google/protobuf/compiler/plugin.pb.cc"); + &output_directory, &error)); + + output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h", + "google/protobuf/descriptor.pb.h"); + output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc", + "google/protobuf/descriptor.pb.cc"); + output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", + "google/protobuf/compiler/plugin.pb.h"); + output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", + "google/protobuf/compiler/plugin.pb.cc"); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index c31cb5b..76d2b79 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -45,27 +45,11 @@ namespace protobuf { namespace compiler { namespace cpp { -namespace { -// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the -// generation of the GOOGLE_ARRAYSIZE constant. -bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { - int32 max_value = descriptor->value(0)->number(); - for (int i = 0; i < descriptor->value_count(); i++) { - if (descriptor->value(i)->number() > max_value) { - max_value = descriptor->value(i)->number(); - } - } - return max_value != kint32max; -} -} // namespace - EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, - const Options& options) + const string& dllexport_decl) : descriptor_(descriptor), classname_(ClassName(descriptor, false)), - options_(options), - generate_array_size_(ShouldGenerateArraySize(descriptor)) { + dllexport_decl_(dllexport_decl) { } EnumGenerator::~EnumGenerator() {} @@ -83,10 +67,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { for (int i = 0; i < descriptor_->value_count(); i++) { vars["name"] = descriptor_->value(i)->name(); - // In C++, an value of -2147483648 gets interpreted as the negative of - // 2147483648, and since 2147483648 can't fit in an integer, this produces a - // compiler warning. This works around that issue. - vars["number"] = Int32ToString(descriptor_->value(i)->number()); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; @@ -107,22 +88,18 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["min_name"] = min_value->name(); vars["max_name"] = max_value->name(); - if (options_.dllexport_decl.empty()) { + if (dllexport_decl_.empty()) { vars["dllexport"] = ""; } else { - vars["dllexport"] = options_.dllexport_decl + " "; + vars["dllexport"] = dllexport_decl_ + " "; } printer->Print(vars, "$dllexport$bool $classname$_IsValid(int value);\n" "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" - "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"); - - if (generate_array_size_) { - printer->Print(vars, - "const int $prefix$$short_name$_ARRAYSIZE = " - "$prefix$$short_name$_MAX + 1;\n\n"); - } + "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" + "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n" + "\n"); if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -146,7 +123,6 @@ void EnumGenerator:: GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { if (HasDescriptorMethods(descriptor_->file())) { printer->Print( - "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n" "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" " return $classname$_descriptor();\n" @@ -174,12 +150,9 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { "static const $nested_name$ $nested_name$_MIN =\n" " $classname$_$nested_name$_MIN;\n" "static const $nested_name$ $nested_name$_MAX =\n" - " $classname$_$nested_name$_MAX;\n"); - if (generate_array_size_) { - printer->Print(vars, - "static const int $nested_name$_ARRAYSIZE =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n"); - } + " $classname$_$nested_name$_MAX;\n" + "static const int $nested_name$_ARRAYSIZE =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n"); if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -245,7 +218,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { iter != numbers.end(); ++iter) { printer->Print( " case $number$:\n", - "number", Int32ToString(*iter)); + "number", SimpleItoa(*iter)); } printer->Print(vars, @@ -272,11 +245,8 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { } printer->Print(vars, "const $classname$ $parent$::$nested_name$_MIN;\n" - "const $classname$ $parent$::$nested_name$_MAX;\n"); - if (generate_array_size_) { - printer->Print(vars, - "const int $parent$::$nested_name$_ARRAYSIZE;\n"); - } + "const $classname$ $parent$::$nested_name$_MAX;\n" + "const int $parent$::$nested_name$_ARRAYSIZE;\n"); printer->Print("#endif // _MSC_VER\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 1ebd7cf..58f7721 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -36,10 +36,8 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ #include <string> -#include <google/protobuf/compiler/cpp/cpp_options.h> #include <google/protobuf/descriptor.h> - namespace google { namespace protobuf { namespace io { @@ -55,7 +53,7 @@ class EnumGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit EnumGenerator(const EnumDescriptor* descriptor, - const Options& options); + const string& dllexport_decl); ~EnumGenerator(); // Header stuff. @@ -88,9 +86,7 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; string classname_; - Options options_; - // whether to generate the *_ARRAYSIZE constant. - bool generate_array_size_; + string dllexport_decl_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 20b18ad..91ce493 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,13 +46,11 @@ namespace cpp { namespace { void SetEnumVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); + map<string, string>* variables) { + SetCommonFieldVariables(descriptor, variables); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); (*variables)["type"] = ClassName(descriptor->enum_type(), true); - (*variables)["default"] = Int32ToString(default_value->number()); - (*variables)["full_name"] = descriptor->full_name(); + (*variables)["default"] = SimpleItoa(default_value->number()); } } // namespace @@ -60,10 +58,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +EnumFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_, options); + SetEnumVariables(descriptor, &variables_); } EnumFieldGenerator::~EnumFieldGenerator() {} @@ -84,14 +81,12 @@ void EnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_);\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" - " assert($type$_IsValid(value));\n" - " set_has_$name$();\n" + " GOOGLE_DCHECK($type$_IsValid(value));\n" + " _set_bit($index$);\n" " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -124,15 +119,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " set_$name$(static_cast< $type$ >(value));\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); - } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print(variables_, "}\n"); @@ -161,57 +151,10 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== -EnumOneofFieldGenerator:: -EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : EnumFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} - -void EnumOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " if (has_$name$()) {\n" - " return static_cast< $type$ >($oneof_prefix$$name$_);\n" - " }\n" - " return static_cast< $type$ >($default$);\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " assert($type$_IsValid(value));\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $oneof_prefix$$name$_ = value;\n" - "}\n"); -} - -void EnumOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); -} - -void EnumOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void EnumOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, - " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); -} - -// =================================================================== - RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_, options); + SetEnumVariables(descriptor, &variables_); } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} @@ -220,8 +163,7 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField<int> $name$_;\n"); - if (descriptor_->options().packed() - && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -242,28 +184,23 @@ void RepeatedEnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_.Get(index));\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" - " assert($type$_IsValid(value));\n" + " GOOGLE_DCHECK($type$_IsValid(value));\n" " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" - " assert($type$_IsValid(value));\n" + " GOOGLE_DCHECK($type$_IsValid(value));\n" " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField<int>&\n" "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField<int>*\n" "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -298,15 +235,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); - } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print("}\n"); } @@ -413,9 +345,7 @@ GenerateByteSize(io::Printer* printer) const { " total_size += $tag_size$ +\n" " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" "_$name$_cached_byte_size_ = data_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" "total_size += data_size;\n"); } else { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index def2b23..0793430 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,8 +46,7 @@ namespace cpp { class EnumFieldGenerator : public FieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit EnumFieldGenerator(const FieldDescriptor* descriptor); ~EnumFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -63,34 +62,16 @@ class EnumFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; -class EnumOneofFieldGenerator : public EnumFieldGenerator { - public: - explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~EnumOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateClearingCode(io::Printer* printer) const; - void GenerateSwappingCode(io::Printer* printer) const; - void GenerateConstructorCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); -}; - class RepeatedEnumFieldGenerator : public FieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); ~RepeatedEnumFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index 468ca48..658a707 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -57,9 +57,9 @@ string ExtendeeClassName(const FieldDescriptor* descriptor) { } // anonymous namespace ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, - const Options& options) + const string& dllexport_decl) : descriptor_(descriptor), - options_(options) { + dllexport_decl_(dllexport_decl) { // Construct type_traits_. if (descriptor_->is_repeated()) { type_traits_ = "Repeated"; @@ -106,8 +106,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { // export/import specifier. if (descriptor_->extension_scope() == NULL) { vars["qualifier"] = "extern"; - if (!options_.dllexport_decl.empty()) { - vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"]; + if (!dllexport_decl_.empty()) { + vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"]; } } else { vars["qualifier"] = "static"; diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h index d354c16..3068b09 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.h +++ b/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -37,7 +37,6 @@ #include <string> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/cpp/cpp_options.h> namespace google { namespace protobuf { @@ -57,8 +56,8 @@ namespace cpp { class ExtensionGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit ExtensionGenerator(const FieldDescriptor* desycriptor, - const Options& options); + explicit ExtensionGenerator(const FieldDescriptor* descriptor, + const string& dllexport_decl); ~ExtensionGenerator(); // Header stuff. @@ -73,7 +72,7 @@ class ExtensionGenerator { private: const FieldDescriptor* descriptor_; string type_traits_; - Options options_; + string dllexport_decl_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 1e9a40a..103cac4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,8 +33,6 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/cpp/cpp_field.h> -#include <memory> - #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_primitive_field.h> #include <google/protobuf/compiler/cpp/cpp_string_field.h> @@ -54,8 +52,7 @@ namespace cpp { using internal::WireFormat; void SetCommonFieldVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options) { + map<string, string>* variables) { (*variables)["name"] = FieldName(descriptor); (*variables)["index"] = SimpleItoa(descriptor->index()); (*variables)["number"] = SimpleItoa(descriptor->number()); @@ -67,13 +64,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["deprecation"] = descriptor->options().deprecated() ? " PROTOBUF_DEPRECATED" : ""; - (*variables)["cppget"] = "Get"; -} - -void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, - map<string, string>* variables) { - (*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_."; - (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); } FieldGenerator::~FieldGenerator() {} @@ -90,63 +80,46 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { } -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, - const Options& options) - : descriptor_(descriptor), - field_generators_( - new scoped_ptr<FieldGenerator>[descriptor->field_count()]) { +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_( + new scoped_ptr<FieldGenerator>[descriptor->field_count()]) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i), options)); + field_generators_[i].reset(MakeGenerator(descriptor->field(i))); } } -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, - const Options& options) { +FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) { if (field->is_repeated()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field, options); + return new RepeatedMessageFieldGenerator(field); case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // RepeatedStringFieldGenerator handles unknown ctypes. case FieldOptions::STRING: - return new RepeatedStringFieldGenerator(field, options); - } - case FieldDescriptor::CPPTYPE_ENUM: - return new RepeatedEnumFieldGenerator(field, options); - default: - return new RepeatedPrimitiveFieldGenerator(field, options); - } - } else if (field->containing_oneof()) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageOneofFieldGenerator(field, options); - case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // StringOneofFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new StringOneofFieldGenerator(field, options); + return new RepeatedStringFieldGenerator(field); } case FieldDescriptor::CPPTYPE_ENUM: - return new EnumOneofFieldGenerator(field, options); + return new RepeatedEnumFieldGenerator(field); default: - return new PrimitiveOneofFieldGenerator(field, options); + return new RepeatedPrimitiveFieldGenerator(field); } } else { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageFieldGenerator(field, options); + return new MessageFieldGenerator(field); case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // StringFieldGenerator handles unknown ctypes. case FieldOptions::STRING: - return new StringFieldGenerator(field, options); + return new StringFieldGenerator(field); } case FieldDescriptor::CPPTYPE_ENUM: - return new EnumFieldGenerator(field, options); + return new EnumFieldGenerator(field); default: - return new PrimitiveFieldGenerator(field, options); + return new PrimitiveFieldGenerator(field); } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 96c2963..c303a33 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -36,11 +36,10 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #include <map> -#include <memory> #include <string> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/cpp_options.h> namespace google { namespace protobuf { @@ -58,11 +57,7 @@ namespace cpp { // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', // 'deprecation']. void SetCommonFieldVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options); - -void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, - map<string, string>* variables); + map<string, string>* variables); class FieldGenerator { public: @@ -74,11 +69,6 @@ class FieldGenerator { // class. virtual void GeneratePrivateMembers(io::Printer* printer) const = 0; - // Generate static default variable for this field. These are placed inside - // the message class. Most field types don't need this, so the default - // implementation is empty. - virtual void GenerateStaticMembers(io::Printer* printer) const {} - // Generate prototypes for all of the accessor functions related to this // field. These are placed inside the class definition. virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; @@ -124,13 +114,6 @@ class FieldGenerator { // Most field types don't need this, so the default implementation is empty. virtual void GenerateDestructorCode(io::Printer* printer) const {} - // Generate code that allocates the fields's default instance. - virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {} - - // Generate code that should be run when ShutdownProtobufLibrary() is called, - // to delete all dynamically-allocated objects. - virtual void GenerateShutdownCode(io::Printer* printer) const {} - // Generate lines to decode this field, which will be placed inside the // message's MergeFromCodedStream() method. virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0; @@ -161,7 +144,7 @@ class FieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options); + explicit FieldGeneratorMap(const Descriptor* descriptor); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; @@ -170,8 +153,7 @@ class FieldGeneratorMap { const Descriptor* descriptor_; scoped_array<scoped_ptr<FieldGenerator> > field_generators_; - static FieldGenerator* MakeGenerator(const FieldDescriptor* field, - const Options& options); + static FieldGenerator* MakeGenerator(const FieldDescriptor* field); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index fa19427..80da7e4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,9 +33,6 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/cpp/cpp_file.h> -#include <memory> -#include <set> - #include <google/protobuf/compiler/cpp/cpp_enum.h> #include <google/protobuf/compiler/cpp/cpp_service.h> #include <google/protobuf/compiler/cpp/cpp_extension.h> @@ -53,36 +50,37 @@ namespace cpp { // =================================================================== -FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) - : file_(file), - message_generators_( - new scoped_ptr<MessageGenerator>[file->message_type_count()]), - enum_generators_( - new scoped_ptr<EnumGenerator>[file->enum_type_count()]), - service_generators_( - new scoped_ptr<ServiceGenerator>[file->service_count()]), - extension_generators_( - new scoped_ptr<ExtensionGenerator>[file->extension_count()]), - options_(options) { +FileGenerator::FileGenerator(const FileDescriptor* file, + const string& dllexport_decl) + : file_(file), + message_generators_( + new scoped_ptr<MessageGenerator>[file->message_type_count()]), + enum_generators_( + new scoped_ptr<EnumGenerator>[file->enum_type_count()]), + service_generators_( + new scoped_ptr<ServiceGenerator>[file->service_count()]), + extension_generators_( + new scoped_ptr<ExtensionGenerator>[file->extension_count()]), + dllexport_decl_(dllexport_decl) { for (int i = 0; i < file->message_type_count(); i++) { message_generators_[i].reset( - new MessageGenerator(file->message_type(i), options)); + new MessageGenerator(file->message_type(i), dllexport_decl)); } for (int i = 0; i < file->enum_type_count(); i++) { enum_generators_[i].reset( - new EnumGenerator(file->enum_type(i), options)); + new EnumGenerator(file->enum_type(i), dllexport_decl)); } for (int i = 0; i < file->service_count(); i++) { service_generators_[i].reset( - new ServiceGenerator(file->service(i), options)); + new ServiceGenerator(file->service(i), dllexport_decl)); } for (int i = 0; i < file->extension_count(); i++) { extension_generators_[i].reset( - new ExtensionGenerator(file->extension(i), options)); + new ExtensionGenerator(file->extension(i), dllexport_decl)); } SplitStringUsing(file_->package(), ".", &package_parts_); @@ -106,7 +104,6 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "filename", file_->name(), "filename_identifier", filename_identifier); - printer->Print( "#include <google/protobuf/stubs/common.h>\n" "\n"); @@ -131,23 +128,13 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // OK, it's now safe to #include other files. printer->Print( - "#include <google/protobuf/generated_message_util.h>\n"); - if (file_->message_type_count() > 0) { - if (HasDescriptorMethods(file_)) { - printer->Print( - "#include <google/protobuf/message.h>\n"); - } else { - printer->Print( - "#include <google/protobuf/message_lite.h>\n"); - } - } - printer->Print( + "#include <google/protobuf/generated_message_util.h>\n" "#include <google/protobuf/repeated_field.h>\n" "#include <google/protobuf/extension_set.h>\n"); - if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { + if (HasDescriptorMethods(file_)) { printer->Print( - "#include <google/protobuf/generated_enum_reflection.h>\n"); + "#include <google/protobuf/generated_message_reflection.h>\n"); } if (HasGenericServices(file_)) { @@ -155,32 +142,16 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#include <google/protobuf/service.h>\n"); } - if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { - printer->Print( - "#include <google/protobuf/unknown_field_set.h>\n"); - } - - - set<string> public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } for (int i = 0; i < file_->dependency_count(); i++) { - const string& name = file_->dependency(i)->name(); - bool public_import = (public_import_names.count(name) != 0); - - printer->Print( - "#include \"$dependency$.pb.h\"$iwyu$\n", - "dependency", StripProto(name), - "iwyu", (public_import) ? " // IWYU pragma: export" : ""); + "#include \"$dependency$.pb.h\"\n", + "dependency", StripProto(file_->dependency(i)->name())); } printer->Print( "// @@protoc_insertion_point(includes)\n"); - // Open namespace. GenerateNamespaceOpeners(printer); @@ -191,7 +162,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "// Internal implementation detail -- do not call these.\n" "void $dllexport_decl$ $adddescriptorsname$();\n", "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "dllexport_decl", options_.dllexport_decl); + "dllexport_decl", dllexport_decl_); printer->Print( // Note that we don't put dllexport_decl on these because they are only @@ -259,7 +230,6 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); - // Generate class inline methods. for (int i = 0; i < file_->message_type_count(); i++) { if (i > 0) { @@ -312,33 +282,20 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" "\n" - // The generated code calls accessors that might be deprecated. We don't // want the compiler to warn in generated code. "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" "#include \"$basename$.pb.h\"\n" - "\n" - "#include <algorithm>\n" // for swap() - "\n" - "#include <google/protobuf/stubs/common.h>\n" + "#include <google/protobuf/stubs/once.h>\n" "#include <google/protobuf/io/coded_stream.h>\n" "#include <google/protobuf/wire_format_lite_inl.h>\n", - "filename", file_->name(), "basename", StripProto(file_->name())); - // Unknown fields implementation in lite mode uses StringOutputStream - if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { - printer->Print( - "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n"); - } - if (HasDescriptorMethods(file_)) { printer->Print( "#include <google/protobuf/descriptor.h>\n" - "#include <google/protobuf/generated_message_reflection.h>\n" "#include <google/protobuf/reflection_ops.h>\n" "#include <google/protobuf/wire_format.h>\n"); } @@ -421,12 +378,11 @@ void FileGenerator::GenerateSource(io::Printer* printer) { void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // AddDescriptors() is a file-level procedure which adds the encoded - // FileDescriptorProto for this .proto file to the global DescriptorPool for - // generated files (DescriptorPool::generated_pool()). It either runs at - // static initialization time (by default) or when default_instance() is - // called for the first time (in LITE_RUNTIME mode with - // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also - // constructs default instances and registers extensions. + // FileDescriptorProto for this .proto file to the global DescriptorPool + // for generated files (DescriptorPool::generated_pool()). It always runs + // at static initialization time, so all files will be registered before + // main() starts. This procedure also constructs default instances and + // registers extensions. // // Its sibling, AssignDescriptors(), actually pulls the compiled // FileDescriptor from the DescriptorPool and uses it to populate all of @@ -530,29 +486,22 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { printer->Outdent(); printer->Print( - "}\n\n"); + "}\n"); // ----------------------------------------------------------------- // Now generate the AddDescriptors() function. - PrintHandlingOptionalStaticInitializers( - file_, printer, - // With static initializers. - // Note that we don't need any special synchronization in the following code - // because it is called at static init time before any threads exist. + printer->Print( + "\n" "void $adddescriptorsname$() {\n" + // We don't need any special synchronization here because this code is + // called at static init time before any threads exist. " static bool already_here = false;\n" " if (already_here) return;\n" " already_here = true;\n" " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" "\n", - // Without. - "void $adddescriptorsname$_impl() {\n" - " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" - "\n", - // Vars. "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); - printer->Indent(); // Call the AddDescriptors() methods for all of our dependencies, to make @@ -560,12 +509,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dependency = file_->dependency(i); // Print the namespace prefix for the dependency. - string add_desc_name = QualifiedFileLevelSymbol( - dependency->package(), GlobalAddDescriptorsName(dependency->name())); + vector<string> dependency_package_parts; + SplitStringUsing(dependency->package(), ".", &dependency_package_parts); + printer->Print("::"); + for (int i = 0; i < dependency_package_parts.size(); i++) { + printer->Print("$name$::", + "name", dependency_package_parts[i]); + } // Call its AddDescriptors function. printer->Print( "$name$();\n", - "name", add_desc_name); + "name", GlobalAddDescriptorsName(dependency->name())); } if (HasDescriptorMethods(file_)) { @@ -584,12 +538,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { static const int kBytesPerLine = 40; for (int i = 0; i < file_data.size(); i += kBytesPerLine) { printer->Print("\n \"$data$\"", - "data", - EscapeTrigraphs( - CEscape(file_data.substr(i, kBytesPerLine)))); + "data", CEscape(file_data.substr(i, kBytesPerLine))); } printer->Print( - ", $size$);\n", + ", $size$);\n", "size", SimpleItoa(file_data.size())); // Call MessageFactory::InternalRegisterGeneratedFile(). @@ -617,26 +569,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "shutdownfilename", GlobalShutdownFileName(file_->name())); printer->Outdent(); + printer->Print( "}\n" - "\n"); - - PrintHandlingOptionalStaticInitializers( - file_, printer, - // With static initializers. + "\n" "// Force AddDescriptors() to be called at static initialization time.\n" "struct StaticDescriptorInitializer_$filename$ {\n" " StaticDescriptorInitializer_$filename$() {\n" " $adddescriptorsname$();\n" " }\n" - "} static_descriptor_initializer_$filename$_;\n", - // Without. - "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" - "void $adddescriptorsname$() {\n" - " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" - " &$adddescriptorsname$_impl);\n" - "}\n", - // Vars. + "} static_descriptor_initializer_$filename$_;\n" + "\n", "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename", FilenameIdentifier(file_->name())); } diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index 4e4d8b6..b4e0128 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,12 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ -#include <memory> #include <string> #include <vector> #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/cpp/cpp_field.h> -#include <google/protobuf/compiler/cpp/cpp_options.h> namespace google { namespace protobuf { @@ -63,7 +61,7 @@ class FileGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit FileGenerator(const FileDescriptor* file, - const Options& options); + const string& dllexport_decl); ~FileGenerator(); void GenerateHeader(io::Printer* printer); @@ -86,7 +84,8 @@ class FileGenerator { // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. vector<string> package_parts_; - const Options options_; + + string dllexport_decl_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index 75d558e..d67d350 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/cpp/cpp_generator.h> #include <vector> -#include <memory> #include <utility> #include <google/protobuf/compiler/cpp/cpp_file.h> @@ -54,7 +53,7 @@ CppGenerator::~CppGenerator() {} bool CppGenerator::Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error) const { vector<pair<string, string> > options; ParseGeneratorParameter(parameter, &options); @@ -79,13 +78,11 @@ bool CppGenerator::Generate(const FileDescriptor* file, // } // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or // __declspec(dllimport) depending on what is being compiled. - Options file_options; + string dllexport_decl; for (int i = 0; i < options.size(); i++) { if (options[i].first == "dllexport_decl") { - file_options.dllexport_decl = options[i].second; - } else if (options[i].first == "safe_boundary_check") { - file_options.safe_boundary_check = true; + dllexport_decl = options[i].second; } else { *error = "Unknown generator option: " + options[i].first; return false; @@ -98,12 +95,12 @@ bool CppGenerator::Generate(const FileDescriptor* file, string basename = StripProto(file->name()); basename.append(".pb"); - FileGenerator file_generator(file, file_options); + FileGenerator file_generator(file, dllexport_decl); // Generate header. { scoped_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".h")); + output_directory->Open(basename + ".h")); io::Printer printer(output.get(), '$'); file_generator.GenerateHeader(&printer); } @@ -111,7 +108,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate cc file. { scoped_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".cc")); + output_directory->Open(basename + ".cc")); io::Printer printer(output.get(), '$'); file_generator.GenerateSource(&printer); } diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h index 3d517cf..f52e886 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.h +++ b/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error) const; private: diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index b7a47ac..e3df88b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,12 +33,10 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <limits> -#include <map> #include <vector> #include <google/protobuf/stubs/hash.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> -#include <google/protobuf/io/printer.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> @@ -82,22 +80,6 @@ hash_set<string> MakeKeywordsMap() { hash_set<string> kKeywords = MakeKeywordsMap(); -// Returns whether the provided descriptor has an extension. This includes its -// nested types. -bool HasExtension(const Descriptor* descriptor) { - if (descriptor->extension_count() > 0) { - return true; - } - for (int i = 0; i < descriptor->nested_type_count(); ++i) { - if (HasExtension(descriptor->nested_type(i))) { - return true; - } - } - return false; -} - -} // namespace - string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. @@ -123,6 +105,8 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { return result; } +} // namespace + const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -148,7 +132,7 @@ string ClassName(const Descriptor* descriptor, bool qualified) { string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) { if (enum_descriptor->containing_type() == NULL) { if (qualified) { - return "::" + DotsToColons(enum_descriptor->full_name()); + return DotsToColons(enum_descriptor->full_name()); } else { return enum_descriptor->name(); } @@ -256,35 +240,14 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { return ""; } -string Int32ToString(int number) { - // gcc rejects the decimal form of kint32min. - if (number == kint32min) { - GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error); - return "(~0x7fffffff)"; - } else { - return SimpleItoa(number); - } -} - -string Int64ToString(int64 number) { - // gcc rejects the decimal form of kint64min - if (number == kint64min) { - // Make sure we are in a 2's complement system. - GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff), - kint64min_value_error); - return "GOOGLE_LONGLONG(~0x7fffffffffffffff)"; - } - return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")"; -} - string DefaultValue(const FieldDescriptor* field) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return Int32ToString(field->default_value_int32()); + return SimpleItoa(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: return SimpleItoa(field->default_value_uint32()) + "u"; case FieldDescriptor::CPPTYPE_INT64: - return Int64ToString(field->default_value_int64()); + return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")"; case FieldDescriptor::CPPTYPE_UINT64: return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; case FieldDescriptor::CPPTYPE_DOUBLE: { @@ -327,11 +290,9 @@ string DefaultValue(const FieldDescriptor* field) { return strings::Substitute( "static_cast< $0 >($1)", ClassName(field->enum_type(), true), - Int32ToString(field->default_value_enum()->number())); + field->default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - return "\"" + EscapeTrigraphs( - CEscape(field->default_value_string())) + - "\""; + return "\"" + CEscape(field->default_value_string()) + "\""; case FieldDescriptor::CPPTYPE_MESSAGE: return FieldMessageTypeName(field) + "::default_instance()"; } @@ -374,120 +335,6 @@ string GlobalShutdownFileName(const string& filename) { return "protobuf_ShutdownFile_" + FilenameIdentifier(filename); } -// Return the qualified C++ name for a file level symbol. -string QualifiedFileLevelSymbol(const string& package, const string& name) { - if (package.empty()) { - return StrCat("::", name); - } - return StrCat("::", DotsToColons(package), "::", name); -} - -// Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape) { - return StringReplace(to_escape, "?", "\\?", true); -} - -// Escaped function name to eliminate naming conflict. -string SafeFunctionName(const Descriptor* descriptor, - const FieldDescriptor* field, - const string& prefix) { - // Do not use FieldName() since it will escape keywords. - string name = field->name(); - LowerString(&name); - string function_name = prefix + name; - if (descriptor->FindFieldByName(function_name)) { - // Single underscore will also make it conflicting with the private data - // member. We use double underscore to escape function names. - function_name.append("__"); - } else if (kKeywords.count(name) > 0) { - // If the field name is a keyword, we append the underscore back to keep it - // consistent with other function names. - function_name.append("_"); - } - return function_name; -} - -bool StaticInitializersForced(const FileDescriptor* file) { - if (HasDescriptorMethods(file) || file->extension_count() > 0) { - return true; - } - for (int i = 0; i < file->message_type_count(); ++i) { - if (HasExtension(file->message_type(i))) { - return true; - } - } - return false; -} - -void PrintHandlingOptionalStaticInitializers( - const FileDescriptor* file, io::Printer* printer, - const char* with_static_init, const char* without_static_init, - const char* var1, const string& val1, - const char* var2, const string& val2) { - map<string, string> vars; - if (var1) { - vars[var1] = val1; - } - if (var2) { - vars[var2] = val2; - } - PrintHandlingOptionalStaticInitializers( - vars, file, printer, with_static_init, without_static_init); -} - -void PrintHandlingOptionalStaticInitializers( - const map<string, string>& vars, const FileDescriptor* file, - io::Printer* printer, const char* with_static_init, - const char* without_static_init) { - if (StaticInitializersForced(file)) { - printer->Print(vars, with_static_init); - } else { - printer->Print(vars, (string( - "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") + - without_static_init + - "#else\n" + - with_static_init + - "#endif\n").c_str()); - } -} - - -static bool HasEnumDefinitions(const Descriptor* message_type) { - if (message_type->enum_type_count() > 0) return true; - for (int i = 0; i < message_type->nested_type_count(); ++i) { - if (HasEnumDefinitions(message_type->nested_type(i))) return true; - } - return false; -} - -bool HasEnumDefinitions(const FileDescriptor* file) { - if (file->enum_type_count() > 0) return true; - for (int i = 0; i < file->message_type_count(); ++i) { - if (HasEnumDefinitions(file->message_type(i))) return true; - } - return false; -} - -bool IsStringOrMessage(const FieldDescriptor* field) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - case FieldDescriptor::CPPTYPE_INT64: - case FieldDescriptor::CPPTYPE_UINT32: - case FieldDescriptor::CPPTYPE_UINT64: - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_BOOL: - case FieldDescriptor::CPPTYPE_ENUM: - return false; - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_MESSAGE: - return true; - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 5d30240..f99b5fe 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,18 +35,12 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ -#include <map> #include <string> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> namespace google { namespace protobuf { - -namespace io { -class Printer; -} - namespace compiler { namespace cpp { @@ -103,12 +97,6 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type); // methods of WireFormat. For example, TYPE_INT32 becomes "Int32". const char* DeclaredTypeMethodName(FieldDescriptor::Type type); -// Return the code that evaluates to the number when compiled. -string Int32ToString(int number); - -// Return the code that evaluates to the number when compiled. -string Int64ToString(int64 number); - // Get code that evaluates to the field's default value. string DefaultValue(const FieldDescriptor* field); @@ -121,43 +109,27 @@ string GlobalAddDescriptorsName(const string& filename); // Return the name of the AssignDescriptors() function for a given file. string GlobalAssignDescriptorsName(const string& filename); -// Return the qualified C++ name for a file level symbol. -string QualifiedFileLevelSymbol(const string& package, const string& name); - // Return the name of the ShutdownFile() function for a given file. string GlobalShutdownFileName(const string& filename); -// Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape); - -// Escaped function name to eliminate naming conflict. -string SafeFunctionName(const Descriptor* descriptor, - const FieldDescriptor* field, - const string& prefix); - -// Do message classes in this file use UnknownFieldSet? -// Otherwise, messages will store unknown fields in a string -inline bool UseUnknownFieldSet(const FileDescriptor* file) { +// Do message classes in this file keep track of unknown fields? +inline bool HasUnknownFields(const FileDescriptor *file) { return file->options().optimize_for() != FileOptions::LITE_RUNTIME; } - -// Does this file have any enum type definitions? -bool HasEnumDefinitions(const FileDescriptor* file); - // Does this file have generated parsing, serialization, and other // standard methods for which reflection-based fallback implementations exist? -inline bool HasGeneratedMethods(const FileDescriptor* file) { +inline bool HasGeneratedMethods(const FileDescriptor *file) { return file->options().optimize_for() != FileOptions::CODE_SIZE; } -// Do message classes in this file have descriptor and reflection methods? -inline bool HasDescriptorMethods(const FileDescriptor* file) { +// Do message classes in this file have descriptor and refelction methods? +inline bool HasDescriptorMethods(const FileDescriptor *file) { return file->options().optimize_for() != FileOptions::LITE_RUNTIME; } // Should we generate generic services for this file? -inline bool HasGenericServices(const FileDescriptor* file) { +inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && file->options().optimize_for() != FileOptions::LITE_RUNTIME && file->options().cc_generic_services(); @@ -175,28 +147,6 @@ inline bool HasFastArraySerialization(const FileDescriptor* file) { return file->options().optimize_for() == FileOptions::SPEED; } -// Returns whether we have to generate code with static initializers. -bool StaticInitializersForced(const FileDescriptor* file); - -// Prints 'with_static_init' if static initializers have to be used for the -// provided file. Otherwise emits both 'with_static_init' and -// 'without_static_init' using #ifdef. -void PrintHandlingOptionalStaticInitializers( - const FileDescriptor* file, io::Printer* printer, - const char* with_static_init, const char* without_static_init, - const char* var1 = NULL, const string& val1 = "", - const char* var2 = NULL, const string& val2 = ""); - -void PrintHandlingOptionalStaticInitializers( - const map<string, string>& vars, const FileDescriptor* file, - io::Printer* printer, const char* with_static_init, - const char* without_static_init); - - -// Returns true if the field's CPPTYPE is string or message. -bool IsStringOrMessage(const FieldDescriptor* field); - -string UnderscoresToCamelCase(const string& input, bool cap_next_letter); } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 3a9d263..cbdcce8 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,9 +35,6 @@ #include <algorithm> #include <google/protobuf/stubs/hash.h> #include <map> -#include <memory> -#include <set> -#include <utility> #include <vector> #include <google/protobuf/compiler/cpp/cpp_message.h> #include <google/protobuf/compiler/cpp/cpp_field.h> @@ -50,7 +47,6 @@ #include <google/protobuf/wire_format.h> #include <google/protobuf/descriptor.pb.h> - namespace google { namespace protobuf { namespace compiler { @@ -76,6 +72,15 @@ struct FieldOrderingByNumber { } }; +const char* kWireTypeNames[] = { + "VARINT", + "FIXED64", + "LENGTH_DELIMITED", + "START_GROUP", + "END_GROUP", + "FIXED32", +}; + // Sort the fields of the given Descriptor by number into a new[]'d array // and return it. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { @@ -97,13 +102,6 @@ struct ExtensionRangeSorter { } }; -// Returns true if the "required" restriction check should be ignored for the -// given field. -inline static bool ShouldIgnoreRequiredFieldCheck( - const FieldDescriptor* field) { - return false; -} - // Returns true if the message type has any required fields. If it doesn't, // we can optimize out calls to its IsInitialized() method. // @@ -130,8 +128,7 @@ static bool HasRequiredFields( if (field->is_required()) { return true; } - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !ShouldIgnoreRequiredFieldCheck(field)) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (HasRequiredFields(field->message_type(), already_seen)) { return true; } @@ -146,171 +143,36 @@ static bool HasRequiredFields(const Descriptor* type) { return HasRequiredFields(type, &already_seen); } -// This returns an estimate of the compiler's alignment for the field. This -// can't guarantee to be correct because the generated code could be compiled on -// different systems with different alignment rules. The estimates below assume -// 64-bit pointers. -int EstimateAlignmentSize(const FieldDescriptor* field) { - if (field == NULL) return 0; - if (field->is_repeated()) return 8; - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_BOOL: - return 1; - - case FieldDescriptor::CPPTYPE_INT32: - case FieldDescriptor::CPPTYPE_UINT32: - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_FLOAT: - return 4; - - case FieldDescriptor::CPPTYPE_INT64: - case FieldDescriptor::CPPTYPE_UINT64: - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_MESSAGE: - return 8; - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; // Make compiler happy. -} - -// FieldGroup is just a helper for OptimizePadding below. It holds a vector of -// fields that are grouped together because they have compatible alignment, and -// a preferred location in the final field ordering. -class FieldGroup { - public: - FieldGroup() - : preferred_location_(0) {} - - // A group with a single field. - FieldGroup(float preferred_location, const FieldDescriptor* field) - : preferred_location_(preferred_location), - fields_(1, field) {} - - // Append the fields in 'other' to this group. - void Append(const FieldGroup& other) { - if (other.fields_.empty()) { - return; - } - // Preferred location is the average among all the fields, so we weight by - // the number of fields on each FieldGroup object. - preferred_location_ = - (preferred_location_ * fields_.size() + - (other.preferred_location_ * other.fields_.size())) / - (fields_.size() + other.fields_.size()); - fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); - } - - void SetPreferredLocation(float location) { preferred_location_ = location; } - const vector<const FieldDescriptor*>& fields() const { return fields_; } - - // FieldGroup objects sort by their preferred location. - bool operator<(const FieldGroup& other) const { - return preferred_location_ < other.preferred_location_; - } - - private: - // "preferred_location_" is an estimate of where this group should go in the - // final list of fields. We compute this by taking the average index of each - // field in this group in the original ordering of fields. This is very - // approximate, but should put this group close to where its member fields - // originally went. - float preferred_location_; - vector<const FieldDescriptor*> fields_; - // We rely on the default copy constructor and operator= so this type can be - // used in a vector. -}; - -// Reorder 'fields' so that if the fields are output into a c++ class in the new -// order, the alignment padding is minimized. We try to do this while keeping -// each field as close as possible to its original position so that we don't -// reduce cache locality much for function that access each field in order. -void OptimizePadding(vector<const FieldDescriptor*>* fields) { - // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. - vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8; - for (int i = 0; i < fields->size(); ++i) { - switch (EstimateAlignmentSize((*fields)[i])) { - case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; - case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; - case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; - default: - GOOGLE_LOG(FATAL) << "Unknown alignment size."; - } - } - - // Now group fields aligned to 1 byte into sets of 4, and treat those like a - // single field aligned to 4 bytes. - for (int i = 0; i < aligned_to_1.size(); i += 4) { - FieldGroup field_group; - for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { - field_group.Append(aligned_to_1[j]); - } - aligned_to_4.push_back(field_group); - } - // Sort by preferred location to keep fields as close to their original - // location as possible. Using stable_sort ensures that the output is - // consistent across runs. - stable_sort(aligned_to_4.begin(), aligned_to_4.end()); - - // Now group fields aligned to 4 bytes (or the 4-field groups created above) - // into pairs, and treat those like a single field aligned to 8 bytes. - for (int i = 0; i < aligned_to_4.size(); i += 2) { - FieldGroup field_group; - for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { - field_group.Append(aligned_to_4[j]); - } - if (i == aligned_to_4.size() - 1) { - // Move incomplete 4-byte block to the end. - field_group.SetPreferredLocation(fields->size() + 1); - } - aligned_to_8.push_back(field_group); - } - // Sort by preferred location. - stable_sort(aligned_to_8.begin(), aligned_to_8.end()); - - // Now pull out all the FieldDescriptors in order. - fields->clear(); - for (int i = 0; i < aligned_to_8.size(); ++i) { - fields->insert(fields->end(), - aligned_to_8[i].fields().begin(), - aligned_to_8[i].fields().end()); - } -} - -string MessageTypeProtoName(const FieldDescriptor* field) { - return field->message_type()->full_name(); -} - } // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor, - const Options& options) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), - options_(options), - field_generators_(descriptor, options), - nested_generators_(new scoped_ptr< - MessageGenerator>[descriptor->nested_type_count()]), - enum_generators_( - new scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]), - extension_generators_(new scoped_ptr< - ExtensionGenerator>[descriptor->extension_count()]) { + const string& dllexport_decl) + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + dllexport_decl_(dllexport_decl), + field_generators_(descriptor), + nested_generators_(new scoped_ptr<MessageGenerator>[ + descriptor->nested_type_count()]), + enum_generators_(new scoped_ptr<EnumGenerator>[ + descriptor->enum_type_count()]), + extension_generators_(new scoped_ptr<ExtensionGenerator>[ + descriptor->extension_count()]) { for (int i = 0; i < descriptor->nested_type_count(); i++) { nested_generators_[i].reset( - new MessageGenerator(descriptor->nested_type(i), options)); + new MessageGenerator(descriptor->nested_type(i), dllexport_decl)); } for (int i = 0; i < descriptor->enum_type_count(); i++) { enum_generators_[i].reset( - new EnumGenerator(descriptor->enum_type(i), options)); + new EnumGenerator(descriptor->enum_type(i), dllexport_decl)); } for (int i = 0; i < descriptor->extension_count(); i++) { extension_generators_[i].reset( - new ExtensionGenerator(descriptor->extension(i), options)); + new ExtensionGenerator(descriptor->extension(i), dllexport_decl)); } } @@ -355,7 +217,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { PrintFieldComment(printer, field); map<string, string> vars; - SetCommonFieldVariables(field, &vars, options_); + SetCommonFieldVariables(field, &vars); vars["constant_name"] = FieldConstantName(field); if (field->is_repeated()) { @@ -380,14 +242,6 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", "classname", classname_); } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "inline $camel_oneof_name$Case $oneof_name$_case() const;\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), - "oneof_name", descriptor_->oneof_decl(i)->name()); - } } void MessageGenerator:: @@ -400,7 +254,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { PrintFieldComment(printer, field); map<string, string> vars; - SetCommonFieldVariables(field, &vars, options_); + SetCommonFieldVariables(field, &vars); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { @@ -408,34 +262,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); - } else if (field->containing_oneof()) { - // Singular field in a oneof - vars["field_name"] = UnderscoresToCamelCase(field->name(), true); - vars["oneof_name"] = field->containing_oneof()->name(); - vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); - printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" - "}\n" - "inline void $classname$::set_has_$name$() {\n" - " _oneof_case_[$oneof_index$] = k$field_name$;\n" - "}\n"); } else { // Singular field. - char buffer[kFastToBufferSize]; - vars["has_array_index"] = SimpleItoa(field->index() / 32); - vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); printer->Print(vars, "inline bool $classname$::has_$name$() const {\n" - " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" - "}\n" - "inline void $classname$::set_has_$name$() {\n" - " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" - "}\n" - "inline void $classname$::clear_has_$name$() {\n" - " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" - "}\n" - ); + " return _has_bit($index$);\n" + "}\n"); } // Generate clear_$name$() @@ -443,27 +275,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline void $classname$::clear_$name$() {\n"); printer->Indent(); + field_generators_.get(field).GenerateClearingCode(printer); + printer->Outdent(); - if (field->containing_oneof()) { - // Clear this field only if it is the active field in this oneof, - // otherwise ignore - printer->Print(vars, - "if (has_$name$()) {\n"); - printer->Indent(); - field_generators_.get(field).GenerateClearingCode(printer); - printer->Print(vars, - "clear_has_$oneof_name$();\n"); - printer->Outdent(); - printer->Print("}\n"); - } else { - field_generators_.get(field).GenerateClearingCode(printer); - if (!field->is_repeated()) { - printer->Print(vars, - "clear_has_$name$();\n"); - } + if (!field->is_repeated()) { + printer->Print(vars, " _clear_bit($index$);\n"); } - printer->Outdent(); printer->Print("}\n"); // Generate type-specific accessors. @@ -471,49 +289,6 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Print("\n"); } - - // Generate has_$name$() and clear_has_$name$() functions for oneofs - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - map<string, string> vars; - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - vars["cap_oneof_name"] = - ToUpper(descriptor_->oneof_decl(i)->name()); - vars["classname"] = classname_; - printer->Print( - vars, - "inline bool $classname$::has_$oneof_name$() {\n" - " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" - "}\n" - "inline void $classname$::clear_has_$oneof_name$() {\n" - " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" - "}\n"); - } -} - -// Helper for the code that emits the Clear() method. -static bool CanClearByZeroing(const FieldDescriptor* field) { - if (field->is_repeated() || field->is_extension()) return false; - switch (field->cpp_type()) { - case internal::WireFormatLite::CPPTYPE_ENUM: - return field->default_value_enum()->number() == 0; - case internal::WireFormatLite::CPPTYPE_INT32: - return field->default_value_int32() == 0; - case internal::WireFormatLite::CPPTYPE_INT64: - return field->default_value_int64() == 0; - case internal::WireFormatLite::CPPTYPE_UINT32: - return field->default_value_uint32() == 0; - case internal::WireFormatLite::CPPTYPE_UINT64: - return field->default_value_uint64() == 0; - case internal::WireFormatLite::CPPTYPE_FLOAT: - return field->default_value_float() == 0; - case internal::WireFormatLite::CPPTYPE_DOUBLE: - return field->default_value_double() == 0; - case internal::WireFormatLite::CPPTYPE_BOOL: - return field->default_value_bool() == false; - default: - return false; - } } void MessageGenerator:: @@ -528,11 +303,10 @@ GenerateClassDefinition(io::Printer* printer) { map<string, string> vars; vars["classname"] = classname_; vars["field_count"] = SimpleItoa(descriptor_->field_count()); - vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); - if (options_.dllexport_decl.empty()) { + if (dllexport_decl_.empty()) { vars["dllexport"] = ""; } else { - vars["dllexport"] = options_.dllexport_decl + " "; + vars["dllexport"] = dllexport_decl_ + " "; } vars["superclass"] = SuperClassName(descriptor_); @@ -553,7 +327,7 @@ GenerateClassDefinition(io::Printer* printer) { "}\n" "\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print( "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" " return _unknown_fields_;\n" @@ -563,16 +337,6 @@ GenerateClassDefinition(io::Printer* printer) { " return &_unknown_fields_;\n" "}\n" "\n"); - } else { - printer->Print( - "inline const ::std::string& unknown_fields() const {\n" - " return _unknown_fields_;\n" - "}\n" - "\n" - "inline ::std::string* mutable_unknown_fields() {\n" - " return &_unknown_fields_;\n" - "}\n" - "\n"); } // Only generate this member if it's not disabled. @@ -586,47 +350,6 @@ GenerateClassDefinition(io::Printer* printer) { "static const $classname$& default_instance();\n" "\n"); - // Generate enum values for every field in oneofs. One list is generated for - // each oneof with an additional *_NOT_SET value. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "enum $camel_oneof_name$Case {\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - printer->Print( - "k$field_name$ = $field_number$,\n", - "field_name", - UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->field(j)->name(), true), - "field_number", - SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); - } - printer->Print( - "$cap_oneof_name$_NOT_SET = 0,\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "};\n" - "\n"); - } - - if (!StaticInitializersForced(descriptor_->file())) { - printer->Print(vars, - "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" - "// Returns the internal default instance pointer. This function can\n" - "// return NULL thus should not be used by the user. This is intended\n" - "// for Protobuf internal code. Please use default_instance() declared\n" - "// above instead.\n" - "static inline const $classname$* internal_default_instance() {\n" - " return default_instance_;\n" - "}\n" - "#endif\n" - "\n"); - } - printer->Print(vars, "void Swap($classname$* other);\n" @@ -656,50 +379,20 @@ GenerateClassDefinition(io::Printer* printer) { " ::google::protobuf::io::CodedInputStream* input);\n" "void SerializeWithCachedSizes(\n" " ::google::protobuf::io::CodedOutputStream* output) const;\n"); - // DiscardUnknownFields() is implemented in message.cc using reflections. We - // need to implement this function in generated code for messages. - if (!UseUnknownFieldSet(descriptor_->file())) { - printer->Print( - "void DiscardUnknownFields();\n"); - } if (HasFastArraySerialization(descriptor_->file())) { printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } } - // Check all FieldDescriptors including those in oneofs to estimate - // whether ::std::string is likely to be used, and depending on that - // estimate, set uses_string_ to true or false. That contols - // whether to force initialization of empty_string_ in SharedCtor(). - // It's often advantageous to do so to keep "is empty_string_ - // inited?" code from appearing all over the place. - vector<const FieldDescriptor*> descriptors; - for (int i = 0; i < descriptor_->field_count(); i++) { - descriptors.push_back(descriptor_->field(i)); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - descriptors.push_back(descriptor_->oneof_decl(i)->field(j)); - } - } - uses_string_ = false; - for (int i = 0; i < descriptors.size(); i++) { - const FieldDescriptor* field = descriptors[i]; - if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - switch (field->options().ctype()) { - default: uses_string_ = true; break; - } - } - } - - printer->Print( + printer->Print(vars, "int GetCachedSize() const { return _cached_size_; }\n" "private:\n" "void SharedCtor();\n" "void SharedDtor();\n" "void SetCachedSize(int size) const;\n" - "public:\n"); + "public:\n" + "\n"); if (HasDescriptorMethods(descriptor_->file())) { printer->Print( @@ -751,172 +444,38 @@ GenerateClassDefinition(io::Printer* printer) { "// @@protoc_insertion_point(class_scope:$full_name$)\n", "full_name", descriptor_->full_name()); - // Generate private members. + // Generate private members for fields. printer->Outdent(); printer->Print(" private:\n"); printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->is_repeated()) { - printer->Print( - "inline void set_has_$name$();\n", - "name", FieldName(descriptor_->field(i))); - if (!descriptor_->field(i)->containing_oneof()) { - printer->Print( - "inline void clear_has_$name$();\n", - "name", FieldName(descriptor_->field(i))); - } - } - } - printer->Print("\n"); - - // Generate oneof function declarations - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "inline bool has_$oneof_name$();\n" - "void clear_$oneof_name$();\n" - "inline void clear_has_$oneof_name$();\n\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - } - - // Prepare decls for _cached_size_ and _has_bits_. Their position in the - // output will be determined later. - - bool need_to_emit_cached_size = true; - // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. - const string cached_size_decl = "mutable int _cached_size_;\n"; - - // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. - size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; - if (descriptor_->field_count() == 0) { - // Zero-size arrays aren't technically allowed, and MSVC in particular - // doesn't like them. We still need to declare these arrays to make - // other code compile. Since this is an uncommon case, we'll just declare - // them with size 1 and waste some space. Oh well. - sizeof_has_bits = 4; - } - const string has_bits_decl = sizeof_has_bits == 0 ? "" : - "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n"; - - - // To minimize padding, data members are divided into three sections: - // (1) members assumed to align to 8 bytes - // (2) members corresponding to message fields, re-ordered to optimize - // alignment. - // (3) members assumed to align to 4 bytes. - - // Members assumed to align to 8 bytes: - if (descriptor_->extension_range_count() > 0) { printer->Print( - "::google::protobuf::internal::ExtensionSet _extensions_;\n" - "\n"); + "::google::protobuf::internal::ExtensionSet _extensions_;\n"); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print( - "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" - "\n"); - } else { - printer->Print( - "::std::string _unknown_fields_;\n" - "\n"); - } - - // _has_bits_ is frequently accessed, so to reduce code size and improve - // speed, it should be close to the start of the object. But, try not to - // waste space:_has_bits_ by itself always makes sense if its size is a - // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together - // will work well. - printer->Print(has_bits_decl.c_str()); - if ((sizeof_has_bits % 8) != 0) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"); } - // Field members: - - // List fields which doesn't belong to any oneof - vector<const FieldDescriptor*> fields; - hash_map<string, int> fieldname_to_chunk; + // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. + printer->Print( + "mutable int _cached_size_;\n" + "\n"); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - const FieldDescriptor* field = descriptor_->field(i); - fields.push_back(field); - fieldname_to_chunk[FieldName(field)] = i / 8; - } - } - OptimizePadding(&fields); - // Emit some private and static members - runs_of_fields_ = vector< vector<string> >(1); - for (int i = 0; i < fields.size(); ++i) { - const FieldDescriptor* field = fields[i]; - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateStaticMembers(printer); - generator.GeneratePrivateMembers(printer); - if (CanClearByZeroing(field)) { - const string& fieldname = FieldName(field); - if (!runs_of_fields_.back().empty() && - (fieldname_to_chunk[runs_of_fields_.back().back()] != - fieldname_to_chunk[fieldname])) { - runs_of_fields_.push_back(vector<string>()); - } - runs_of_fields_.back().push_back(fieldname); - } else if (!runs_of_fields_.back().empty()) { - runs_of_fields_.push_back(vector<string>()); - } - } - - // For each oneof generate a union - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "union $camel_oneof_name$Union {\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GeneratePrivateMembers(printer); - } - printer->Outdent(); - printer->Print( - "} $oneof_name$_;\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GenerateStaticMembers(printer); - } - } - - // Members assumed to align to 4 bytes: - - if (need_to_emit_cached_size) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } - - // Generate _oneof_case_. - if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" - "\n"); + field_generators_.get(descriptor_->field(i)) + .GeneratePrivateMembers(printer); } // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as // friends so that they can access private static variables like // default_instance_ and reflection_. - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. + printer->Print( "friend void $dllexport_decl$ $adddescriptorsname$();\n", - // Without. - "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", - // Vars. - "dllexport_decl", options_.dllexport_decl, + "dllexport_decl", dllexport_decl_, "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); - + GlobalAddDescriptorsName(descriptor_->file()->name())); printer->Print( "friend void $assigndescriptorsname$();\n" "friend void $shutdownfilename$();\n" @@ -925,14 +484,38 @@ GenerateClassDefinition(io::Printer* printer) { GlobalAssignDescriptorsName(descriptor_->file()->name()), "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); + // Generate offsets and _has_bits_ boilerplate. + if (descriptor_->field_count() > 0) { + printer->Print(vars, + "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"); + } else { + // Zero-size arrays aren't technically allowed, and MSVC in particular + // doesn't like them. We still need to declare these arrays to make + // other code compile. Since this is an uncommon case, we'll just declare + // them with size 1 and waste some space. Oh well. + printer->Print( + "::google::protobuf::uint32 _has_bits_[1];\n"); + } + printer->Print( + "\n" + "// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n" + "inline bool _has_bit(int index) const {\n" + " return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n" + "}\n" + "inline void _set_bit(int index) {\n" + " _has_bits_[index / 32] |= (1u << (index % 32));\n" + "}\n" + "inline void _clear_bit(int index) {\n" + " _has_bits_[index / 32] &= ~(1u << (index % 32));\n" + "}\n" + "\n" "void InitAsDefaultInstance();\n" "static $classname$* default_instance_;\n", "classname", classname_); printer->Outdent(); printer->Print(vars, "};"); - GOOGLE_DCHECK(!need_to_emit_cached_size); } void MessageGenerator:: @@ -944,23 +527,6 @@ GenerateInlineMethods(io::Printer* printer) { } GenerateFieldAccessorDefinitions(printer); - - // Generate oneof_case() functions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - map<string, string> vars; - vars["class_name"] = classname_; - vars["camel_oneof_name"] = UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->name(), true); - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - printer->Print( - vars, - "inline $class_name$::$camel_oneof_name$Case $class_name$::" - "$oneof_name$_case() const {\n" - " return $class_name$::$camel_oneof_name$Case(" - "_oneof_case_[$oneof_index$]);\n" - "}\n"); - } } void MessageGenerator:: @@ -971,25 +537,6 @@ GenerateDescriptorDeclarations(io::Printer* printer) { " $name$_reflection_ = NULL;\n", "name", classname_); - // Generate oneof default instance for reflection usage. - if (descriptor_->oneof_decl_count() > 0) { - printer->Print("struct $name$OneofInstance {\n", - "name", classname_); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print(" "); - if (IsStringOrMessage(field)) { - printer->Print("const "); - } - field_generators_.get(field).GeneratePrivateMembers(printer); - } - } - - printer->Print("}* $name$_default_oneof_instance_ = NULL;\n", - "name", classname_); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDescriptorDeclarations(printer); } @@ -1042,19 +589,9 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { printer->Print(vars, " -1,\n"); } - - if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - " $classname$_default_oneof_instance_,\n" - " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "$classname$, _oneof_case_[0]),\n"); - } - - printer->Print( - " ::google::protobuf::DescriptorPool::generated_pool(),\n"); - printer->Print(vars, - " ::google::protobuf::MessageFactory::generated_factory(),\n"); printer->Print(vars, + " ::google::protobuf::DescriptorPool::generated_pool(),\n" + " ::google::protobuf::MessageFactory::generated_factory(),\n" " sizeof($classname$));\n"); // Handle nested types. @@ -1083,13 +620,6 @@ GenerateTypeRegistrations(io::Printer* printer) { void MessageGenerator:: GenerateDefaultInstanceAllocator(io::Printer* printer) { - // Construct the default instances of all fields, as they will be used - // when creating the default instance of the entire message. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDefaultInstanceAllocator(printer); - } - // Construct the default instance. We can't call InitAsDefaultInstance() yet // because we need to make sure all default instances that this one might // depend on are constructed first. @@ -1097,13 +627,6 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) { "$classname$::default_instance_ = new $classname$();\n", "classname", classname_); - if ((descriptor_->oneof_decl_count() > 0) && - HasDescriptorMethods(descriptor_->file())) { - printer->Print( - "$classname$_default_oneof_instance_ = new $classname$OneofInstance;\n", - "classname", classname_); - } - // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); @@ -1135,22 +658,11 @@ GenerateShutdownCode(io::Printer* printer) { "classname", classname_); if (HasDescriptorMethods(descriptor_->file())) { - if (descriptor_->oneof_decl_count() > 0) { - printer->Print( - "delete $classname$_default_oneof_instance_;\n", - "classname", classname_); - } printer->Print( "delete $classname$_reflection_;\n", "classname", classname_); } - // Handle default instances of fields. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateShutdownCode(printer); - } - // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateShutdownCode(printer); @@ -1197,11 +709,6 @@ GenerateClassMethods(io::Printer* printer) { GenerateStructors(printer); printer->Print("\n"); - if (descriptor_->oneof_decl_count() > 0) { - GenerateOneofClear(printer); - printer->Print("\n"); - } - if (HasGeneratedMethods(descriptor_->file())) { GenerateClear(printer); printer->Print("\n"); @@ -1261,33 +768,15 @@ GenerateOffsets(io::Printer* printer) { printer->Print( "static const int $classname$_offsets_[$field_count$] = {\n", "classname", classname_, - "field_count", SimpleItoa(max( - 1, descriptor_->field_count() + descriptor_->oneof_decl_count()))); + "field_count", SimpleItoa(max(1, descriptor_->field_count()))); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof()) { - printer->Print( - "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" - "$classname$_default_oneof_instance_, $name$_),\n", - "classname", classname_, - "name", FieldName(field)); - } else { - printer->Print( - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "$name$_),\n", - "classname", classname_, - "name", FieldName(field)); - } - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); printer->Print( "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", "classname", classname_, - "name", oneof->name()); + "name", FieldName(field)); } printer->Outdent(); @@ -1301,26 +790,17 @@ GenerateSharedConstructorCode(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print(StrCat( - uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", - "_cached_size_ = 0;\n").c_str()); + printer->Print( + "_cached_size_ = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); - } + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); } printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_has_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - } - printer->Outdent(); printer->Print("}\n\n"); } @@ -1331,29 +811,14 @@ GenerateSharedDestructorCode(io::Printer* printer) { "void $classname$::SharedDtor() {\n", "classname", classname_); printer->Indent(); - // Write the destructors for each field except oneof members. + // Write the destructors for each field. for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateDestructorCode(printer); - } - } - - // Generate code to destruct oneofs. Clearing should do the work. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" - "}\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + field_generators_.get(descriptor_->field(i)) + .GenerateDestructorCode(printer); } - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - "if (this != default_instance_) {\n", - // Without. - "if (this != &default_instance()) {\n"); + printer->Print( + "if (this != default_instance_) {\n"); // We need to delete all embedded messages. // TODO(kenton): If we make unset messages point at default instances @@ -1364,12 +829,8 @@ GenerateSharedDestructorCode(io::Printer* printer) { if (!field->is_repeated() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Skip oneof members - if (!field->containing_oneof()) { - printer->Print( - " delete $name$_;\n", - "name", FieldName(field)); - } + printer->Print(" delete $name$_;\n", + "name", FieldName(field)); } } @@ -1389,11 +850,9 @@ GenerateStructors(io::Printer* printer) { "$classname$::$classname$()\n" " : $superclass$() {\n" " SharedCtor();\n" - " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", "classname", classname_, - "superclass", superclass, - "full_name", descriptor_->full_name()); + "superclass", superclass); printer->Print( "\n" @@ -1410,28 +869,11 @@ GenerateStructors(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - (field->containing_oneof() == NULL || - HasDescriptorMethods(descriptor_->file()))) { - string name; - if (field->containing_oneof()) { - name = classname_ + "_default_oneof_instance_->"; - } - name += FieldName(field); - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", - // Without. - " $name$_ = const_cast< $type$*>(\n" - " $type$::internal_default_instance());\n", - // Vars. - "name", name, - "type", FieldMessageTypeName(field)); - } else if (field->containing_oneof() && - HasDescriptorMethods(descriptor_->file())) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", + "name", FieldName(field), + "type", FieldMessageTypeName(field)); } } printer->Print( @@ -1444,12 +886,10 @@ GenerateStructors(io::Printer* printer) { " : $superclass$() {\n" " SharedCtor();\n" " MergeFrom(from);\n" - " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" "}\n" "\n", "classname", classname_, - "superclass", superclass, - "full_name", descriptor_->full_name()); + "superclass", superclass); // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -1457,12 +897,10 @@ GenerateStructors(io::Printer* printer) { // Generate the destructor. printer->Print( "$classname$::~$classname$() {\n" - " // @@protoc_insertion_point(destructor:$full_name$)\n" " SharedDtor();\n" "}\n" "\n", - "classname", classname_, - "full_name", descriptor_->full_name()); + "classname", classname_); // Generate the shared destructor code. GenerateSharedDestructorCode(printer); @@ -1491,43 +929,20 @@ GenerateStructors(io::Printer* printer) { } printer->Print( - "const $classname$& $classname$::default_instance() {\n", - "classname", classname_); - - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " if (default_instance_ == NULL) $adddescriptorsname$();\n", - // Without. - " $adddescriptorsname$();\n", - // Vars. - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); - - printer->Print( + "const $classname$& $classname$::default_instance() {\n" + " if (default_instance_ == NULL) $adddescriptorsname$();" " return *default_instance_;\n" "}\n" "\n" "$classname$* $classname$::default_instance_ = NULL;\n" - "\n", - "classname", classname_); - - printer->Print( + "\n" "$classname$* $classname$::New() const {\n" " return new $classname$;\n" "}\n", - "classname", classname_); - -} + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); -// Return the number of bits set in n, a non-negative integer. -static int popcnt(uint32 n) { - int result = 0; - while (n != 0) { - result += (n & 1); - n = n / 2; - } - return result; } void MessageGenerator:: @@ -1536,133 +951,64 @@ GenerateClear(io::Printer* printer) { "classname", classname_); printer->Indent(); - // Step 1: Extensions + int last_index = -1; + if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Clear();\n"); } - // Step 2: Everything but extensions, repeateds, unions. - // These are handled in chunks of 8. The first chunk is - // the non-extensions-non-repeateds-non-unions in - // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), - // and the second chunk is the same for - // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), - // etc. - set<int> step2_indices; - hash_map<string, int> fieldname_to_chunk; - hash_map<int, string> memsets_for_chunk; - hash_map<int, int> memset_field_count_for_chunk; - hash_set<string> handled; // fields that appear anywhere in memsets_for_chunk - hash_map<int, uint32> fields_mask_for_chunk; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated() && !field->containing_oneof()) { - step2_indices.insert(i); - int chunk = i / 8; - fieldname_to_chunk[FieldName(field)] = chunk; - fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32); - } - } - // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. - // The generated code uses two macros to help it clear runs of fields: - // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message. - // ZR_ zeroes a non-empty range of fields via memset. - const char* macros = - "#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \\\n" - " &reinterpret_cast<$classname$*>(16)->f) - \\\n" - " reinterpret_cast<char*>(16))\n\n" - "#define ZR_(first, last) do { \\\n" - " size_t f = OFFSET_OF_FIELD_(first); \\\n" - " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n" - " ::memset(&first, 0, n); \\\n" - " } while (0)\n\n"; - for (int i = 0; i < runs_of_fields_.size(); i++) { - const vector<string>& run = runs_of_fields_[i]; - if (run.size() < 2) continue; - const string& first_field_name = run[0]; - const string& last_field_name = run.back(); - int chunk = fieldname_to_chunk[run[0]]; - memsets_for_chunk[chunk].append( - "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n"); - for (int j = 0; j < run.size(); j++) { - GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]); - handled.insert(run[j]); - } - memset_field_count_for_chunk[chunk] += run.size(); - } - const bool macros_are_needed = handled.size() > 0; - if (macros_are_needed) { - printer->Outdent(); - printer->Print(macros, - "classname", classname_); - printer->Indent(); - } - // Step 2b: Finish step 2, ignoring fields handled in step 2a. - int last_index = -1; - bool chunk_block_in_progress = false; - for (int i = 0; i < descriptor_->field_count(); i++) { - if (step2_indices.count(i) == 0) continue; - const FieldDescriptor* field = descriptor_->field(i); - const string fieldname = FieldName(field); - if (i / 8 != last_index / 8 || last_index < 0) { - // End previous chunk, if there was one. - if (chunk_block_in_progress) { - printer->Outdent(); - printer->Print("}\n"); - chunk_block_in_progress = false; + if (!field->is_repeated()) { + map<string, string> vars; + vars["index"] = SimpleItoa(field->index()); + + // We can use the fact that _has_bits_ is a giant bitfield to our + // advantage: We can check up to 32 bits at a time for equality to + // zero, and skip the whole range if so. This can improve the speed + // of Clear() for messages which contain a very large number of + // optional fields of which only a few are used at a time. Here, + // we've chosen to check 8 bits at a time rather than 32. + if (i / 8 != last_index / 8 || last_index < 0) { + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print(vars, + "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); + printer->Indent(); } - // Start chunk. - const string& memsets = memsets_for_chunk[i / 8]; - uint32 mask = fields_mask_for_chunk[i / 8]; - int count = popcnt(mask); - if (count == 1 || - (count <= 4 && count == memset_field_count_for_chunk[i / 8])) { - // No "if" here because the chunk is trivial. - } else { - printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$) {\n", - "index", SimpleItoa(i / 8 * 8), - "mask", SimpleItoa(mask)); + last_index = i; + + // It's faster to just overwrite primitive types, but we should + // only clear strings and messages if they were set. + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; + + if (should_check_bit) { + printer->Print(vars, "if (_has_bit($index$)) {\n"); printer->Indent(); - chunk_block_in_progress = true; } - printer->Print(memsets.c_str()); - } - last_index = i; - if (handled.count(fieldname) > 0) continue; - - // It's faster to just overwrite primitive types, but we should - // only clear strings and messages if they were set. - // TODO(kenton): Let the CppFieldGenerator decide this somehow. - bool should_check_bit = - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; - - if (should_check_bit) { - printer->Print("if (has_$name$()) {\n", "name", fieldname); - printer->Indent(); - } - field_generators_.get(field).GenerateClearingCode(printer); + field_generators_.get(field).GenerateClearingCode(printer); - if (should_check_bit) { - printer->Outdent(); - printer->Print("}\n"); + if (should_check_bit) { + printer->Outdent(); + printer->Print("}\n"); + } } } - if (chunk_block_in_progress) { + if (last_index >= 0) { printer->Outdent(); printer->Print("}\n"); } - if (macros_are_needed) { - printer->Outdent(); - printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n"); - printer->Indent(); - } - // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here. + // Repeated fields don't use _has_bits_ so we clear them in a separate + // pass. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -1671,23 +1017,12 @@ GenerateClear(io::Printer* printer) { } } - // Step 4: Unions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - } - - // Step 5: Everything else. printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->Clear();\n"); - } else { - printer->Print( - "mutable_unknown_fields()->clear();\n"); } printer->Outdent(); @@ -1695,58 +1030,6 @@ GenerateClear(io::Printer* printer) { } void MessageGenerator:: -GenerateOneofClear(io::Printer* printer) { - // Generated function clears the active field and union case (e.g. foo_case_). - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "void $classname$::clear_$oneofname$() {\n", - "classname", classname_, - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - printer->Print( - "switch($oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - // We clear only allocated objects in oneofs - if (!IsStringOrMessage(field)) { - printer->Print( - "// No need to clear\n"); - } else { - field_generators_.get(field).GenerateClearingCode(printer); - } - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n" - "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", - "oneof_index", SimpleItoa(i), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); - } -} - -void MessageGenerator:: GenerateSwap(io::Printer* printer) { // Generate the Swap member function. printer->Print("void $classname$::Swap($classname$* other) {\n", @@ -1761,23 +1044,13 @@ GenerateSwap(io::Printer* printer) { field_generators_.get(field).GenerateSwappingCode(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "std::swap($oneof_name$_, other->$oneof_name$_);\n" - "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", - "oneof_name", descriptor_->oneof_decl(i)->name(), - "i", SimpleItoa(i)); - } - for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", "i", SimpleItoa(i)); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); - } else { - printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n"); } printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { @@ -1849,60 +1122,31 @@ GenerateMergeFrom(io::Printer* printer) { } } - // Merge oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); - } - // Merge Optional and Required fields (after a _has_bit check). int last_index = -1; for (int i = 0; i < descriptor_->field_count(); ++i) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated() && !field->containing_oneof()) { + if (!field->is_repeated()) { + map<string, string> vars; + vars["index"] = SimpleItoa(field->index()); + // See above in GenerateClear for an explanation of this. if (i / 8 != last_index / 8 || last_index < 0) { if (last_index >= 0) { printer->Outdent(); printer->Print("}\n"); } - printer->Print( - "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", - "index", SimpleItoa(field->index())); + printer->Print(vars, + "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); printer->Indent(); } last_index = i; - printer->Print( - "if (from.has_$name$()) {\n", - "name", FieldName(field)); + printer->Print(vars, + "if (from._has_bit($index$)) {\n"); printer->Indent(); field_generators_.get(field).GenerateMergingCode(printer); @@ -1921,12 +1165,9 @@ GenerateMergeFrom(io::Printer* printer) { printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); - } else { - printer->Print( - "mutable_unknown_fields()->append(from.unknown_fields());\n"); } printer->Outdent(); @@ -1973,61 +1214,25 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Special-case MessageSet. printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n", - "classname", classname_); - - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. + " ::google::protobuf::io::CodedInputStream* input) {\n" " return _extensions_.ParseMessageSet(input, default_instance_,\n" - " mutable_unknown_fields());\n", - // Without. - " return _extensions_.ParseMessageSet(input, &default_instance(),\n" - " mutable_unknown_fields());\n", - // Vars. + " mutable_unknown_fields());\n" + "}\n", "classname", classname_); - - printer->Print( - "}\n"); return; } printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" - "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n" - " ::google::protobuf::uint32 tag;\n", + "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n" + " ::google::protobuf::uint32 tag;\n" + " while ((tag = input->ReadTag()) != 0) {\n", "classname", classname_); - if (!UseUnknownFieldSet(descriptor_->file())) { - printer->Print( - " ::google::protobuf::io::StringOutputStream unknown_fields_string(\n" - " mutable_unknown_fields());\n" - " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" - " &unknown_fields_string);\n"); - } - - printer->Print( - " // @@protoc_insertion_point(parse_start:$full_name$)\n", - "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Print("for (;;) {\n"); printer->Indent(); - scoped_array<const FieldDescriptor*> ordered_fields( - SortFieldsByNumber(descriptor_)); - uint32 maxtag = descriptor_->field_count() == 0 ? 0 : - WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); - const int kCutoff0 = 127; // fits in 1-byte varint - const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint - printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " - "input->ReadTagWithCutoff($max$);\n" - "tag = p.first;\n" - "if (!p.second) goto handle_unusual;\n", - "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : - (maxtag <= kCutoff1 ? kCutoff1 : - maxtag))); if (descriptor_->field_count() > 0) { // We don't even want to print the switch() if we have no fields because // MSVC dislikes switch() statements that contain only a default value. @@ -2037,11 +1242,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // of each case. However, this is actually a bit slower in practice as it // creates a jump table that is 8x larger and sparser, and meanwhile the // if()s are highly predictable. - printer->Print("switch (::google::protobuf::internal::WireFormatLite::" - "GetTagFieldNumber(tag)) {\n"); + printer->Print( + "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); printer->Indent(); + scoped_array<const FieldDescriptor*> ordered_fields( + SortFieldsByNumber(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = ordered_fields[i]; @@ -2054,8 +1262,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) { const FieldGenerator& field_generator = field_generators_.get(field); // Emit code to parse the common, expected case. - printer->Print("if (tag == $commontag$) {\n", - "commontag", SimpleItoa(WireFormat::MakeTag(field))); + printer->Print( + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n", + "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]); if (i > 0 || (field->is_repeated() && !field->options().packed())) { printer->Print( @@ -2073,22 +1283,20 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Emit code to parse unexpectedly packed or unpacked values. if (field->is_packable() && field->options().packed()) { - internal::WireFormatLite::WireType wiretype = - WireFormat::WireTypeForFieldType(field->type()); - printer->Print("} else if (tag == $uncommontag$) {\n", - "uncommontag", SimpleItoa( - internal::WireFormatLite::MakeTag( - field->number(), wiretype))); + printer->Print( + "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" + " == ::google::protobuf::internal::WireFormatLite::\n" + " WIRETYPE_$wiretype$) {\n", + "wiretype", + kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]); printer->Indent(); field_generator.GenerateMergeFromCodedStream(printer); printer->Outdent(); } else if (field->is_packable() && !field->options().packed()) { - internal::WireFormatLite::WireType wiretype = - internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; - printer->Print("} else if (tag == $uncommontag$) {\n", - "uncommontag", SimpleItoa( - internal::WireFormatLite::MakeTag( - field->number(), wiretype))); + printer->Print( + "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" + " == ::google::protobuf::internal::WireFormatLite::\n" + " WIRETYPE_LENGTH_DELIMITED) {\n"); printer->Indent(); field_generator.GenerateMergeFromCodedStreamWithPacking(printer); printer->Outdent(); @@ -2096,7 +1304,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "} else {\n" - " goto handle_unusual;\n" + " goto handle_uninterpreted;\n" "}\n"); // switch() is slow since it can't be predicted well. Insert some if()s @@ -2120,7 +1328,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Expect EOF. // TODO(kenton): Expect group end-tag? printer->Print( - "if (input->ExpectAtEnd()) goto success;\n"); + "if (input->ExpectAtEnd()) return true;\n"); } printer->Print( @@ -2130,19 +1338,17 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print("}\n\n"); } - printer->Print("default: {\n"); + printer->Print( + "default: {\n" + "handle_uninterpreted:\n"); printer->Indent(); } - printer->Outdent(); - printer->Print("handle_unusual:\n"); - printer->Indent(); - // If tag is 0 or an end-group tag then this must be the end of the message. + // Is this an end-group tag? If so, this must be the end of the message. printer->Print( - "if (tag == 0 ||\n" - " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" - " goto success;\n" + " return true;\n" "}\n"); // Handle extension ranges. @@ -2171,24 +1377,13 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } } printer->Print(") {\n"); - if (UseUnknownFieldSet(descriptor_->file())) { - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. + if (HasUnknownFields(descriptor_->file())) { + printer->Print( " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " mutable_unknown_fields()));\n", - // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" " mutable_unknown_fields()));\n"); } else { - PrintHandlingOptionalStaticInitializers( - descriptor_->file(), printer, - // With static initializers. - " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " &unknown_fields_stream));\n", - // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" - " &unknown_fields_stream));\n"); + printer->Print( + " DO_(_extensions_.ParseField(tag, input, default_instance_));\n"); } printer->Print( " continue;\n" @@ -2196,14 +1391,13 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } // We really don't recognize this tag. Skip it. - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print( "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" " input, tag, mutable_unknown_fields()));\n"); } else { printer->Print( - "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" - " input, tag, &unknown_fields_stream));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); } if (descriptor_->field_count() > 0) { @@ -2217,15 +1411,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // for (;;) - "success:\n" - " // @@protoc_insertion_point(parse_success:$full_name$)\n" + " }\n" // while " return true;\n" - "failure:\n" - " // @@protoc_insertion_point(parse_failure:$full_name$)\n" - " return false;\n" "#undef DO_\n" - "}\n", "full_name", descriptor_->full_name()); + "}\n"); } void MessageGenerator::GenerateSerializeOneField( @@ -2234,8 +1423,8 @@ void MessageGenerator::GenerateSerializeOneField( if (!field->is_repeated()) { printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); + "if (_has_bit($index$)) {\n", + "index", SimpleItoa(field->index())); printer->Indent(); } @@ -2281,10 +1470,11 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { " ::google::protobuf::io::CodedOutputStream* output) const {\n" " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); - printer->Print( - " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" - " unknown_fields(), output);\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); + } printer->Print( "}\n"); return; @@ -2296,16 +1486,8 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print( - "// @@protoc_insertion_point(serialize_start:$full_name$)\n", - "full_name", descriptor_->full_name()); - GenerateSerializeWithCachedSizesBody(printer, false); - printer->Print( - "// @@protoc_insertion_point(serialize_end:$full_name$)\n", - "full_name", descriptor_->full_name()); - printer->Outdent(); printer->Print( "}\n"); @@ -2321,11 +1503,12 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { " target =\n" " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); - printer->Print( - " target = ::google::protobuf::internal::WireFormat::\n" - " SerializeUnknownMessageSetItemsToArray(\n" - " unknown_fields(), target);\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); + } printer->Print( " return target;\n" "}\n"); @@ -2338,16 +1521,8 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", - "full_name", descriptor_->full_name()); - GenerateSerializeWithCachedSizesBody(printer, true); - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", - "full_name", descriptor_->full_name()); - printer->Outdent(); printer->Print( " return target;\n" @@ -2357,7 +1532,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { void MessageGenerator:: GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { scoped_array<const FieldDescriptor*> ordered_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector<const Descriptor::ExtensionRange*> sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -2386,7 +1561,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } } - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); if (to_array) { @@ -2403,10 +1578,6 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { printer->Print( "}\n"); - } else { - printer->Print( - "output->WriteRaw(unknown_fields().data(),\n" - " unknown_fields().size());\n"); } } @@ -2418,10 +1589,11 @@ GenerateByteSize(io::Printer* printer) { "int $classname$::ByteSize() const {\n" " int total_size = _extensions_.MessageSetByteSize();\n", "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); - printer->Print( - " total_size += ::google::protobuf::internal::WireFormat::\n" - " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); + } printer->Print( " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" " _cached_size_ = total_size;\n" @@ -2444,7 +1616,7 @@ GenerateByteSize(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated() && !field->containing_oneof()) { + if (!field->is_repeated()) { // See above in GenerateClear for an explanation of this. // TODO(kenton): Share code? Unclear how to do so without // over-engineering. @@ -2494,45 +1666,13 @@ GenerateByteSize(io::Printer* printer) { } } - // Fields inside a oneof don't use _has_bits_ so we count them in a separate - // pass. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - PrintFieldComment(printer, field); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - field_generators_.get(field).GenerateByteSize(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); - } - if (descriptor_->extension_range_count() > 0) { printer->Print( "total_size += _extensions_.ByteSize();\n" "\n"); } - if (UseUnknownFieldSet(descriptor_->file())) { + if (HasUnknownFields(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); printer->Print( @@ -2541,10 +1681,6 @@ GenerateByteSize(io::Printer* printer) { " unknown_fields());\n"); printer->Outdent(); printer->Print("}\n"); - } else { - printer->Print( - "total_size += unknown_fields().size();\n" - "\n"); } // We update _cached_size_ even though this is a const method. In theory, @@ -2598,30 +1734,19 @@ GenerateIsInitialized(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !ShouldIgnoreRequiredFieldCheck(field) && HasRequiredFields(field->message_type())) { if (field->is_repeated()) { printer->Print( - "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" - " return false;\n", + "for (int i = 0; i < $name$_size(); i++) {\n" + " if (!this->$name$(i).IsInitialized()) return false;\n" + "}\n", "name", FieldName(field)); } else { - if (field->options().weak()) { - // For weak fields, use the data member (google::protobuf::Message*) instead - // of the getter to avoid a link dependency on the weak message type - // which is only forward declared. - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$_->IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); - } else { - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$().IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); - } + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$().IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index bfd3cec..04778f6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,11 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ -#include <memory> #include <string> -#include <vector> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/cpp/cpp_field.h> -#include <google/protobuf/compiler/cpp/cpp_options.h> namespace google { namespace protobuf { @@ -59,7 +57,7 @@ class MessageGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit MessageGenerator(const Descriptor* descriptor, - const Options& options); + const string& dllexport_decl); ~MessageGenerator(); // Header stuff. @@ -133,7 +131,6 @@ class MessageGenerator { // Generate standard Message methods. void GenerateClear(io::Printer* printer); - void GenerateOneofClear(io::Printer* printer); void GenerateMergeFromCodedStream(io::Printer* printer); void GenerateSerializeWithCachedSizes(io::Printer* printer); void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); @@ -156,13 +153,11 @@ class MessageGenerator { const Descriptor* descriptor_; string classname_; - Options options_; + string dllexport_decl_; FieldGeneratorMap field_generators_; - vector< vector<string> > runs_of_fields_; // that might be trivially cleared scoped_array<scoped_ptr<MessageGenerator> > nested_generators_; scoped_array<scoped_ptr<EnumGenerator> > enum_generators_; scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_; - bool uses_string_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 6ac15a5..c04bdc6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -45,20 +45,13 @@ namespace cpp { namespace { void SetMessageVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); + map<string, string>* variables) { + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = FieldMessageTypeName(descriptor); (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file()) ? "MaybeToArray" : ""); - // NOTE: Escaped here to unblock proto1->proto2 migration. - // TODO(liujisi): Extend this to apply for other conflicting methods. - (*variables)["release_name"] = - SafeFunctionName(descriptor->containing_type(), - descriptor, "release_"); - (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -66,10 +59,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +MessageFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_, options); + SetMessageVariables(descriptor, &variables_); } MessageFieldGenerator::~MessageFieldGenerator() {} @@ -83,47 +75,19 @@ void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $name$() const$deprecation$;\n" - "inline $type$* mutable_$name$()$deprecation$;\n" - "inline $type$* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + "inline $type$* mutable_$name$()$deprecation$;\n"); } void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n"); - - PrintHandlingOptionalStaticInitializers( - variables_, descriptor_->file(), printer, - // With static initializers. - " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", - // Without. - " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); - - printer->Print(variables_, + " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n" "}\n" "inline $type$* $classname$::mutable_$name$() {\n" - " set_has_$name$();\n" + " _set_bit($index$);\n" " if ($name$_ == NULL) $name$_ = new $type$;\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" - "}\n" - "inline $type$* $classname$::$release_name$() {\n" - " clear_has_$name$();\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" - "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" - " delete $name$_;\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " } else {\n" - " clear_has_$name$();\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } @@ -187,74 +151,10 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== -MessageOneofFieldGenerator:: -MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : MessageFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} - -void MessageOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" - " return has_$name$() ? *$oneof_prefix$$name$_\n" - " : $type$::default_instance();\n" - "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = new $type$;\n" - " }\n" - " return $oneof_prefix$$name$_;\n" - "}\n" - "inline $type$* $classname$::$release_name$() {\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " $type$* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" - " return temp;\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" - " }\n" - "}\n"); -} - -void MessageOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - // if it is the active field, it cannot be NULL. - printer->Print(variables_, - "delete $oneof_prefix$$name$_;\n"); -} - -void MessageOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void MessageOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - // Don't print any constructor code. The field is in a union. We allocate - // space only when this field is used. -} - -// =================================================================== - RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_, options); + SetMessageVariables(descriptor, &variables_); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} @@ -282,26 +182,21 @@ void RepeatedMessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" + " return $name$_.Get(index);\n" "}\n" "inline $type$* $classname$::mutable_$name$(int index) {\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline $type$* $classname$::add_$name$() {\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" " return $name$_.Add();\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 2dff314..f514727 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,8 +46,7 @@ namespace cpp { class MessageFieldGenerator : public FieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit MessageFieldGenerator(const FieldDescriptor* descriptor); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -63,34 +62,16 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; -class MessageOneofFieldGenerator : public MessageFieldGenerator { - public: - explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~MessageOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateClearingCode(io::Printer* printer) const; - void GenerateSwappingCode(io::Printer* printer) const; - void GenerateConstructorCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); -}; - class RepeatedMessageFieldGenerator : public FieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h deleted file mode 100644 index 0c99cff..0000000 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -// Author: rennie@google.com (Jeffrey Rennie) - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ - -#include <string> - -#include <google/protobuf/stubs/common.h> -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -// Generator options: -struct Options { - Options() : safe_boundary_check(false) { - } - string dllexport_decl; - bool safe_boundary_check; -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf - - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index 2dbf14c..440b716 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -34,8 +34,6 @@ // It seemed like parameterizing it would add more complexity than it is // worth. -#include <memory> - #include <google/protobuf/compiler/cpp/cpp_generator.h> #include <google/protobuf/compiler/command_line_interface.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -58,24 +56,24 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { - TryInsert("test.pb.h", "includes", context); - TryInsert("test.pb.h", "namespace_scope", context); - TryInsert("test.pb.h", "global_scope", context); - TryInsert("test.pb.h", "class_scope:foo.Bar", context); - TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context); - - TryInsert("test.pb.cc", "includes", context); - TryInsert("test.pb.cc", "namespace_scope", context); - TryInsert("test.pb.cc", "global_scope", context); + TryInsert("test.pb.h", "includes", output_directory); + TryInsert("test.pb.h", "namespace_scope", output_directory); + TryInsert("test.pb.h", "global_scope", output_directory); + TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory); + TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory); + + TryInsert("test.pb.cc", "includes", output_directory); + TryInsert("test.pb.cc", "namespace_scope", output_directory); + TryInsert("test.pb.cc", "global_scope", output_directory); return true; } void TryInsert(const string& filename, const string& insertion_point, - GeneratorContext* context) const { + OutputDirectory* output_directory) const { scoped_ptr<io::ZeroCopyOutputStream> output( - context->OpenForInsert(filename, insertion_point)); + output_directory->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -85,13 +83,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(CppPluginTest, PluginTest) { - GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - true)); + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + TestTempDir() + "/test.proto"); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 44290a3..a69c48b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -80,9 +80,8 @@ int FixedSize(FieldDescriptor::Type type) { } void SetPrimitiveVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); + map<string, string>* variables) { + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); (*variables)["default"] = DefaultValue(descriptor); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); @@ -93,7 +92,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["wire_format_field_type"] = "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( static_cast<FieldDescriptorProto_Type>(descriptor->type())); - (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -101,10 +99,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +PrimitiveFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_, options); + SetPrimitiveVariables(descriptor, &variables_); } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} @@ -125,13 +122,11 @@ void PrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_;\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" - " set_has_$name$();\n" + " _set_bit($index$);\n" " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -161,7 +156,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" " $type$, $wire_format_field_type$>(\n" " input, &$name$_)));\n" - "set_has_$name$();\n"); + "_set_bit($index$);\n"); } void PrimitiveFieldGenerator:: @@ -194,67 +189,10 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== -PrimitiveOneofFieldGenerator:: -PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : PrimitiveFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} - -void PrimitiveOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_;\n" - " }\n" - " return $default$;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $oneof_prefix$$name$_ = value;\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); -} - -void PrimitiveOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void PrimitiveOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print( - variables_, - " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); -} - -void PrimitiveOneofFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "clear_$oneof_name$();\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " $type$, $wire_format_field_type$>(\n" - " input, &$oneof_prefix$$name$_)));\n" - "set_has_$name$();\n"); -} - -// =================================================================== - RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_, options); + SetPrimitiveVariables(descriptor, &variables_); if (descriptor->options().packed()) { variables_["packed_reader"] = "ReadPackedPrimitive"; @@ -294,26 +232,21 @@ void RepeatedPrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get(index);\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField< $type$ >&\n" "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField< $type$ >*\n" "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -433,9 +366,7 @@ GenerateByteSize(io::Printer* printer) const { " total_size += $tag_size$ +\n" " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" "_$name$_cached_byte_size_ = data_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" "total_size += data_size;\n"); } else { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 97b5e86..8fcd74a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,8 +46,7 @@ namespace cpp { class PrimitiveFieldGenerator : public FieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -63,35 +62,16 @@ class PrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; -class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { - public: - explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~PrimitiveOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateClearingCode(io::Printer* printer) const; - void GenerateSwappingCode(io::Printer* printer) const; - void GenerateConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); -}; - class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index a8f303d..c282568 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -43,14 +43,14 @@ namespace compiler { namespace cpp { ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, - const Options& options) + const string& dllexport_decl) : descriptor_(descriptor) { vars_["classname"] = descriptor_->name(); vars_["full_name"] = descriptor_->full_name(); - if (options.dllexport_decl.empty()) { + if (dllexport_decl.empty()) { vars_["dllexport"] = ""; } else { - vars_["dllexport"] = options.dllexport_decl + " "; + vars_["dllexport"] = dllexport_decl + " "; } } diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h index ede2fd8..10e9dd3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.h +++ b/src/google/protobuf/compiler/cpp/cpp_service.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -37,7 +37,7 @@ #include <map> #include <string> -#include <google/protobuf/compiler/cpp/cpp_options.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> namespace google { @@ -55,7 +55,7 @@ class ServiceGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit ServiceGenerator(const ServiceDescriptor* descriptor, - const Options& options); + const string& dllexport_decl); ~ServiceGenerator(); // Header stuff. diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 180d236..ea6809a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,23 +46,12 @@ namespace cpp { namespace { void SetStringVariables(const FieldDescriptor* descriptor, - map<string, string>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["default_length"] = - SimpleItoa(descriptor->default_value_string().length()); - (*variables)["default_variable"] = descriptor->default_value_string().empty() - ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()" - : "_default_" + FieldName(descriptor) + "_"; + map<string, string>* variables) { + SetCommonFieldVariables(descriptor, variables); + (*variables)["default"] = + "\"" + CEscape(descriptor->default_value_string()) + "\""; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; - // NOTE: Escaped here to unblock proto1->proto2 migration. - // TODO(liujisi): Extend this to apply for other conflicting methods. - (*variables)["release_name"] = - SafeFunctionName(descriptor->containing_type(), - descriptor, "release_"); - (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -70,24 +59,18 @@ void SetStringVariables(const FieldDescriptor* descriptor, // =================================================================== StringFieldGenerator:: -StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +StringFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetStringVariables(descriptor, &variables_, options); + SetStringVariables(descriptor, &variables_); } StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "::std::string* $name$_;\n"); -} - -void StringFieldGenerator:: -GenerateStaticMembers(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, "static ::std::string* $default_variable$;\n"); - } + printer->Print(variables_, + "::std::string* $name$_;\n" + "static const ::std::string _default_$name$_;\n"); } void StringFieldGenerator:: @@ -122,10 +105,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "inline void set_$name$(const char* value)$deprecation$;\n" "inline void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* mutable_$name$()$deprecation$;\n" - "inline ::std::string* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); - + "inline ::std::string* mutable_$name$()$deprecation$;\n"); if (descriptor_->options().ctype() != FieldOptions::STRING) { printer->Outdent(); @@ -138,80 +118,54 @@ void StringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" " return *$name$_;\n" "}\n" "inline void $classname$::set_$name$(const ::std::string& value) {\n" - " set_has_$name$();\n" - " if ($name$_ == $default_variable$) {\n" + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" - " set_has_$name$();\n" - " if ($name$_ == $default_variable$) {\n" + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" - " set_has_$name$();\n" - " if ($name$_ == $default_variable$) {\n" + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(reinterpret_cast<const char*>(value), size);\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::mutable_$name$() {\n" - " set_has_$name$();\n" - " if ($name$_ == $default_variable$) {\n"); + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n"); if (descriptor_->default_value_string().empty()) { printer->Print(variables_, " $name$_ = new ::std::string;\n"); } else { printer->Print(variables_, - " $name$_ = new ::std::string(*$default_variable$);\n"); + " $name$_ = new ::std::string(_default_$name$_);\n"); } printer->Print(variables_, " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" - "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" - " clear_has_$name$();\n" - " if ($name$_ == $default_variable$) {\n" - " return NULL;\n" - " } else {\n" - " ::std::string* temp = $name$_;\n" - " $name$_ = const_cast< ::std::string*>($default_variable$);\n" - " return temp;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if ($name$_ != $default_variable$) {\n" - " delete $name$_;\n" - " }\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $name$_ = $name$;\n" - " } else {\n" - " clear_has_$name$();\n" - " $name$_ = const_cast< ::std::string*>($default_variable$);\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } void StringFieldGenerator:: GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - // Initialized in GenerateDefaultInstanceAllocator. + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "const ::std::string $classname$::_default_$name$_;\n"); + } else { printer->Print(variables_, - "::std::string* $classname$::$default_variable$ = NULL;\n"); + "const ::std::string $classname$::_default_$name$_($default$);\n"); } } @@ -219,13 +173,13 @@ void StringFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { if (descriptor_->default_value_string().empty()) { printer->Print(variables_, - "if ($name$_ != $default_variable$) {\n" + "if ($name$_ != &_default_$name$_) {\n" " $name$_->clear();\n" "}\n"); } else { printer->Print(variables_, - "if ($name$_ != $default_variable$) {\n" - " $name$_->assign(*$default_variable$);\n" + "if ($name$_ != &_default_$name$_) {\n" + " $name$_->assign(_default_$name$_);\n" "}\n"); } } @@ -243,35 +197,18 @@ GenerateSwappingCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print(variables_, - "$name$_ = const_cast< ::std::string*>($default_variable$);\n"); + "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n"); } void StringFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { printer->Print(variables_, - "if ($name$_ != $default_variable$) {\n" + "if ($name$_ != &_default_$name$_) {\n" " delete $name$_;\n" "}\n"); } void StringFieldGenerator:: -GenerateDefaultInstanceAllocator(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$classname$::$default_variable$ =\n" - " new ::std::string($default$, $default_length$);\n"); - } -} - -void StringFieldGenerator:: -GenerateShutdownCode(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "delete $classname$::$default_variable$;\n"); - } -} - -void StringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" @@ -279,10 +216,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE,\n" - " \"$name$\");\n"); + " ::google::protobuf::internal::WireFormat::PARSE);\n"); } } @@ -291,13 +227,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" - " \"$name$\");\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); } printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n" + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" " $number$, this->$name$(), output);\n"); } @@ -306,10 +241,9 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" - " \"$name$\");\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); } printer->Print(variables_, "target =\n" @@ -327,130 +261,10 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== -StringOneofFieldGenerator:: -StringOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : StringFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -StringOneofFieldGenerator::~StringOneofFieldGenerator() {} - -void StringOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" - " if (has_$name$()) {\n" - " return *$oneof_prefix$$name$_;\n" - " }\n"); - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - " return ::google::protobuf::internal::GetEmptyStringAlreadyInited();\n"); - } else { - printer->Print(variables_, - " return *$default_variable$;\n"); - } - printer->Print(variables_, - "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = new ::std::string;\n" - " }\n" - " $oneof_prefix$$name$_->assign(value);\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = new ::std::string;\n" - " }\n" - " $oneof_prefix$$name$_->assign(value);\n" - "}\n" - "inline " - "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = new ::std::string;\n" - " }\n" - " $oneof_prefix$$name$_->assign(\n" - " reinterpret_cast<const char*>(value), size);\n" - "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n"); - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - " $oneof_prefix$$name$_ = new ::std::string;\n"); - } else { - printer->Print(variables_, - " $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\n"); - } - printer->Print(variables_, - " }\n" - " return $oneof_prefix$$name$_;\n" - "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " ::std::string* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" - " return temp;\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" - " }\n" - "}\n"); -} - -void StringOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, - "delete $oneof_prefix$$name$_;\n"); -} - -void StringOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void StringOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, - " $classname$_default_oneof_instance_->$name$_ = " - "$classname$::$default_variable$;\n"); - } else { - printer->Print(variables_, - " $classname$_default_oneof_instance_->$name$_ = " - "$default_variable$;\n"); - } -} - -void StringOneofFieldGenerator:: -GenerateDestructorCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has_$name$()) {\n" - " delete $oneof_prefix$$name$_;\n" - "}\n"); -} - -// =================================================================== - RepeatedStringFieldGenerator:: -RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) +RepeatedStringFieldGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { - SetStringVariables(descriptor, &variables_, options); + SetStringVariables(descriptor, &variables_); } RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} @@ -503,53 +317,43 @@ void RepeatedStringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" + " return $name$_.Get(index);\n" "}\n" "inline ::std::string* $classname$::mutable_$name$(int index) {\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" "inline void $classname$::set_$name$(int index, const char* value) {\n" " $name$_.Mutable(index)->assign(value);\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline void " "$classname$::set_$name$" "(int index, const $pointer_type$* value, size_t size) {\n" " $name$_.Mutable(index)->assign(\n" " reinterpret_cast<const char*>(value), size);\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" "inline void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n" "inline void $classname$::add_$name$(const char* value) {\n" " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add_char:$full_name$)\n" "}\n" "inline void " "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n" - " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -582,11 +386,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" - " this->$name$(this->$name$_size() - 1).data(),\n" - " this->$name$(this->$name$_size() - 1).length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE,\n" - " \"$name$\");\n"); + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(0).data(), this->$name$(0).length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); } } @@ -597,10 +399,9 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" - " \"$name$\");\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); } printer->Print(variables_, " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" @@ -615,10 +416,9 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" - " \"$name$\");\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); } printer->Print(variables_, " target = ::google::protobuf::internal::WireFormatLite::\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 86da38f..7f45107 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,13 +46,11 @@ namespace cpp { class StringFieldGenerator : public FieldGenerator { public: - explicit StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit StringFieldGenerator(const FieldDescriptor* descriptor); ~StringFieldGenerator(); // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; - void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; @@ -61,42 +59,21 @@ class StringFieldGenerator : public FieldGenerator { void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateDestructorCode(io::Printer* printer) const; - void GenerateDefaultInstanceAllocator(io::Printer* printer) const; - void GenerateShutdownCode(io::Printer* printer) const; void GenerateMergeFromCodedStream(io::Printer* printer) const; void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); }; -class StringOneofFieldGenerator : public StringFieldGenerator { - public: - explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~StringOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateClearingCode(io::Printer* printer) const; - void GenerateSwappingCode(io::Printer* printer) const; - void GenerateConstructorCode(io::Printer* printer) const; - void GenerateDestructorCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); -}; - class RepeatedStringFieldGenerator : public FieldGenerator { public: - explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor); ~RepeatedStringFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 6b7f830..79971a9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -36,10 +36,6 @@ // though the same identifiers are used internally by the C++ code generator. -// Some generic_services option(s) added automatically. -// See: http://go/proto2-generic-services-default -option cc_generic_services = true; // auto-added - // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. package protobuf_unittest; @@ -98,33 +94,14 @@ message TestConflictingSymbolNames { // Some keywords. optional uint32 int = 30; optional uint32 friend = 31; - optional uint32 class = 37; // The generator used to #define a macro called "DO" inside the .cc file. message DO {} optional DO do = 32; - // Some template parameter names for extensions. - optional int32 field_type = 33; - optional bool is_packed = 34; - - // test conflicting release_$name$. "length" and "do" field in this message - // must remain string or message fields to make the test valid. - optional string release_length = 35; - // A more extreme case, the field name "do" here is a keyword, which will be - // escaped to "do_" already. Test there is no conflict even with escaped field - // names. - optional DO release_do = 36; - extensions 1000 to max; } -message TestConflictingSymbolNamesExtension { - extend TestConflictingSymbolNames { - repeated int32 repeated_int32_ext = 20423638 [packed=true]; - } -} - message DummyMessage {} service TestConflictingMethodNames { diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 93e1c3f..a7e852d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -44,9 +44,6 @@ // correctly and produces the interfaces we expect, which is why this test // is written this way. -#include <google/protobuf/compiler/cpp/cpp_unittest.h> - -#include <memory> #include <vector> #include <google/protobuf/unittest.pb.h> @@ -54,7 +51,6 @@ #include <google/protobuf/unittest_embed_optimize_for.pb.h> #include <google/protobuf/unittest_no_generic_services.pb.h> #include <google/protobuf/test_util.h> -#include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h> #include <google/protobuf/compiler/importer.h> #include <google/protobuf/io/coded_stream.h> @@ -68,7 +64,7 @@ #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/stl_util-inl.h> namespace google { namespace protobuf { @@ -78,8 +74,6 @@ namespace cpp { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace cpp_unittest { -namespace protobuf_unittest = ::protobuf_unittest; - class MockErrorCollector : public MultiFileErrorCollector { public: @@ -150,19 +144,6 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } -TEST(GeneratedMessageTest, Int32StringConversion) { - EXPECT_EQ("971", Int32ToString(971)); - EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); - EXPECT_EQ("2147483647", Int32ToString(kint32max)); -} - -TEST(GeneratedMessageTest, Int64StringConversion) { - EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971)); - EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min)); - EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); - EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); -} - TEST(GeneratedMessageTest, FloatingPointDefaults) { const unittest::TestExtremeDefaultValues& extreme_default = unittest::TestExtremeDefaultValues::default_instance(); @@ -186,22 +167,6 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) { EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float()); } -TEST(GeneratedMessageTest, Trigraph) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - - EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph()); -} - -TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - EXPECT_EQ(~0x7fffffff, kint32min); - EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min); - EXPECT_EQ(kint32min, extreme_default.really_small_int32()); - EXPECT_EQ(kint64min, extreme_default.really_small_int64()); -} - TEST(GeneratedMessageTest, Accessors) { // Set every field to a unique value then go back and check all those // values. @@ -230,96 +195,6 @@ TEST(GeneratedMessageTest, MutableStringDefault) { EXPECT_EQ("hello", *message.mutable_default_string()); } -TEST(GeneratedMessageTest, StringDefaults) { - unittest::TestExtremeDefaultValues message; - // Check if '\000' can be used in default string value. - EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero()); - EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero()); -} - -TEST(GeneratedMessageTest, ReleaseString) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestAllTypes message; - - EXPECT_EQ(NULL, message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - EXPECT_EQ("hello", message.default_string()); - - message.set_default_string("blah"); - EXPECT_TRUE(message.has_default_string()); - scoped_ptr<string> str(message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - ASSERT_TRUE(str != NULL); - EXPECT_EQ("blah", *str); - - EXPECT_EQ(NULL, message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - EXPECT_EQ("hello", message.default_string()); -} - -TEST(GeneratedMessageTest, ReleaseMessage) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestAllTypes message; - - EXPECT_EQ(NULL, message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - scoped_ptr<unittest::TestAllTypes::NestedMessage> nest( - message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); - ASSERT_TRUE(nest != NULL); - EXPECT_EQ(1, nest->bb()); - - EXPECT_EQ(NULL, message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); -} - -TEST(GeneratedMessageTest, SetAllocatedString) { - // Check that set_allocated_foo() works for strings. - unittest::TestAllTypes message; - - EXPECT_FALSE(message.has_optional_string()); - const string kHello("hello"); - message.set_optional_string(kHello); - EXPECT_TRUE(message.has_optional_string()); - - message.set_allocated_optional_string(NULL); - EXPECT_FALSE(message.has_optional_string()); - EXPECT_EQ("", message.optional_string()); - - message.set_allocated_optional_string(new string(kHello)); - EXPECT_TRUE(message.has_optional_string()); - EXPECT_EQ(kHello, message.optional_string()); -} - -TEST(GeneratedMessageTest, SetAllocatedMessage) { - // Check that set_allocated_foo() can be called in all cases. - unittest::TestAllTypes message; - - EXPECT_FALSE(message.has_optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - EXPECT_TRUE(message.has_optional_nested_message()); - - message.set_allocated_optional_nested_message(NULL); - EXPECT_FALSE(message.has_optional_nested_message()); - EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), - &message.optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - unittest::TestAllTypes::NestedMessage* nest = - message.release_optional_nested_message(); - ASSERT_TRUE(nest != NULL); - EXPECT_FALSE(message.has_optional_nested_message()); - - message.set_allocated_optional_nested_message(nest); - EXPECT_TRUE(message.has_optional_nested_message()); - EXPECT_EQ(1, message.optional_nested_message().bb()); -} - TEST(GeneratedMessageTest, Clear) { // Set every field to a unique value, clear the message, then check that // it is cleared. @@ -407,7 +282,6 @@ TEST(GeneratedMessageTest, CopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } - TEST(GeneratedMessageTest, SwapWithEmpty) { unittest::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); @@ -502,12 +376,10 @@ TEST(GeneratedMessageTest, CopyAssignmentOperator) { TestUtil::ExpectAllFieldsSet(message2); // Make sure that self-assignment does something sane. - message2.operator=(message2); + message2 = message2; TestUtil::ExpectAllFieldsSet(message2); } -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) TEST(GeneratedMessageTest, UpcastCopyFrom) { // Test the CopyFrom method that takes in the generic const Message& // parameter. @@ -520,7 +392,6 @@ TEST(GeneratedMessageTest, UpcastCopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } -#endif #ifndef PROTOBUF_TEST_NO_DESCRIPTORS @@ -572,9 +443,7 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) { TestUtil::ExpectAllFieldsSet(message1); } -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) -#ifdef PROTOBUF_HAS_DEATH_TEST +#ifdef GTEST_HAS_DEATH_TEST TEST(GeneratedMessageTest, MergeFromSelf) { unittest::TestAllTypes message; @@ -583,8 +452,7 @@ TEST(GeneratedMessageTest, MergeFromSelf) { "&from"); } -#endif // PROTOBUF_HAS_DEATH_TEST -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI +#endif // GTEST_HAS_DEATH_TEST // Test the generated SerializeWithCachedSizesToArray(), TEST(GeneratedMessageTest, SerializationToArray) { @@ -777,16 +645,6 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { message.set_friend_(5); EXPECT_EQ(5, message.friend_()); - - message.set_class_(6); - EXPECT_EQ(6, message.class_()); - - // Instantiate extension template functions to test conflicting template - // parameter names. - typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage; - message.AddExtension(ExtensionMessage::repeated_int32_ext, 123); - EXPECT_EQ(123, - message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } #ifndef PROTOBUF_TEST_NO_DESCRIPTORS @@ -858,43 +716,8 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { message1.SpaceUsed()); } -TEST(GeneratedMessageTest, TestOneofSpaceUsed) { - unittest::TestOneof2 message1; - EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed()); - - const int empty_message_size = message1.SpaceUsed(); - // Setting primitive types shouldn't affect the space used. - message1.set_foo_int(123); - message1.set_bar_int(12345); - EXPECT_EQ(empty_message_size, message1.SpaceUsed()); - - // Setting a string in oneof to a small value should only increase SpaceUsed() - // by the size of a string object. - message1.set_foo_string("abc"); - EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); - - // Setting a string in oneof to a value larger than the string object itself - // should increase SpaceUsed(), because it cannot store the value internally. - message1.set_foo_string(string(sizeof(string) + 1, 'x')); - int min_expected_increase = message1.foo_string().capacity() + - sizeof(string); - EXPECT_LE(empty_message_size + min_expected_increase, - message1.SpaceUsed()); - - // Setting a message in oneof should delete the other fields and increase the - // size by the size of the nested message type. NestedMessage is simple enough - // that it is equal to sizeof(NestedMessage) - message1.mutable_foo_message(); - ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage), - message1.foo_message().SpaceUsed()); - EXPECT_EQ(empty_message_size + - sizeof(unittest::TestOneof2::NestedMessage), - message1.SpaceUsed()); -} - #endif // !PROTOBUF_TEST_NO_DESCRIPTORS - TEST(GeneratedMessageTest, FieldConstantValues) { unittest::TestRequired message; EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); @@ -939,9 +762,6 @@ TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { case unittest::TestAllTypes::BAZ: i = 3; break; - case unittest::TestAllTypes::NEG: - i = -1; - break; // no default case: We want to make sure the compiler recognizes that // all cases are covered. (GCC warns if you do not cover all cases of // an enum in a switch.) @@ -970,7 +790,7 @@ TEST(GeneratedEnumTest, IsValidValue) { } TEST(GeneratedEnumTest, MinAndMax) { - EXPECT_EQ(unittest::TestAllTypes::NEG, + EXPECT_EQ(unittest::TestAllTypes::FOO, unittest::TestAllTypes::NestedEnum_MIN); EXPECT_EQ(unittest::TestAllTypes::BAZ, unittest::TestAllTypes::NestedEnum_MAX); @@ -989,19 +809,20 @@ TEST(GeneratedEnumTest, MinAndMax) { EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE); // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE. - void* null_pointer = 0; // NULL may be integer-type, not pointer-type. - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN); - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX); - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); + void* nullptr = 0; // NULL may be integer-type, not pointer-type. + EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MIN); + EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MAX); + EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); - EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN); - EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX); - EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE); + EXPECT_NE(nullptr, &unittest::ForeignEnum_MIN); + EXPECT_NE(nullptr, &unittest::ForeignEnum_MAX); + EXPECT_NE(nullptr, &unittest::ForeignEnum_ARRAYSIZE); - // Make sure we can use _MIN and _MAX as switch cases. + // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases. switch (unittest::SPARSE_A) { case unittest::TestSparseEnum_MIN: case unittest::TestSparseEnum_MAX: + case unittest::TestSparseEnum_ARRAYSIZE: break; default: break; @@ -1044,20 +865,6 @@ TEST(GeneratedEnumTest, GetEnumDescriptor) { GetEnumDescriptor<unittest::TestSparseEnum>()); } -enum NonProtoEnum { - kFoo = 1, -}; - -TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) { - EXPECT_TRUE(is_proto_enum<unittest::TestAllTypes::NestedEnum>::value); - EXPECT_TRUE(is_proto_enum<unittest::ForeignEnum>::value); - EXPECT_TRUE(is_proto_enum<unittest::TestEnumWithDupValue>::value); - EXPECT_TRUE(is_proto_enum<unittest::TestSparseEnum>::value); - - EXPECT_FALSE(is_proto_enum<int>::value); - EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value); -} - #endif // PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== @@ -1272,7 +1079,7 @@ TEST_F(GeneratedServiceTest, CallMethod) { TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { // Verify death if we call Foo() with Bar's message types. -#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet +#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet EXPECT_DEBUG_DEATH( mock_service_.CallMethod(foo_, &mock_controller_, &foo_request_, &bar_response_, done_.get()), @@ -1283,7 +1090,7 @@ TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { mock_service_.CallMethod(foo_, &mock_controller_, &bar_request_, &foo_response_, done_.get()), "dynamic_cast"); -#endif // PROTOBUF_HAS_DEATH_TEST +#endif // GTEST_HAS_DEATH_TEST } TEST_F(GeneratedServiceTest, GetPrototypes) { @@ -1357,657 +1164,6 @@ TEST_F(GeneratedServiceTest, NotImplemented) { EXPECT_TRUE(controller.called_); } -// =================================================================== - -class OneofTest : public testing::Test { - protected: - virtual void SetUp() { - } - - void ExpectEnumCasesWork(const unittest::TestOneof2 &message) { - switch (message.foo_case()) { - case unittest::TestOneof2::kFooInt: - EXPECT_TRUE(message.has_foo_int()); - break; - case unittest::TestOneof2::kFooString: - EXPECT_TRUE(message.has_foo_string()); - break; - case unittest::TestOneof2::kFooBytes: - EXPECT_TRUE(message.has_foo_bytes()); - break; - case unittest::TestOneof2::kFooEnum: - EXPECT_TRUE(message.has_foo_enum()); - break; - case unittest::TestOneof2::kFooMessage: - EXPECT_TRUE(message.has_foo_message()); - break; - case unittest::TestOneof2::kFoogroup: - EXPECT_TRUE(message.has_foogroup()); - break; - case unittest::TestOneof2::FOO_NOT_SET: - break; - } - } -}; - -TEST_F(OneofTest, SettingOneFieldClearsOthers) { - unittest::TestOneof2 message; - - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.set_foo_string("foo"); - EXPECT_TRUE(message.has_foo_string()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - - message.set_foo_bytes("qux"); - EXPECT_TRUE(message.has_foo_bytes()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.set_foo_enum(unittest::TestOneof2::FOO); - EXPECT_TRUE(message.has_foo_enum()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.mutable_foo_message()->set_qux_int(234); - EXPECT_TRUE(message.has_foo_message()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.mutable_foogroup()->set_a(345); - EXPECT_TRUE(message.has_foogroup()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - - // we repeat this because we didn't test if this properly clears other fields - // at the beginning. - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); -} - -TEST_F(OneofTest, EnumCases) { - unittest::TestOneof2 message; - - message.set_foo_int(123); - ExpectEnumCasesWork(message); - message.set_foo_string("foo"); - ExpectEnumCasesWork(message); - message.set_foo_bytes("qux"); - ExpectEnumCasesWork(message); - message.set_foo_enum(unittest::TestOneof2::FOO); - ExpectEnumCasesWork(message); - message.mutable_foo_message()->set_qux_int(234); - ExpectEnumCasesWork(message); - message.mutable_foogroup()->set_a(345); - ExpectEnumCasesWork(message); -} - -TEST_F(OneofTest, PrimitiveType) { - unittest::TestOneof2 message; - // Unset field returns default value - EXPECT_EQ(message.foo_int(), 0); - - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - EXPECT_EQ(message.foo_int(), 123); - message.clear_foo_int(); - EXPECT_FALSE(message.has_foo_int()); -} - -TEST_F(OneofTest, EnumType) { - unittest::TestOneof2 message; - // Unset field returns default value - EXPECT_EQ(message.foo_enum(), 1); - - message.set_foo_enum(unittest::TestOneof2::FOO); - EXPECT_TRUE(message.has_foo_enum()); - EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO); - message.clear_foo_enum(); - EXPECT_FALSE(message.has_foo_enum()); -} - -TEST_F(OneofTest, SetString) { - // Check that setting a string field in various ways works - unittest::TestOneof2 message; - - // Unset field returns default value - EXPECT_EQ(message.foo_string(), ""); - - message.set_foo_string("foo"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "foo"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string(string("bar")); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "bar"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - - message.set_foo_string("qux", 3); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "qux"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.mutable_foo_string()->assign("quux"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "quux"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string("corge"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "corge"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); -} - -TEST_F(OneofTest, ReleaseString) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestOneof2 message; - - EXPECT_EQ(NULL, message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string("blah"); - EXPECT_TRUE(message.has_foo_string()); - scoped_ptr<string> str(message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); - ASSERT_TRUE(str != NULL); - EXPECT_EQ("blah", *str); - - EXPECT_EQ(NULL, message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); -} - -TEST_F(OneofTest, SetAllocatedString) { - // Check that set_allocated_foo() works for strings. - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_string()); - const string kHello("hello"); - message.set_foo_string(kHello); - EXPECT_TRUE(message.has_foo_string()); - - message.set_allocated_foo_string(NULL); - EXPECT_FALSE(message.has_foo_string()); - EXPECT_EQ("", message.foo_string()); - - message.set_allocated_foo_string(new string(kHello)); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(kHello, message.foo_string()); -} - - -TEST_F(OneofTest, SetMessage) { - // Check that setting a message field works - unittest::TestOneof2 message; - - // Unset field returns default instance - EXPECT_EQ(&message.foo_message(), - &unittest::TestOneof2_NestedMessage::default_instance()); - EXPECT_EQ(message.foo_message().qux_int(), 0); - - message.mutable_foo_message()->set_qux_int(234); - EXPECT_TRUE(message.has_foo_message()); - EXPECT_EQ(message.foo_message().qux_int(), 234); - message.clear_foo_message(); - EXPECT_FALSE(message.has_foo_message()); -} - -TEST_F(OneofTest, ReleaseMessage) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestOneof2 message; - - EXPECT_EQ(NULL, message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); - - message.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message.has_foo_message()); - scoped_ptr<unittest::TestOneof2_NestedMessage> mes( - message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); - ASSERT_TRUE(mes != NULL); - EXPECT_EQ(1, mes->qux_int()); - - EXPECT_EQ(NULL, message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); -} - -TEST_F(OneofTest, SetAllocatedMessage) { - // Check that set_allocated_foo() works for messages. - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_message()); - - message.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message.has_foo_message()); - - message.set_allocated_foo_message(NULL); - EXPECT_FALSE(message.has_foo_message()); - EXPECT_EQ(&message.foo_message(), - &unittest::TestOneof2_NestedMessage::default_instance()); - - message.mutable_foo_message()->set_qux_int(1); - unittest::TestOneof2_NestedMessage* mes = message.release_foo_message(); - ASSERT_TRUE(mes != NULL); - EXPECT_FALSE(message.has_foo_message()); - - message.set_allocated_foo_message(mes); - EXPECT_TRUE(message.has_foo_message()); - EXPECT_EQ(1, message.foo_message().qux_int()); -} - - -TEST_F(OneofTest, Clear) { - unittest::TestOneof2 message; - - message.set_foo_int(1); - EXPECT_TRUE(message.has_foo_int()); - message.clear_foo_int(); - EXPECT_FALSE(message.has_foo_int()); -} - -TEST_F(OneofTest, Defaults) { - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_int()); - EXPECT_EQ(message.foo_int(), 0); - - EXPECT_FALSE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), ""); - - - EXPECT_FALSE(message.has_foo_bytes()); - EXPECT_EQ(message.foo_bytes(), ""); - - EXPECT_FALSE(message.has_foo_enum()); - EXPECT_EQ(message.foo_enum(), 1); - - EXPECT_FALSE(message.has_foo_message()); - EXPECT_EQ(message.foo_message().qux_int(), 0); - - EXPECT_FALSE(message.has_foogroup()); - EXPECT_EQ(message.foogroup().a(), 0); - - - EXPECT_FALSE(message.has_bar_int()); - EXPECT_EQ(message.bar_int(), 5); - - EXPECT_FALSE(message.has_bar_string()); - EXPECT_EQ(message.bar_string(), "STRING"); - - - EXPECT_FALSE(message.has_bar_bytes()); - EXPECT_EQ(message.bar_bytes(), "BYTES"); - - EXPECT_FALSE(message.has_bar_enum()); - EXPECT_EQ(message.bar_enum(), 2); -} - -TEST_F(OneofTest, SwapWithEmpty) { - unittest::TestOneof2 message1, message2; - message1.set_foo_string("FOO"); - EXPECT_TRUE(message1.has_foo_string()); - message1.Swap(&message2); - EXPECT_FALSE(message1.has_foo_string()); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "FOO"); -} - -TEST_F(OneofTest, SwapWithSelf) { - unittest::TestOneof2 message; - message.set_foo_string("FOO"); - EXPECT_TRUE(message.has_foo_string()); - message.Swap(&message); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "FOO"); -} - -TEST_F(OneofTest, SwapBothHasFields) { - unittest::TestOneof2 message1, message2; - - message1.set_foo_string("FOO"); - EXPECT_TRUE(message1.has_foo_string()); - message2.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message2.has_foo_message()); - - message1.Swap(&message2); - EXPECT_FALSE(message1.has_foo_string()); - EXPECT_FALSE(message2.has_foo_message()); - EXPECT_TRUE(message1.has_foo_message()); - EXPECT_EQ(message1.foo_message().qux_int(), 1); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "FOO"); -} - -TEST_F(OneofTest, CopyContructor) { - unittest::TestOneof2 message1; - message1.set_foo_bytes("FOO"); - - unittest::TestOneof2 message2(message1); - EXPECT_TRUE(message2.has_foo_bytes()); - EXPECT_EQ(message2.foo_bytes(), "FOO"); -} - -TEST_F(OneofTest, CopyFrom) { - unittest::TestOneof2 message1, message2; - message1.set_foo_enum(unittest::TestOneof2::BAR); - EXPECT_TRUE(message1.has_foo_enum()); - - message2.CopyFrom(message1); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); - - // Copying from self should be a no-op. - message2.CopyFrom(message2); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); -} - -TEST_F(OneofTest, CopyAssignmentOperator) { - unittest::TestOneof2 message1; - message1.mutable_foo_message()->set_qux_int(123); - EXPECT_TRUE(message1.has_foo_message()); - - unittest::TestOneof2 message2; - message2 = message1; - EXPECT_EQ(message2.foo_message().qux_int(), 123); - - // Make sure that self-assignment does something sane. - message2 = message2; - EXPECT_EQ(message2.foo_message().qux_int(), 123); -} - -TEST_F(OneofTest, UpcastCopyFrom) { - // Test the CopyFrom method that takes in the generic const Message& - // parameter. - unittest::TestOneof2 message1, message2; - message1.mutable_foogroup()->set_a(123); - EXPECT_TRUE(message1.has_foogroup()); - - const Message* source = implicit_cast<const Message*>(&message1); - message2.CopyFrom(*source); - - EXPECT_TRUE(message2.has_foogroup()); - EXPECT_EQ(message2.foogroup().a(), 123); -} - -// Test the generated SerializeWithCachedSizesToArray(), -// This indirectly tests MergePartialFromCodedStream() -// We have to test each field type separately because we cannot set them at the -// same time -TEST_F(OneofTest, SerializationToArray) { - // Primitive type - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_int(123); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_int(), 123); - } - - // String - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_string("foo"); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_string(), "foo"); - } - - - // Bytes - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_bytes("qux"); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_bytes(), "qux"); - } - - // Enum - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_enum(unittest::TestOneof2::FOO); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - } - - // Message - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foo_message()->set_qux_int(234); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - } - - // Group - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foogroup()->set_a(345); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foogroup().a(), 345); - } - -} - -// Test the generated SerializeWithCachedSizes() by forcing the buffer to write -// one byte at a time. -// This indirectly tests MergePartialFromCodedStream() -// We have to test each field type separately because we cannot set them at the -// same time -TEST_F(OneofTest, SerializationToStream) { - // Primitive type - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_int(123); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_int(), 123); - } - - // String - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_string("foo"); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_string(), "foo"); - } - - - // Bytes - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_bytes("qux"); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_bytes(), "qux"); - } - - // Enum - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_enum(unittest::TestOneof2::FOO); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - } - - // Message - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foo_message()->set_qux_int(234); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - } - - // Group - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foogroup()->set_a(345); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foogroup().a(), 345); - } - -} - -TEST_F(OneofTest, MergeFrom) { - unittest::TestOneof2 message1, message2; - - message1.set_foo_int(123); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_int()); - EXPECT_EQ(message2.foo_int(), 123); - - message1.set_foo_string("foo"); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "foo"); - - - message1.set_foo_bytes("qux"); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_bytes()); - EXPECT_EQ(message2.foo_bytes(), "qux"); - - message1.set_foo_enum(unittest::TestOneof2::FOO); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - - message1.mutable_foo_message()->set_qux_int(234); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_message()); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - - message1.mutable_foogroup()->set_a(345); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foogroup()); - EXPECT_EQ(message2.foogroup().a(), 345); - -} - } // namespace cpp_unittest } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h deleted file mode 100644 index 69c8f44..0000000 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -// This header declares the namespace google::protobuf::protobuf_unittest in order to expose -// any problems with the generated class names. We use this header to ensure -// unittest.cc will declare the namespace prior to other includes, while obeying -// normal include ordering. -// -// When generating a class name of "foo.Bar" we must ensure we prefix the class -// name with "::", in case the namespace google::protobuf::foo exists. We intentionally -// trigger that case here by declaring google::protobuf::protobuf_unittest. -// -// See ClassName in helpers.h for more details. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ - -namespace google { -namespace protobuf { -namespace protobuf_unittest {} -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index e6c446a..7689ce9 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -43,7 +43,6 @@ #include <errno.h> #include <algorithm> -#include <memory> #include <google/protobuf/compiler/importer.h> @@ -125,8 +124,7 @@ bool SourceTreeDescriptorDatabase::FindFileByName( scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename)); if (input == NULL) { if (error_collector_ != NULL) { - error_collector_->AddError(filename, -1, 0, - source_tree_->GetLastErrorMessage()); + error_collector_->AddError(filename, -1, 0, "File not found."); } return false; } @@ -188,7 +186,6 @@ Importer::Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector) : database_(source_tree), pool_(&database_, database_.GetValidationErrorCollector()) { - pool_.EnforceWeakDependencies(true); database_.RecordErrorsTo(error_collector); } @@ -198,22 +195,10 @@ const FileDescriptor* Importer::Import(const string& filename) { return pool_.FindFileByName(filename); } -void Importer::AddUnusedImportTrackFile(const string& file_name) { - pool_.AddUnusedImportTrackFile(file_name); -} - -void Importer::ClearUnusedImportTrackFiles() { - pool_.ClearUnusedImportTrackFiles(); -} - // =================================================================== SourceTree::~SourceTree() {} -string SourceTree::GetLastErrorMessage() { - return "File not found."; -} - DiskSourceTree::DiskSourceTree() {} DiskSourceTree::~DiskSourceTree() {} @@ -246,17 +231,12 @@ static string CanonicalizePath(string path) { // The Win32 API accepts forward slashes as a path delimiter even though // backslashes are standard. Let's avoid confusion and use only forward // slashes. - if (HasPrefixString(path, "\\\\")) { - // Avoid converting two leading backslashes. - path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true); - } else { - path = StringReplace(path, "\\", "/", true); - } + path = StringReplace(path, "\\", "/", true); #endif + vector<string> parts; vector<string> canonical_parts; - vector<string> parts = Split( - path, "/", true); // Note: Removes empty parts. + SplitStringUsing(path, "/", &parts); // Note: Removes empty parts. for (int i = 0; i < parts.size(); i++) { if (parts[i] == ".") { // Ignore. @@ -264,7 +244,7 @@ static string CanonicalizePath(string path) { canonical_parts.push_back(parts[i]); } } - string result = Join(canonical_parts, "/"); + string result = JoinStrings(canonical_parts, "/"); if (!path.empty() && path[0] == '/') { // Restore leading slash. result = '/' + result; @@ -410,8 +390,8 @@ DiskSourceTree::DiskFileToVirtualFile( bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file, string* disk_file) { - scoped_ptr<io::ZeroCopyInputStream> stream( - OpenVirtualFile(virtual_file, disk_file)); + scoped_ptr<io::ZeroCopyInputStream> stream(OpenVirtualFile(virtual_file, + disk_file)); return stream != NULL; } @@ -419,10 +399,6 @@ io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) { return OpenVirtualFile(filename, NULL); } -string DiskSourceTree::GetLastErrorMessage() { - return last_error_message_; -} - io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( const string& virtual_file, string* disk_file) { @@ -431,8 +407,6 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( // We do not allow importing of paths containing things like ".." or // consecutive slashes since the compiler expects files to be uniquely // identified by file name. - last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" " - "are not allowed in the virtual path"; return NULL; } @@ -450,13 +424,13 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( if (errno == EACCES) { // The file exists but is not readable. - last_error_message_ = "Read access is denied for file: " + - temp_disk_file; + // TODO(kenton): Find a way to report this more nicely. + GOOGLE_LOG(WARNING) << "Read access is denied for file: " << temp_disk_file; return NULL; } } } - last_error_message_ = "File not found."; + return NULL; } diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index f010fd0..7a2efc2 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -166,9 +166,6 @@ class LIBPROTOBUF_EXPORT Importer { return &pool_; } - void AddUnusedImportTrackFile(const string& file_name); - void ClearUnusedImportTrackFiles(); - private: SourceTreeDescriptorDatabase database_; DescriptorPool pool_; @@ -207,13 +204,6 @@ class LIBPROTOBUF_EXPORT SourceTree { // contain "." or ".." components. virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; - // If Open() returns NULL, calling this method immediately will return an - // description of the error. - // Subclasses should implement this method and return a meaningful value for - // better error reporting. - // TODO(xiaofeng): change this to a pure virtual function. - virtual string GetLastErrorMessage(); - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); }; @@ -283,21 +273,17 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); // implements SourceTree ------------------------------------------- - virtual io::ZeroCopyInputStream* Open(const string& filename); - - virtual string GetLastErrorMessage(); + io::ZeroCopyInputStream* Open(const string& filename); private: struct Mapping { string virtual_path; string disk_path; - inline Mapping(const string& virtual_path_param, - const string& disk_path_param) - : virtual_path(virtual_path_param), disk_path(disk_path_param) {} + inline Mapping(const string& virtual_path, const string& disk_path) + : virtual_path(virtual_path), disk_path(disk_path) {} }; vector<Mapping> mappings_; - string last_error_message_; // Like Open(), but returns the on-disk path in disk_file if disk_file is // non-NULL and the file could be successfully opened. diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index 387f135..56fad56 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,13 +33,12 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/stubs/hash.h> -#include <memory> #include <google/protobuf/compiler/importer.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/map-util.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/testing/file.h> #include <google/protobuf/stubs/strutil.h> @@ -93,10 +92,6 @@ class MockSourceTree : public SourceTree { } } - string GetLastErrorMessage() { - return "File not found."; - } - private: hash_map<string, const char*> files_; }; @@ -329,7 +324,6 @@ TEST_F(ImporterTest, MapFieldKeyNotScalar) { EXPECT_SUBSTRING("must name a scalar or string", error()); } - // =================================================================== class DiskSourceTreeTest : public testing::Test { @@ -342,7 +336,7 @@ class DiskSourceTreeTest : public testing::Test { if (File::Exists(dirnames_[i])) { File::DeleteRecursively(dirnames_[i], NULL, NULL); } - GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777)); + GOOGLE_CHECK(File::CreateDir(dirnames_[i].c_str(), DEFAULT_FILE_MODE)); } } @@ -353,11 +347,11 @@ class DiskSourceTreeTest : public testing::Test { } void AddFile(const string& filename, const char* contents) { - GOOGLE_CHECK_OK(File::SetContents(filename, contents, true)); + File::WriteStringToFileOrDie(contents, filename); } void AddSubdir(const string& dirname) { - GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777)); + GOOGLE_CHECK(File::CreateDir(dirname.c_str(), DEFAULT_FILE_MODE)); } void ExpectFileContents(const string& filename, @@ -377,11 +371,9 @@ class DiskSourceTreeTest : public testing::Test { EXPECT_EQ(expected_contents, file_contents); } - void ExpectCannotOpenFile(const string& filename, - const string& error_message) { + void ExpectFileNotFound(const string& filename) { scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename)); EXPECT_TRUE(input == NULL); - EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage()); } DiskSourceTree source_tree_; @@ -397,7 +389,7 @@ TEST_F(DiskSourceTreeTest, MapRoot) { source_tree_.MapPath("", dirnames_[0]); ExpectFileContents("foo", "Hello World!"); - ExpectCannotOpenFile("bar", "File not found."); + ExpectFileNotFound("bar"); } TEST_F(DiskSourceTreeTest, MapDirectory) { @@ -408,21 +400,15 @@ TEST_F(DiskSourceTreeTest, MapDirectory) { source_tree_.MapPath("baz", dirnames_[0]); ExpectFileContents("baz/foo", "Hello World!"); - ExpectCannotOpenFile("baz/bar", "File not found."); - ExpectCannotOpenFile("foo", "File not found."); - ExpectCannotOpenFile("bar", "File not found."); + ExpectFileNotFound("baz/bar"); + ExpectFileNotFound("foo"); + ExpectFileNotFound("bar"); // Non-canonical file names should not work. - ExpectCannotOpenFile("baz//foo", - "Backslashes, consecutive slashes, \".\", or \"..\" are " - "not allowed in the virtual path"); - ExpectCannotOpenFile("baz/../baz/foo", - "Backslashes, consecutive slashes, \".\", or \"..\" are " - "not allowed in the virtual path"); - ExpectCannotOpenFile("baz/./foo", - "Backslashes, consecutive slashes, \".\", or \"..\" are " - "not allowed in the virtual path"); - ExpectCannotOpenFile("baz/foo/", "File not found."); + ExpectFileNotFound("baz//foo"); + ExpectFileNotFound("baz/../baz/foo"); + ExpectFileNotFound("baz/./foo"); + ExpectFileNotFound("baz/foo/"); } TEST_F(DiskSourceTreeTest, NoParent) { @@ -434,12 +420,8 @@ TEST_F(DiskSourceTreeTest, NoParent) { source_tree_.MapPath("", dirnames_[0] + "/bar"); ExpectFileContents("baz", "Blah."); - ExpectCannotOpenFile("../foo", - "Backslashes, consecutive slashes, \".\", or \"..\" are " - "not allowed in the virtual path"); - ExpectCannotOpenFile("../bar/baz", - "Backslashes, consecutive slashes, \".\", or \"..\" are " - "not allowed in the virtual path"); + ExpectFileNotFound("../foo"); + ExpectFileNotFound("../bar/baz"); } TEST_F(DiskSourceTreeTest, MapFile) { @@ -449,7 +431,7 @@ TEST_F(DiskSourceTreeTest, MapFile) { source_tree_.MapPath("foo", dirnames_[0] + "/foo"); ExpectFileContents("foo", "Hello World!"); - ExpectCannotOpenFile("bar", "File not found."); + ExpectFileNotFound("bar"); } TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { @@ -463,7 +445,7 @@ TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { ExpectFileContents("foo", "Hello World!"); ExpectFileContents("bar", "Goodbye World!"); - ExpectCannotOpenFile("baz", "File not found."); + ExpectFileNotFound("baz"); } TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { @@ -471,7 +453,8 @@ TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { // directory is more-specific than a former one. // Create the "bar" directory so we can put a file in it. - GOOGLE_CHECK_OK(File::CreateDir(dirnames_[0] + "/bar", 0777)); + ASSERT_TRUE(File::CreateDir((dirnames_[0] + "/bar").c_str(), + DEFAULT_FILE_MODE)); // Add files and map paths. AddFile(dirnames_[0] + "/bar/foo", "Hello World!"); diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc deleted file mode 100644 index 7d21fe6..0000000 --- a/src/google/protobuf/compiler/java/java_context.cc +++ /dev/null @@ -1,195 +0,0 @@ -// 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 <google/protobuf/compiler/java/java_context.h> - -#include <google/protobuf/compiler/java/java_field.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/map_util.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -Context::Context(const FileDescriptor* file) - : name_resolver_(new ClassNameResolver) { - InitializeFieldGeneratorInfo(file); -} - -Context::~Context() { -} - -ClassNameResolver* Context::GetNameResolver() { - return name_resolver_.get(); -} - -namespace { -// Whether two fields have conflicting accessors (assuming name1 and name2 -// are different). name1 and name2 are field1 and field2's camel-case name -// respectively. -bool IsConflicting(const FieldDescriptor* field1, const string& name1, - const FieldDescriptor* field2, const string& name2, - string* info) { - if (field1->is_repeated()) { - if (field2->is_repeated()) { - // Both fields are repeated. - return false; - } else { - // field1 is repeated, and field2 is not. - if (name1 + "Count" == name2) { - *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generates the method \"" + - "get" + name1 + "Count()\""; - return true; - } - if (name1 + "List" == name2) { - *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generates the method \"" + - "get" + name1 + "List()\""; - return true; - } - // Well, there are obviously many more conflicting cases, but it probably - // doesn't worth the effort to exhaust all of them because they rarely - // happen and as we are continuing adding new methods/changing existing - // methods the number of different conflicting cases will keep growing. - // We can just add more cases here when they are found in the real world. - return false; - } - } else { - if (field2->is_repeated()) { - return IsConflicting(field2, name2, field1, name1, info); - } else { - // None of the two fields are repeated. - return false; - } - } -} -} // namespace - -void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) { - for (int i = 0; i < file->message_type_count(); ++i) { - InitializeFieldGeneratorInfoForMessage(file->message_type(i)); - } -} - -void Context::InitializeFieldGeneratorInfoForMessage( - const Descriptor* message) { - for (int i = 0; i < message->nested_type_count(); ++i) { - InitializeFieldGeneratorInfoForMessage(message->nested_type(i)); - } - vector<const FieldDescriptor*> fields; - for (int i = 0; i < message->field_count(); ++i) { - fields.push_back(message->field(i)); - } - InitializeFieldGeneratorInfoForFields(fields); - - for (int i = 0; i < message->oneof_decl_count(); ++i) { - const OneofDescriptor* oneof = message->oneof_decl(i); - OneofGeneratorInfo info; - info.name = UnderscoresToCamelCase(oneof->name(), false); - info.capitalized_name = UnderscoresToCamelCase(oneof->name(), true); - oneof_generator_info_map_[oneof] = info; - } -} - -void Context::InitializeFieldGeneratorInfoForFields( - const vector<const FieldDescriptor*>& fields) { - // Find out all fields that conflict with some other field in the same - // message. - vector<bool> is_conflict(fields.size()); - vector<string> conflict_reason(fields.size()); - for (int i = 0; i < fields.size(); ++i) { - const FieldDescriptor* field = fields[i]; - const string& name = UnderscoresToCapitalizedCamelCase(field); - for (int j = i + 1; j < fields.size(); ++j) { - const FieldDescriptor* other = fields[j]; - const string& other_name = UnderscoresToCapitalizedCamelCase(other); - if (name == other_name) { - is_conflict[i] = is_conflict[j] = true; - conflict_reason[i] = conflict_reason[j] = - "capitalized name of field \"" + field->name() + - "\" conflicts with field \"" + other->name() + "\""; - } else if (IsConflicting(field, name, other, other_name, - &conflict_reason[j])) { - is_conflict[i] = is_conflict[j] = true; - conflict_reason[i] = conflict_reason[j]; - } - } - if (is_conflict[i]) { - GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting " - << "with another field: " << conflict_reason[i]; - } - } - for (int i = 0; i < fields.size(); ++i) { - const FieldDescriptor* field = fields[i]; - FieldGeneratorInfo info; - info.name = UnderscoresToCamelCase(field); - info.capitalized_name = UnderscoresToCapitalizedCamelCase(field); - // For fields conflicting with some other fields, we append the field - // number to their field names in generated code to avoid conflicts. - if (is_conflict[i]) { - info.name += SimpleItoa(field->number()); - info.capitalized_name += SimpleItoa(field->number()); - info.disambiguated_reason = conflict_reason[i]; - } - field_generator_info_map_[field] = info; - } -} - -const FieldGeneratorInfo* Context::GetFieldGeneratorInfo( - const FieldDescriptor* field) const { - const FieldGeneratorInfo* result = - FindOrNull(field_generator_info_map_, field); - if (result == NULL) { - GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: " - << field->full_name(); - } - return result; -} - -const OneofGeneratorInfo* Context::GetOneofGeneratorInfo( - const OneofDescriptor* oneof) const { - const OneofGeneratorInfo* result = - FindOrNull(oneof_generator_info_map_, oneof); - if (result == NULL) { - GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: " - << oneof->name(); - } - return result; -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h deleted file mode 100644 index 5791445..0000000 --- a/src/google/protobuf/compiler/java/java_context.h +++ /dev/null @@ -1,95 +0,0 @@ -// 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. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ - -#include <map> -#include <memory> -#include <vector> - -#include <google/protobuf/stubs/common.h> - -namespace google { -namespace protobuf { - class FileDescriptor; - class FieldDescriptor; - class OneofDescriptor; - class Descriptor; - namespace compiler { - namespace java { - class ClassNameResolver; // name_resolver.h - } - } -} // namespace protobuf - -namespace protobuf { -namespace compiler { -namespace java { - -struct FieldGeneratorInfo; -struct OneofGeneratorInfo; -// A context object holds the information that is shared among all code -// generators. -class Context { - public: - explicit Context(const FileDescriptor* file); - ~Context(); - - // Get the name resolver associated with this context. The resolver - // can be used to map descriptors to Java class names. - ClassNameResolver* GetNameResolver(); - - // Get the FieldGeneratorInfo for a given field. - const FieldGeneratorInfo* GetFieldGeneratorInfo( - const FieldDescriptor* field) const; - - // Get the OneofGeneratorInfo for a given oneof. - const OneofGeneratorInfo* GetOneofGeneratorInfo( - const OneofDescriptor* oneof) const; - - private: - void InitializeFieldGeneratorInfo(const FileDescriptor* file); - void InitializeFieldGeneratorInfoForMessage(const Descriptor* message); - void InitializeFieldGeneratorInfoForFields( - const vector<const FieldDescriptor*>& fields); - - scoped_ptr<ClassNameResolver> name_resolver_; - map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_; - map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc deleted file mode 100644 index 663f0c9..0000000 --- a/src/google/protobuf/compiler/java/java_doc_comment.cc +++ /dev/null @@ -1,233 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/java/java_doc_comment.h> - -#include <vector> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -string EscapeJavadoc(const string& input) { - string result; - result.reserve(input.size() * 2); - - char prev = '*'; - - for (string::size_type i = 0; i < input.size(); i++) { - char c = input[i]; - switch (c) { - case '*': - // Avoid "/*". - if (prev == '/') { - result.append("*"); - } else { - result.push_back(c); - } - break; - case '/': - // Avoid "*/". - if (prev == '*') { - result.append("/"); - } else { - result.push_back(c); - } - break; - case '@': - // '@' starts javadoc tags including the @deprecated tag, which will - // cause a compile-time error if inserted before a declaration that - // does not have a corresponding @Deprecated annotation. - result.append("@"); - break; - case '<': - // Avoid interpretation as HTML. - result.append("<"); - break; - case '>': - // Avoid interpretation as HTML. - result.append(">"); - break; - case '&': - // Avoid interpretation as HTML. - result.append("&"); - break; - case '\\': - // Java interprets Unicode escape sequences anywhere! - result.append("\"); - break; - default: - result.push_back(c); - break; - } - - prev = c; - } - - return result; -} - -static void WriteDocCommentBodyForLocation( - io::Printer* printer, const SourceLocation& location) { - string comments = location.leading_comments.empty() ? - location.trailing_comments : location.leading_comments; - if (!comments.empty()) { - // TODO(kenton): Ideally we should parse the comment text as Markdown and - // write it back as HTML, but this requires a Markdown parser. For now - // we just use <pre> to get fixed-width text formatting. - - // If the comment itself contains block comment start or end markers, - // HTML-escape them so that they don't accidentally close the doc comment. - comments = EscapeJavadoc(comments); - - vector<string> lines = Split(comments, "\n"); - while (!lines.empty() && lines.back().empty()) { - lines.pop_back(); - } - - printer->Print( - " *\n" - " * <pre>\n"); - for (int i = 0; i < lines.size(); i++) { - // Most lines should start with a space. Watch out for lines that start - // with a /, since putting that right after the leading asterisk will - // close the comment. - if (!lines[i].empty() && lines[i][0] == '/') { - printer->Print(" * $line$\n", "line", lines[i]); - } else { - printer->Print(" *$line$\n", "line", lines[i]); - } - } - printer->Print(" * </pre>\n"); - } -} - -template <typename DescriptorType> -static void WriteDocCommentBody( - io::Printer* printer, const DescriptorType* descriptor) { - SourceLocation location; - if (descriptor->GetSourceLocation(&location)) { - WriteDocCommentBodyForLocation(printer, location); - } -} - -static string FirstLineOf(const string& value) { - string result = value; - - string::size_type pos = result.find_first_of('\n'); - if (pos != string::npos) { - result.erase(pos); - } - - // If line ends in an opening brace, make it "{ ... }" so it looks nice. - if (!result.empty() && result[result.size() - 1] == '{') { - result.append(" ... }"); - } - - return result; -} - -void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { - printer->Print( - "/**\n" - " * Protobuf type {@code $fullname$}\n", - "fullname", EscapeJavadoc(message->full_name())); - WriteDocCommentBody(printer, message); - printer->Print(" */\n"); -} - -void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { - // In theory we should have slightly different comments for setters, getters, - // etc., but in practice everyone already knows the difference between these - // so it's redundant information. - - // We use the field declaration as the first line of the comment, e.g.: - // optional string foo = 5; - // This communicates a lot of information about the field in a small space. - // If the field is a group, the debug string might end with {. - printer->Print( - "/**\n" - " * <code>$def$</code>\n", - "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDocCommentBody(printer, field); - printer->Print(" */\n"); -} - -void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { - printer->Print( - "/**\n" - " * Protobuf enum {@code $fullname$}\n", - "fullname", EscapeJavadoc(enum_->full_name())); - WriteDocCommentBody(printer, enum_); - printer->Print(" */\n"); -} - -void WriteEnumValueDocComment(io::Printer* printer, - const EnumValueDescriptor* value) { - printer->Print( - "/**\n" - " * <code>$def$</code>\n", - "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); - WriteDocCommentBody(printer, value); - printer->Print(" */\n"); -} - -void WriteServiceDocComment(io::Printer* printer, - const ServiceDescriptor* service) { - printer->Print( - "/**\n" - " * Protobuf service {@code $fullname$}\n", - "fullname", EscapeJavadoc(service->full_name())); - WriteDocCommentBody(printer, service); - printer->Print(" */\n"); -} - -void WriteMethodDocComment(io::Printer* printer, - const MethodDescriptor* method) { - printer->Print( - "/**\n" - " * <code>$def$</code>\n", - "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); - WriteDocCommentBody(printer, method); - printer->Print(" */\n"); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_doc_comment.h b/src/google/protobuf/compiler/java/java_doc_comment.h deleted file mode 100644 index 7d9535c..0000000 --- a/src/google/protobuf/compiler/java/java_doc_comment.h +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ - -#include <google/protobuf/descriptor.h> - -namespace google { -namespace protobuf { - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -void WriteMessageDocComment(io::Printer* printer, const Descriptor* message); -void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field); -void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_); -void WriteEnumValueDocComment(io::Printer* printer, - const EnumValueDescriptor* value); -void WriteServiceDocComment(io::Printer* printer, - const ServiceDescriptor* service); -void WriteMethodDocComment(io::Printer* printer, - const MethodDescriptor* method); - -// Exposed for testing only. -LIBPROTOC_EXPORT string EscapeJavadoc(const string& input); - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc deleted file mode 100644 index ae582ea..0000000 --- a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc +++ /dev/null @@ -1,67 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) - -#include <google/protobuf/compiler/java/java_doc_comment.h> - -#include <gtest/gtest.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { -namespace { - -TEST(JavaDocCommentTest, Escaping) { - EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz")); - EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz")); - EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}")); - EXPECT_EQ("<i>&</i>", EscapeJavadoc("<i>&</i>")); - EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar")); - EXPECT_EQ("@deprecated", EscapeJavadoc("@deprecated")); -} - -// TODO(kenton): It's hard to write a robust test of the doc comments -- we -// can only really compare the output against a golden value, which is a -// fairly tedious and fragile testing strategy. If we want to go that route, -// it probably makes sense to bite the bullet and write a test that compares -// the whole generated output for unittest.proto against a golden value, with -// a very simple script that can be run to regenerate it with the latest code. -// This would mean that updates to the golden file would have to be included -// in any change to the code generator, which would actually be fairly useful -// as it allows the reviewer to see clearly how the generated code is -// changing. - -} // namespace -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 668377a..85e39f5 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,11 +35,8 @@ #include <map> #include <string> -#include <google/protobuf/compiler/java/java_context.h> #include <google/protobuf/compiler/java/java_enum.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> @@ -49,22 +46,8 @@ namespace protobuf { namespace compiler { namespace java { -namespace { -bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { - if (descriptor->options().unknown_fields().field_count() > 0) return true; - for (int i = 0; i < descriptor->value_count(); ++i) { - const EnumValueDescriptor* value = descriptor->value(i); - if (value->options().unknown_fields().field_count() > 0) return true; - } - return false; -} -} // namespace - -EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, - bool immutable_api, - Context* context) - : descriptor_(descriptor), immutable_api_(immutable_api), - name_resolver_(context->GetNameResolver()) { +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) + : descriptor_(descriptor) { for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = @@ -84,7 +67,6 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { - WriteEnumDocComment(printer, descriptor_); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public enum $classname$\n" @@ -103,10 +85,6 @@ void EnumGenerator::Generate(io::Printer* printer) { vars["name"] = canonical_values_[i]->name(); vars["index"] = SimpleItoa(canonical_values_[i]->index()); vars["number"] = SimpleItoa(canonical_values_[i]->number()); - WriteEnumValueDocComment(printer, canonical_values_[i]); - if (canonical_values_[i]->options().deprecated()) { - printer->Print("@java.lang.Deprecated\n"); - } printer->Print(vars, "$name$($index$, $number$),\n"); } @@ -122,21 +100,10 @@ void EnumGenerator::Generate(io::Printer* printer) { vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); - WriteEnumValueDocComment(printer, aliases_[i].value); printer->Print(vars, "public static final $classname$ $name$ = $canonical_name$;\n"); } - for (int i = 0; i < descriptor_->value_count(); i++) { - map<string, string> vars; - vars["name"] = descriptor_->value(i)->name(); - vars["number"] = SimpleItoa(descriptor_->value(i)->number()); - WriteEnumValueDocComment(printer, descriptor_->value(i)); - printer->Print(vars, - "public static final int $name$_VALUE = $number$;\n"); - } - printer->Print("\n"); - // ----------------------------------------------------------------- printer->Print( @@ -171,7 +138,7 @@ void EnumGenerator::Generate(io::Printer* printer) { " internalValueMap =\n" " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" " public $classname$ findValueByNumber(int number) {\n" - " return $classname$.valueOf(number);\n" + " return $classname$.valueOf(number)\n;" " }\n" " };\n" "\n", @@ -197,87 +164,32 @@ void EnumGenerator::Generate(io::Printer* printer) { // at module init time because it wouldn't work with descriptor.proto, but // we can cache the value the first time getDescriptor() is called. if (descriptor_->containing_type() == NULL) { - if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { - printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", name_resolver_->GetClassName(descriptor_->file(), - immutable_api_), - "index", SimpleItoa(descriptor_->index())); - } else { - printer->Indent(); - if (EnumHasCustomOptions(descriptor_)) { - // We need to load the immutable classes in order to parse custom - // options. However, since file level enums (no outer class) are - // shared by immutable code and mutable code, the immutable classes - // may not exist. So we try to use Java reflection to retrieve the - // descriptor from immutable classes. - printer->Print( - "try {\n" - " java.lang.Class immutableFileClass =\n" - " java.lang.Class.forName(\"$immutable_file_class_name$\");\n" - " @java.lang.SuppressWarnings(\"unchecked\")\n" - " java.lang.reflect.Method m =\n" - " immutableFileClass.getMethod(\"getDescriptor\");\n" - " com.google.protobuf.Descriptors.FileDescriptor file =\n" - " (com.google.protobuf.Descriptors.FileDescriptor)\n" - " m.invoke(immutableFileClass);\n" - " return file.getEnumTypes().get($index$);\n" - "} catch (Exception e) {\n" - // Immutable classes cannot be found. Proceed as if custom options - // don't exist. - "}\n", - "immutable_file_class_name", - name_resolver_->GetImmutableClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); - } - printer->Print( - "return $immutable_package$.$descriptor_class$.getDescriptor()\n" - " .getEnumTypes().get($index$);\n", - "immutable_package", FileJavaPackage(descriptor_->file(), true), - "descriptor_class", - name_resolver_->GetDescriptorClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); - printer->Outdent(); - } + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", ClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); } else { printer->Print( - " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", - "parent", name_resolver_->GetClassName(descriptor_->containing_type(), - immutable_api_), - "descriptor", descriptor_->containing_type()->options() - .no_standard_descriptor_accessor() - ? "getDefaultInstance().getDescriptorForType()" - : "getDescriptor()", - "index", SimpleItoa(descriptor_->index())); + " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", + "parent", ClassName(descriptor_->containing_type()), + "index", SimpleItoa(descriptor_->index())); } printer->Print( "}\n" "\n" - "private static final $classname$[] VALUES = ", + "private static final $classname$[] VALUES = {\n" + " ", "classname", descriptor_->name()); - if (CanUseEnumValues()) { - // If the constants we are going to output are exactly the ones we - // have declared in the Java enum in the same order, then we can use - // the values() method that the Java compiler automatically generates - // for every enum. - printer->Print("values();\n"); - } else { - printer->Print( - "{\n" - " "); - for (int i = 0; i < descriptor_->value_count(); i++) { - printer->Print("$name$, ", - "name", descriptor_->value(i)->name()); - } - printer->Print( - "\n" - "};\n"); + for (int i = 0; i < descriptor_->value_count(); i++) { + printer->Print("$name$, ", + "name", descriptor_->value(i)->name()); } printer->Print( "\n" + "};\n" "public static $classname$ valueOf(\n" " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" " if (desc.getType() != getDescriptor()) {\n" @@ -285,26 +197,31 @@ void EnumGenerator::Generate(io::Printer* printer) { " \"EnumValueDescriptor is not for this type.\");\n" " }\n" " return VALUES[desc.getIndex()];\n" - "}\n" - "\n", + "}\n", "classname", descriptor_->name()); - - // index is only used for reflection; lite implementation does not need it - printer->Print("private final int index;\n"); } // ----------------------------------------------------------------- printer->Print( - "private final int value;\n\n" - "private $classname$(int index, int value) {\n", + "private final int index;\n" + "private final int value;\n" + "private $classname$(int index, int value) {\n" + " this.index = index;\n" + " this.value = value;\n" + "}\n", "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { - printer->Print(" this.index = index;\n"); + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + printer->Print( + "\n" + "static {\n" + " $file$.getDescriptor();\n" + "}\n", + "file", ClassName(descriptor_->file())); } - printer->Print( - " this.value = value;\n" - "}\n"); printer->Print( "\n" @@ -315,18 +232,6 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print("}\n\n"); } -bool EnumGenerator::CanUseEnumValues() { - if (canonical_values_.size() != descriptor_->value_count()) { - return false; - } - for (int i = 0; i < descriptor_->value_count(); i++) { - if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { - return false; - } - } - return true; -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h index a0d91f5..05ece1f 100644 --- a/src/google/protobuf/compiler/java/java_enum.h +++ b/src/google/protobuf/compiler/java/java_enum.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -41,12 +41,6 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } namespace io { class Printer; // printer.h } @@ -58,9 +52,7 @@ namespace java { class EnumGenerator { public: - explicit EnumGenerator(const EnumDescriptor* descriptor, - bool immutable_api, - Context* context); + explicit EnumGenerator(const EnumDescriptor* descriptor); ~EnumGenerator(); void Generate(io::Printer* printer); @@ -81,13 +73,6 @@ class EnumGenerator { }; vector<Alias> aliases_; - bool immutable_api_; - - Context* context_; - ClassNameResolver* name_resolver_; - - bool CanUseEnumValues(); - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 1f0c4af..af6b1cd 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,12 +35,9 @@ #include <map> #include <string> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_enum_field.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> @@ -52,456 +49,145 @@ namespace java { namespace { +// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of +// repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, map<string, string>* variables) { - SetCommonFieldVariables(descriptor, info, variables); - - (*variables)["type"] = - name_resolver->GetImmutableClassName(descriptor->enum_type()); - (*variables)["mutable_type"] = - name_resolver->GetMutableClassName(descriptor->enum_type()); - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = ClassName(descriptor->enum_type()); + (*variables)["default"] = DefaultValue(descriptor); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); - // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported - // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; - (*variables)["on_changed"] = - HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - - if (SupportFieldPresence(descriptor->file())) { - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - - // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - - (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); - } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"]; - } - - // For repated builders, one bit is used for whether the array is immutable. - (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - - (*variables)["get_has_field_bit_from_local"] = - GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); } } // namespace // =================================================================== -ImmutableEnumFieldGenerator:: -ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} - -ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} - -int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { - return 1; +EnumFieldGenerator:: +EnumFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetEnumVariables(descriptor, &variables_); } -int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} +EnumFieldGenerator::~EnumFieldGenerator() {} -void ImmutableEnumFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); -} - -void ImmutableEnumFieldGenerator:: +void EnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private $type$ $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); + "private boolean has$capitalized_name$;\n" + "private $type$ $name$_;\n" + "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" + "public $type$ get$capitalized_name$() { return $name$_; }\n"); } -void ImmutableEnumFieldGenerator:: +void EnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "private $type$ $name$_ = $default$;\n"); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + "public boolean has$capitalized_name$() {\n" + " return result.has$capitalized_name$();\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " return result.get$capitalized_name$();\n" + "}\n" + "public Builder set$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" + " result.has$capitalized_name$ = true;\n" + " result.$name$_ = value;\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$\n" - " $name$_ = $default$;\n" - " $on_changed$\n" + "}\n" + "public Builder clear$capitalized_name$() {\n" + " result.has$capitalized_name$ = false;\n" + " result.$name$_ = $default$;\n" " return this;\n" "}\n"); } -void ImmutableEnumFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for enums -} - -void ImmutableEnumFieldGenerator:: +void EnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void ImmutableEnumFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); -} - -void ImmutableEnumFieldGenerator:: +void EnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } else { - printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } -} - -void ImmutableEnumFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); -} - -void ImmutableEnumFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n"); - if (UseUnknownFieldSet(descriptor_->containing_type())) { - printer->Print(variables_, - " unknownFields.mergeVarintField($number$, rawValue);\n"); - } else { - printer->Print(variables_, - " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" - " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); - } - printer->Print(variables_, - "} else {\n" - " $set_has_field_bit_message$\n" - " $name$_ = value;\n" - "}\n"); -} - -void ImmutableEnumFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for enums -} - -void ImmutableEnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.writeEnum($number$, $name$_.getNumber());\n" - "}\n"); -} - -void ImmutableEnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, $name$_.getNumber());\n" + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" "}\n"); } -void ImmutableEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result &&\n" - " (get$capitalized_name$() == other.get$capitalized_name$());\n"); -} - -void ImmutableEnumFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + com.google.protobuf.Internal.hashEnum(\n" - " get$capitalized_name$());\n"); -} - -string ImmutableEnumFieldGenerator::GetBoxedType() const { - return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); -} - -// =================================================================== - -ImmutableEnumOneofFieldGenerator:: -ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableEnumFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); -} - -ImmutableEnumOneofFieldGenerator:: -~ImmutableEnumOneofFieldGenerator() {} - -void ImmutableEnumOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); -} - -void ImmutableEnumOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); -} - -void ImmutableEnumOneofFieldGenerator:: +void EnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + // Nothing to do here for enum types. } -void ImmutableEnumOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); -} - -void ImmutableEnumOneofFieldGenerator:: +void EnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n"); - if (UseUnknownFieldSet(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { printer->Print(variables_, - " unknownFields.mergeVarintField($number$, rawValue);\n"); + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); } else { printer->Print(variables_, - " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" - " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); + "if (value != null) {\n"); } printer->Print(variables_, - "} else {\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" + " set$capitalized_name$(value);\n" "}\n"); } -void ImmutableEnumOneofFieldGenerator:: +void EnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeEnum($number$, (($type$) $oneof_name$_).getNumber());\n" + "if (has$capitalized_name$()) {\n" + " output.writeEnum($number$, get$capitalized_name$().getNumber());\n" "}\n"); } -void ImmutableEnumOneofFieldGenerator:: +void EnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" + "if (has$capitalized_name$()) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, (($type$) $oneof_name$_).getNumber());\n" + " .computeEnumSize($number$, get$capitalized_name$().getNumber());\n" "}\n"); } -// =================================================================== - -RepeatedImmutableEnumFieldGenerator:: -RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +string EnumFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->enum_type()); } -RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} +// =================================================================== -int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const { - return 0; +RepeatedEnumFieldGenerator:: +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetEnumVariables(descriptor, &variables_); } -int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} -void RepeatedImmutableEnumFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); -} - -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.util.List<$type$> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + "public java.util.List<$type$> get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + "}\n" + "public int get$capitalized_name$Count() { return $name$_.size(); }\n" + "public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -512,165 +198,99 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - // One field is the list and the other field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value) {\n" + "public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(result.$name$_);\n" + "}\n" + "public int get$capitalized_name$Count() {\n" + " return result.get$capitalized_name$Count();\n" + "}\n" + "public $type$ get$capitalized_name$(int index) {\n" + " return result.get$capitalized_name$(index);\n" + "}\n" + "public Builder set$capitalized_name$(int index, $type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" + " result.$name$_.set(index, value);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + "}\n" + "public Builder add$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " }\n" + " result.$name$_.add(value);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder addAll$capitalized_name$(\n" + "}\n" + "public Builder addAll$capitalized_name$(\n" " java.lang.Iterable<? extends $type$> values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - " $on_changed$\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " }\n" + " super.addAll(values, result.$name$_);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $name$_ = java.util.Collections.emptyList();\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" + "}\n" + "public Builder clear$capitalized_name$() {\n" + " result.$name$_ = java.util.Collections.emptyList();\n" " return this;\n" "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for enums -} - -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); + // Initialized inline. } -void RepeatedImmutableEnumFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n"); -} - -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" " }\n" - " $on_changed$\n" + " result.$name$_.addAll(other.$name$_);\n" "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // The code below ensures that the result has an immutable list. If our - // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" + " result.$name$_ =\n" + " java.util.Collections.unmodifiableList(result.$name$_);\n" + "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { // Read and store the enum printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n"); - if (UseUnknownFieldSet(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { printer->Print(variables_, - " unknownFields.mergeVarintField($number$, rawValue);\n"); + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); } else { printer->Print(variables_, - " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" - " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); + "if (value != null) {\n"); } printer->Print(variables_, - " } else {\n" - " if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$type$>();\n" - " $set_mutable_bit_parser$;\n" - " }\n" - " $name$_.add(value);\n" + " add$capitalized_name$(value);\n" "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { // Wrap GenerateParsingCode's contents with a while loop. @@ -688,15 +308,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "input.popLimit(oldLimit);\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); -} - -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -704,18 +316,18 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnumNoTag($name$_.get(i).getNumber());\n" + "for ($type$ element : get$capitalized_name$List()) {\n" + " output.writeEnumNoTag(element.getNumber());\n" "}\n"); } else { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnum($number$, $name$_.get(i).getNumber());\n" + "for ($type$ element : get$capitalized_name$List()) {\n" + " output.writeEnum($number$, element.getNumber());\n" "}\n"); } } -void RepeatedImmutableEnumFieldGenerator:: +void RepeatedEnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -723,9 +335,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Indent(); printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" + "for ($type$ element : get$capitalized_name$List()) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n" + " .computeEnumSizeNoTag(element.getNumber());\n" "}\n"); printer->Print( "size += dataSize;\n"); @@ -738,7 +350,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}"); } else { printer->Print(variables_, - "size += $tag_size$ * $name$_.size();\n"); + "size += $tag_size$ * get$capitalized_name$List().size();\n"); } // cache the data size for packed fields. @@ -751,25 +363,8 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutableEnumFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n" - " get$capitalized_name$List());\n" - "}\n"); -} - -string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { - return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); +string RepeatedEnumFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->enum_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index 6a9535a..c54a0fa 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -41,113 +41,56 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} - -namespace protobuf { namespace compiler { namespace java { -class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { +class EnumFieldGenerator : public FieldGenerator { public: - explicit ImmutableEnumFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableEnumFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + explicit EnumFieldGenerator(const FieldDescriptor* descriptor); + ~EnumFieldGenerator(); + + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; -class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { +class RepeatedEnumFieldGenerator : public FieldGenerator { public: - ImmutableEnumOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableEnumOneofFieldGenerator(); + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); + ~RepeatedEnumFieldGenerator(); - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator); -}; - -class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { - public: - explicit RepeatedImmutableEnumFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableEnumFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 27cf416..903b0a9 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,168 +33,162 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/java/java_extension.h> - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/io/printer.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { namespace compiler { namespace java { -ImmutableExtensionGenerator::ImmutableExtensionGenerator( - const FieldDescriptor* descriptor, Context* context) - : descriptor_(descriptor), context_(context), - name_resolver_(context->GetNameResolver()) { +namespace { + +const char* TypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} + +ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { if (descriptor_->extension_scope() != NULL) { - scope_ = name_resolver_->GetImmutableClassName( - descriptor_->extension_scope()); + scope_ = ClassName(descriptor_->extension_scope()); } else { - scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); + scope_ = ClassName(descriptor_->file()); } } -ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} - -// Initializes the vars referenced in the generated code templates. -void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor, - const string& scope, - bool immutable, - ClassNameResolver* name_resolver, - map<string, string>* vars_pointer) { - map<string, string> &vars = *vars_pointer; - vars["scope"] = scope; - vars["name"] = UnderscoresToCamelCase(descriptor); - vars["containing_type"] = - name_resolver->GetClassName(descriptor->containing_type(), immutable); - vars["number"] = SimpleItoa(descriptor->number()); - vars["constant_name"] = FieldConstantName(descriptor); - vars["index"] = SimpleItoa(descriptor->index()); - vars["default"] = descriptor->is_repeated() ? - "" : DefaultValue(descriptor, immutable, name_resolver); - vars["type_constant"] = FieldTypeName(GetType(descriptor)); - vars["packed"] = descriptor->options().packed() ? "true" : "false"; - vars["enum_map"] = "null"; - vars["prototype"] = "null"; +ExtensionGenerator::~ExtensionGenerator() {} + +void ExtensionGenerator::Generate(io::Printer* printer) { + map<string, string> vars; + vars["name"] = UnderscoresToCamelCase(descriptor_); + vars["containing_type"] = ClassName(descriptor_->containing_type()); + vars["number"] = SimpleItoa(descriptor_->number()); + vars["constant_name"] = FieldConstantName(descriptor_); + vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite"; - JavaType java_type = GetJavaType(descriptor); + JavaType java_type = GetJavaType(descriptor_); string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: - singular_type = name_resolver->GetClassName(descriptor->message_type(), - immutable); - vars["prototype"] = singular_type + ".getDefaultInstance()"; + vars["type"] = ClassName(descriptor_->message_type()); break; case JAVATYPE_ENUM: - singular_type = name_resolver->GetClassName(descriptor->enum_type(), - immutable); - vars["enum_map"] = singular_type + ".internalGetValueMap()"; - break; - case JAVATYPE_STRING: - singular_type = "java.lang.String"; - break; - case JAVATYPE_BYTES: - singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]"; + vars["type"] = ClassName(descriptor_->enum_type()); break; default: - singular_type = BoxedPrimitiveTypeName(java_type); + vars["type"] = BoxedPrimitiveTypeName(java_type); break; } - vars["type"] = descriptor->is_repeated() ? - "java.util.List<" + singular_type + ">" : singular_type; - vars["singular_type"] = singular_type; + + printer->Print(vars, + "public static final int $constant_name$ = $number$;\n"); + if (descriptor_->is_repeated()) { + printer->Print(vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" + " $containing_type$,\n" + " java.util.List<$type$>> $name$ =\n" + " com.google.protobuf.GeneratedMessage$lite$\n" + " .newGeneratedExtension();\n"); + } else { + printer->Print(vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ =\n" + " com.google.protobuf.GeneratedMessage$lite$\n" + " .newGeneratedExtension();\n"); + } } -void ImmutableExtensionGenerator::Generate(io::Printer* printer) { +void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) { map<string, string> vars; - const bool kUseImmutableNames = true; - InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, - &vars); - printer->Print(vars, - "public static final int $constant_name$ = $number$;\n"); + vars["name"] = UnderscoresToCamelCase(descriptor_); + vars["scope"] = scope_; + vars["index"] = SimpleItoa(descriptor_->index()); + vars["extendee"] = ClassName(descriptor_->containing_type()); + vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_); + vars["number"] = SimpleItoa(descriptor_->number()); + vars["type_constant"] = TypeName(GetType(descriptor_)); + vars["packed"] = descriptor_->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; + + JavaType java_type = GetJavaType(descriptor_); + string singular_type; + switch (java_type) { + case JAVATYPE_MESSAGE: + vars["type"] = ClassName(descriptor_->message_type()); + vars["prototype"] = ClassName(descriptor_->message_type()) + + ".getDefaultInstance()"; + break; + case JAVATYPE_ENUM: + vars["type"] = ClassName(descriptor_->enum_type()); + vars["enum_map"] = ClassName(descriptor_->enum_type()) + + ".internalGetValueMap()"; + break; + default: + vars["type"] = BoxedPrimitiveTypeName(java_type); + break; + } - WriteFieldDocComment(printer, descriptor_); if (HasDescriptorMethods(descriptor_->file())) { - // Non-lite extensions - if (descriptor_->extension_scope() == NULL) { - // Non-nested - printer->Print( - vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" - " .newFileScopedGeneratedExtension(\n" - " $singular_type$.class,\n" - " $prototype$);\n"); - } else { - // Nested - printer->Print( - vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" - " .newMessageScopedGeneratedExtension(\n" - " $scope$.getDefaultInstance(),\n" - " $index$,\n" - " $singular_type$.class,\n" - " $prototype$);\n"); - } + printer->Print(vars, + "$scope$.$name$.internalInit(\n" + " $scope$.getDescriptor().getExtensions().get($index$),\n" + " $type$.class);\n"); } else { - // Lite extensions if (descriptor_->is_repeated()) { - printer->Print( - vars, - "public static final\n" - " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" - " .newRepeatedGeneratedExtension(\n" - " $containing_type$.getDefaultInstance(),\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" - " $packed$,\n" - " $singular_type$.class);\n"); + printer->Print(vars, + "$scope$.$name$.internalInitRepeated(\n" + " $extendee$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$);\n"); } else { - printer->Print( - vars, - "public static final\n" - " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" - " .newSingularGeneratedExtension(\n" - " $containing_type$.getDefaultInstance(),\n" - " $default$,\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" - " $singular_type$.class);\n"); + printer->Print(vars, + "$scope$.$name$.internalInitSingular(\n" + " $extendee$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); } } } -void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( - io::Printer* printer) { - if (descriptor_->extension_scope() == NULL && - HasDescriptorMethods(descriptor_->file())) { - // Only applies to non-nested, non-lite extensions. - printer->Print( - "$name$.internalInit(descriptor.getExtensions().get($index$));\n", - "name", UnderscoresToCamelCase(descriptor_), - "index", SimpleItoa(descriptor_->index())); - } -} - -void ImmutableExtensionGenerator::GenerateRegistrationCode( - io::Printer* printer) { +void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { printer->Print( "registry.add($scope$.$name$);\n", "scope", scope_, diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index f1701fb..1e42304 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,7 +35,6 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ -#include <map> #include <string> #include <google/protobuf/stubs/common.h> @@ -43,12 +42,6 @@ namespace google { namespace protobuf { class FieldDescriptor; // descriptor.h - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } namespace io { class Printer; // printer.h } @@ -63,42 +56,17 @@ namespace java { // since extensions are just simple identifiers with interesting types. class ExtensionGenerator { public: - explicit ExtensionGenerator() {} - virtual ~ExtensionGenerator() {} - - virtual void Generate(io::Printer* printer) = 0; - virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0; - virtual void GenerateRegistrationCode(io::Printer* printer) = 0; + explicit ExtensionGenerator(const FieldDescriptor* descriptor); + ~ExtensionGenerator(); - protected: - static void InitTemplateVars(const FieldDescriptor* descriptor, - const string& scope, - bool immutable, - ClassNameResolver* name_resolver, - map<string, string>* vars_pointer); + void Generate(io::Printer* printer); + void GenerateInitializationCode(io::Printer* printer); + void GenerateRegistrationCode(io::Printer* printer); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); -}; - -class ImmutableExtensionGenerator : public ExtensionGenerator { - public: - explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor, - Context* context); - virtual ~ImmutableExtensionGenerator(); - - virtual void Generate(io::Printer* printer); - virtual void GenerateNonNestedInitializationCode(io::Printer* printer); - virtual void GenerateRegistrationCode(io::Printer* printer); - - protected: const FieldDescriptor* descriptor_; - Context* context_; - ClassNameResolver* name_resolver_; string scope_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; } // namespace java @@ -106,4 +74,4 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index d7b0f3f..978c8f3 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,178 +33,77 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/java/java_field.h> - -#include <memory> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_enum_field.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_lazy_message_field.h> -#include <google/protobuf/compiler/java/java_message_field.h> #include <google/protobuf/compiler/java/java_primitive_field.h> -#include <google/protobuf/compiler/java/java_string_field.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/compiler/java/java_enum_field.h> +#include <google/protobuf/compiler/java/java_message_field.h> +#include <google/protobuf/stubs/common.h> namespace google { namespace protobuf { namespace compiler { namespace java { -namespace { - -ImmutableFieldGenerator* MakeImmutableGenerator( - const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, - Context* context) { - if (field->is_repeated()) { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - if (IsLazy(field)) { - return new RepeatedImmutableLazyMessageFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } else { - return new RepeatedImmutableMessageFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - case JAVATYPE_ENUM: - return new RepeatedImmutableEnumFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - case JAVATYPE_STRING: - return new RepeatedImmutableStringFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - default: - return new RepeatedImmutablePrimitiveFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - } else { - if (field->containing_oneof()) { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - if (IsLazy(field)) { - return new ImmutableLazyMessageOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } else { - return new ImmutableMessageOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - case JAVATYPE_ENUM: - return new ImmutableEnumOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - case JAVATYPE_STRING: - return new ImmutableStringOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - default: - return new ImmutablePrimitiveOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - } else { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - if (IsLazy(field)) { - return new ImmutableLazyMessageFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } else { - return new ImmutableMessageFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - case JAVATYPE_ENUM: - return new ImmutableEnumFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - case JAVATYPE_STRING: - return new ImmutableStringFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - default: - return new ImmutablePrimitiveFieldGenerator( - field, messageBitIndex, builderBitIndex, context); - } - } - } -} - +FieldGenerator::~FieldGenerator() {} -static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { +void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const { // Reaching here indicates a bug. Cases are: - // - This FieldGenerator should support packing, - // but this method should be overridden. - // - This FieldGenerator doesn't support packing, and this method - // should never have been called. + // - This FieldGenerator should support packing, but this method should be + // overridden. + // - This FieldGenerator doesn't support packing, and this method should + // never have been called. GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " << "called on field generator that does not support packing."; } -} // namespace +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_( + new scoped_ptr<FieldGenerator>[descriptor->field_count()]), + extension_generators_( + new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) { -ImmutableFieldGenerator::~ImmutableFieldGenerator() {} - -void ImmutableFieldGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - ReportUnexpectedPackedFieldsCall(printer); -} - -// =================================================================== - -template <> -FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( - const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), - field_generators_(new scoped_ptr< - ImmutableFieldGenerator>[descriptor->field_count()]) { - - // Construct all the FieldGenerators and assign them bit indices for their - // bit fields. - int messageBitIndex = 0; - int builderBitIndex = 0; + // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - ImmutableFieldGenerator* generator = MakeImmutableGenerator( - descriptor->field(i), messageBitIndex, builderBitIndex, context); - field_generators_[i].reset(generator); - messageBitIndex += generator->GetNumBitsForMessage(); - builderBitIndex += generator->GetNumBitsForBuilder(); + field_generators_[i].reset(MakeGenerator(descriptor->field(i))); + } + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset(MakeGenerator(descriptor->extension(i))); } } -template<> -FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} - - -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - const FieldGeneratorInfo* info, - map<string, string>* variables) { - (*variables)["field_name"] = descriptor->name(); - (*variables)["name"] = info->name; - (*variables)["capitalized_name"] = info->capitalized_name; - (*variables)["disambiguated_reason"] = info->disambiguated_reason; - (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); +FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) { + if (field->is_repeated()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + return new RepeatedMessageFieldGenerator(field); + case JAVATYPE_ENUM: + return new RepeatedEnumFieldGenerator(field); + default: + return new RepeatedPrimitiveFieldGenerator(field); + } + } else { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + return new MessageFieldGenerator(field); + case JAVATYPE_ENUM: + return new EnumFieldGenerator(field); + default: + return new PrimitiveFieldGenerator(field); + } + } } -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - const OneofGeneratorInfo* info, - map<string, string>* variables) { - (*variables)["oneof_name"] = info->name; - (*variables)["oneof_capitalized_name"] = info->capitalized_name; - (*variables)["oneof_index"] = - SimpleItoa(descriptor->containing_oneof()->index()); - (*variables)["set_oneof_case_message"] = info->name + - "Case_ = " + SimpleItoa(descriptor->number()); - (*variables)["clear_oneof_case_message"] = info->name + - "Case_ = 0"; - (*variables)["has_oneof_case_message"] = info->name + - "Case_ == " + SimpleItoa(descriptor->number()); +FieldGeneratorMap::~FieldGeneratorMap() {} + +const FieldGenerator& FieldGeneratorMap::get( + const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; } -void PrintExtraFieldInfo(const map<string, string>& variables, - io::Printer* printer) { - const map<string, string>::const_iterator it = - variables.find("disambiguated_reason"); - if (it != variables.end() && !it->second.empty()) { - printer->Print( - variables, - "// An alternative name is used for field \"$field_name$\" because:\n" - "// $disambiguated_reason$\n"); - } +const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { + return *extension_generators_[index]; } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index db339d5..f5bef7a 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,23 +35,14 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ -#include <map> -#include <memory> #include <string> - #include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -59,101 +50,46 @@ namespace protobuf { namespace compiler { namespace java { -class ImmutableFieldGenerator { +class FieldGenerator { public: - ImmutableFieldGenerator() {} - virtual ~ImmutableFieldGenerator(); + FieldGenerator() {} + virtual ~FieldGenerator(); - virtual int GetNumBitsForMessage() const = 0; - virtual int GetNumBitsForBuilder() const = 0; - virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; virtual void GenerateInitializationCode(io::Printer* printer) const = 0; - virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateBuildingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; - virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; - virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) - const = 0; - - virtual void GenerateEqualsCode(io::Printer* printer) const = 0; - virtual void GenerateHashCode(io::Printer* printer) const = 0; virtual string GetBoxedType() const = 0; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); }; - // Convenience class which constructs FieldGenerators for a Descriptor. -template<typename FieldGeneratorType> class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor, - Context* context); + explicit FieldGeneratorMap(const Descriptor* descriptor); ~FieldGeneratorMap(); - const FieldGeneratorType& get(const FieldDescriptor* field) const; + const FieldGenerator& get(const FieldDescriptor* field) const; + const FieldGenerator& get_extension(int index) const; private: const Descriptor* descriptor_; - Context* context_; - ClassNameResolver* name_resolver_; - scoped_array<scoped_ptr<FieldGeneratorType> > field_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); -}; - -template<typename FieldGeneratorType> -inline const FieldGeneratorType& -FieldGeneratorMap<FieldGeneratorType>::get(const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); - return *field_generators_[field->index()]; -} + scoped_array<scoped_ptr<FieldGenerator> > field_generators_; + scoped_array<scoped_ptr<FieldGenerator> > extension_generators_; -// Instantiate template for mutable and immutable maps. -template<> -FieldGeneratorMap<ImmutableFieldGenerator>:: -FieldGeneratorMap(const Descriptor* descriptor, - Context* context); + static FieldGenerator* MakeGenerator(const FieldDescriptor* field); -template<> -FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap(); - - -// Field information used in FieldGeneartors. -struct FieldGeneratorInfo { - string name; - string capitalized_name; - string disambiguated_reason; -}; - -// Oneof information used in OneofFieldGeneartors. -struct OneofGeneratorInfo { - string name; - string capitalized_name; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; -// Set some common variables used in variable FieldGenerators. -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - const FieldGeneratorInfo* info, - map<string, string>* variables); - -// Set some common oneof variables used in OneofFieldGenerators. -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - const OneofGeneratorInfo* info, - map<string, string>* variables); - -// Print useful comments before a field's accessors. -void PrintExtraFieldInfo(const map<string, string>& variables, - io::Printer* printer); - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 231b144..7ea127c 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,23 +33,15 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/java/java_file.h> - -#include <memory> - -#include <google/protobuf/compiler/java/java_context.h> #include <google/protobuf/compiler/java/java_enum.h> +#include <google/protobuf/compiler/java/java_service.h> #include <google/protobuf/compiler/java/java_extension.h> -#include <google/protobuf/compiler/java/java_generator_factory.h> #include <google/protobuf/compiler/java/java_helpers.h> #include <google/protobuf/compiler/java/java_message.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/compiler/java/java_service.h> -#include <google/protobuf/compiler/java/java_shared_code_generator.h> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/dynamic_message.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -59,24 +51,18 @@ namespace java { namespace { - -// Recursively searches the given message to collect extensions. -// Returns true if all the extensions can be recognized. The extensions will be -// appended in to the extensions parameter. -// Returns false when there are unknown fields, in which case the data in the -// extensions output parameter is not reliable and should be discarded. -bool CollectExtensions(const Message& message, - vector<const FieldDescriptor*>* extensions) { +// Recursively searches the given message to see if it contains any extensions. +bool UsesExtensions(const Message& message) { const Reflection* reflection = message.GetReflection(); - // There are unknown fields that could be extensions, thus this call fails. - if (reflection->GetUnknownFields(message).field_count() > 0) return false; + // We conservatively assume that unknown fields are extensions. + if (reflection->GetUnknownFields(message).field_count() > 0) return true; vector<const FieldDescriptor*> fields; reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { - if (fields[i]->is_extension()) extensions->push_back(fields[i]); + if (fields[i]->is_extension()) return true; if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) { if (fields[i]->is_repeated()) { @@ -84,83 +70,25 @@ bool CollectExtensions(const Message& message, for (int j = 0; j < size; j++) { const Message& sub_message = reflection->GetRepeatedMessage(message, fields[i], j); - if (!CollectExtensions(sub_message, extensions)) return false; + if (UsesExtensions(sub_message)) return true; } } else { const Message& sub_message = reflection->GetMessage(message, fields[i]); - if (!CollectExtensions(sub_message, extensions)) return false; + if (UsesExtensions(sub_message)) return true; } } } - return true; -} - -// Finds all extensions in the given message and its sub-messages. If the -// message contains unknown fields (which could be extensions), then those -// extensions are defined in alternate_pool. -// The message will be converted to a DynamicMessage backed by alternate_pool -// in order to handle this case. -void CollectExtensions(const FileDescriptorProto& file_proto, - const DescriptorPool& alternate_pool, - vector<const FieldDescriptor*>* extensions, - const string& file_data) { - if (!CollectExtensions(file_proto, extensions)) { - // There are unknown fields in the file_proto, which are probably - // extensions. We need to parse the data into a dynamic message based on the - // builder-pool to find out all extensions. - const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName( - file_proto.GetDescriptor()->full_name()); - GOOGLE_CHECK(file_proto_desc) - << "Find unknown fields in FileDescriptorProto when building " - << file_proto.name() - << ". It's likely that those fields are custom options, however, " - "descriptor.proto is not in the transitive dependencies. " - "This normally should not happen. Please report a bug."; - DynamicMessageFactory factory; - scoped_ptr<Message> dynamic_file_proto( - factory.GetPrototype(file_proto_desc)->New()); - GOOGLE_CHECK(dynamic_file_proto.get() != NULL); - GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data)); - - // Collect the extensions again from the dynamic message. There should be no - // more unknown fields this time, i.e. all the custom options should be - // parsed as extensions now. - extensions->clear(); - GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) - << "Find unknown fields in FileDescriptorProto when building " - << file_proto.name() - << ". It's likely that those fields are custom options, however, " - "those options cannot be recognized in the builder pool. " - "This normally should not happen. Please report a bug."; - } + return false; } } // namespace -FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api) - : file_(file), - java_package_(FileJavaPackage(file, immutable_api)), - message_generators_( - new scoped_ptr<MessageGenerator>[file->message_type_count()]), - extension_generators_( - new scoped_ptr<ExtensionGenerator>[file->extension_count()]), - context_(new Context(file)), - name_resolver_(context_->GetNameResolver()), - immutable_api_(immutable_api) { - classname_ = name_resolver_->GetFileClassName(file, immutable_api); - generator_factory_.reset( - new ImmutableGeneratorFactory(context_.get())); - for (int i = 0; i < file_->message_type_count(); ++i) { - message_generators_[i].reset( - generator_factory_->NewMessageGenerator(file_->message_type(i))); - } - for (int i = 0; i < file_->extension_count(); ++i) { - extension_generators_[i].reset( - generator_factory_->NewExtensionGenerator(file_->extension(i))); - } -} +FileGenerator::FileGenerator(const FileDescriptor* file) + : file_(file), + java_package_(FileJavaPackage(file)), + classname_(FileClassName(file)) {} FileGenerator::~FileGenerator() {} @@ -169,7 +97,25 @@ bool FileGenerator::Validate(string* error) { // problem that leads to Java compile errors that can be hard to understand. // It's especially bad when using the java_multiple_files, since we would // end up overwriting the outer class with one of the inner ones. - if (name_resolver_->HasConflictingClassName(file_, classname_)) { + + bool found_conflict = false; + for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) { + if (file_->enum_type(i)->name() == classname_) { + found_conflict = true; + } + } + for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) { + if (file_->message_type(i)->name() == classname_) { + found_conflict = true; + } + } + for (int i = 0; i < file_->service_count() && !found_conflict; i++) { + if (file_->service(i)->name() == classname_) { + found_conflict = true; + } + } + + if (found_conflict) { error->assign(file_->name()); error->append( ": Cannot generate Java output because the file's outer class name, \""); @@ -180,29 +126,7 @@ bool FileGenerator::Validate(string* error) { "option to specify a different outer class name for the .proto file."); return false; } - // If java_outer_classname option is not set and the default outer class name - // conflicts with a type defined in the message, we will append a suffix to - // avoid the conflict. This allows proto1 API protos to be dual-compiled into - // proto2 API without code change. When this happens we'd like to issue an - // warning to let the user know that the outer class name has been changed. - // Although we only do this automatic naming fix for immutable API, mutable - // outer class name will also be affected as it's contructed from immutable - // outer class name with an additional "Mutable" prefix. Since the naming - // change in mutable API is not caused by a naming conflict, we generate the - // warning for immutable API only. - if (immutable_api_ && !file_->options().has_java_outer_classname()) { - string default_classname = - name_resolver_->GetFileDefaultImmutableClassName(file_); - if (default_classname != classname_) { - GOOGLE_LOG(WARNING) << file_->name() << ": The default outer class name, \"" - << default_classname << "\", conflicts with a type " - << "declared in the proto file and an alternative outer " - << "class name is used: \"" << classname_ << "\". To avoid " - << "this warning, please use the java_outer_classname " - << "option to specify a different outer class name for " - << "the .proto file."; - } - } + return true; } @@ -236,11 +160,12 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->GenerateRegistrationCode(printer); + ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateExtensionRegistrationCode(printer); + MessageGenerator(file_->message_type(i)) + .GenerateExtensionRegistrationCode(printer); } printer->Outdent(); @@ -249,20 +174,16 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - if (!MultipleJavaFiles(file_, immutable_api_)) { + if (!file_->options().java_multiple_files()) { for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator(file_->enum_type(i), immutable_api_, context_.get()) - .Generate(printer); + EnumGenerator(file_->enum_type(i)).Generate(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateInterface(printer); - message_generators_[i]->Generate(printer); + MessageGenerator(file_->message_type(i)).Generate(printer); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { - scoped_ptr<ServiceGenerator> generator( - generator_factory_->NewServiceGenerator(file_->service(i))); - generator->Generate(printer); + ServiceGenerator(file_->service(i)).Generate(printer); } } } @@ -270,29 +191,34 @@ void FileGenerator::Generate(io::Printer* printer) { // Extensions must be generated in the outer class since they are values, // not classes. for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->Generate(printer); + ExtensionGenerator(file_->extension(i)).Generate(printer); } // Static variables. for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariables(printer); + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer); } printer->Print("\n"); if (HasDescriptorMethods(file_)) { - if (immutable_api_) { - GenerateDescriptorInitializationCodeForImmutable(printer); - } else { - GenerateDescriptorInitializationCodeForMutable(printer); - } + GenerateEmbeddedDescriptor(printer); } else { printer->Print( "static {\n"); printer->Indent(); for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariableInitializers(printer); + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); + } + + for (int i = 0; i < file_->extension_count(); i++) { + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(file_->extension(i)) + .GenerateInitializationCode(printer); } printer->Outdent(); @@ -300,6 +226,13 @@ void FileGenerator::Generate(io::Printer* printer) { "}\n"); } + // Dummy function we can use to force the static initialization block to + // run. Needed by inner classes. Cannot be private due to + // java_multiple_files option. + printer->Print( + "\n" + "public static void internalForceInit() {}\n"); + printer->Print( "\n" "// @@protoc_insertion_point(outer_class_scope)\n"); @@ -308,8 +241,23 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("}\n"); } -void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( - io::Printer* printer) { +void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. We unfortunately have to put it in + // a string literal, not a byte array, because apparently using a literal + // byte array causes the Java compiler to generate *instructions* to + // initialize each and every byte of the array, e.g. as if you typed: + // b[0] = 123; b[1] = 456; b[2] = 789; + // This makes huge bytecode files and can easily hit the compiler's internal + // code size limits (error "code to large"). String literals are apparently + // embedded raw, which is what we want. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + + string file_data; + file_proto.SerializeToString(&file_data); + printer->Print( "public static com.google.protobuf.Descriptors.FileDescriptor\n" " getDescriptor() {\n" @@ -317,135 +265,104 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( "}\n" "private static com.google.protobuf.Descriptors.FileDescriptor\n" " descriptor;\n" - "static {\n"); + "static {\n" + " java.lang.String[] descriptorData = {\n"); + printer->Indent(); printer->Indent(); - SharedCodeGenerator shared_code_generator(file_); - shared_code_generator.GenerateDescriptors(printer); + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + if (i > 0) { + // Every 400 lines, start a new string literal, in order to avoid the + // 64k length limit. + if (i % 400 == 0) { + printer->Print(",\n"); + } else { + printer->Print(" +\n"); + } + } + printer->Print("\"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + + printer->Outdent(); + printer->Print("\n};\n"); + + // ----------------------------------------------------------------- + // Create the InternalDescriptorAssigner. + + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner assigner =\n" + " new com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner() {\n" + " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" + " com.google.protobuf.Descriptors.FileDescriptor root) {\n" + " descriptor = root;\n"); + + printer->Indent(); + printer->Indent(); + printer->Indent(); for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariableInitializers(printer); + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); } + for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(file_->extension(i)) + .GenerateInitializationCode(printer); } - // Proto compiler builds a DescriptorPool, which holds all the descriptors to - // generate, when processing the ".proto" files. We call this DescriptorPool - // the parsed pool (a.k.a. file_->pool()). - // - // Note that when users try to extend the (.*)DescriptorProto in their - // ".proto" files, it does not affect the pre-built FileDescriptorProto class - // in proto compiler. When we put the descriptor data in the file_proto, those - // extensions become unknown fields. - // - // Now we need to find out all the extension value to the (.*)DescriptorProto - // in the file_proto message, and prepare an ExtensionRegistry to return. - // - // To find those extensions, we need to parse the data into a dynamic message - // of the FileDescriptor based on the builder-pool, then we can use - // reflections to find all extension fields - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); - vector<const FieldDescriptor*> extensions; - CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); - - if (extensions.size() > 0) { - // Must construct an ExtensionRegistry containing all existing extensions - // and use it to parse the descriptor data again to recognize extensions. + if (UsesExtensions(file_proto)) { + // Must construct an ExtensionRegistry containing all possible extensions + // and return it. printer->Print( "com.google.protobuf.ExtensionRegistry registry =\n" - " com.google.protobuf.ExtensionRegistry.newInstance();\n"); - for (int i = 0; i < extensions.size(); i++) { - scoped_ptr<ExtensionGenerator> generator( - generator_factory_->NewExtensionGenerator(extensions[i])); - generator->GenerateRegistrationCode(printer); - } - printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalUpdateFileDescriptor(descriptor, registry);\n"); - } - - // Force descriptor initialization of all dependencies. - for (int i = 0; i < file_->dependency_count(); i++) { - if (ShouldIncludeDependency(file_->dependency(i), true)) { - string dependency = - name_resolver_->GetImmutableClassName(file_->dependency(i)); + " com.google.protobuf.ExtensionRegistry.newInstance();\n" + "registerAllExtensions(registry);\n"); + for (int i = 0; i < file_->dependency_count(); i++) { printer->Print( - "$dependency$.getDescriptor();\n", - "dependency", dependency); + "$dependency$.registerAllExtensions(registry);\n", + "dependency", ClassName(file_->dependency(i))); } + printer->Print( + "return registry;\n"); + } else { + printer->Print( + "return null;\n"); } printer->Outdent(); - printer->Print( - "}\n"); -} - -void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) { - printer->Print( - "public static com.google.protobuf.Descriptors.FileDescriptor\n" - " getDescriptor() {\n" - " return descriptor;\n" - "}\n" - "private static com.google.protobuf.Descriptors.FileDescriptor\n" - " descriptor;\n" - "static {\n"); - printer->Indent(); + printer->Outdent(); + printer->Outdent(); printer->Print( - "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", - "immutable_package", FileJavaPackage(file_, true), - "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); + " }\n" + " };\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariableInitializers(printer); - } - for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->GenerateNonNestedInitializationCode(printer); - } - - // Check if custom options exist. If any, try to load immutable classes since - // custom options are only represented with immutable messages. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); - vector<const FieldDescriptor*> extensions; - CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + // ----------------------------------------------------------------- + // Invoke internalBuildGeneratedFileFrom() to build the file. - if (extensions.size() > 0) { - // Try to load immutable messages' outer class. Its initialization code - // will take care of interpreting custom options. - printer->Print( - "try {\n" - // Note that we have to load the immutable class dynamically here as - // we want the mutable code to be independent from the immutable code - // at compile time. It is required to implement dual-compile for - // mutable and immutable API in blaze. - " java.lang.Class immutableClass = java.lang.Class.forName(\n" - " \"$immutable_classname$\");\n" - "} catch (java.lang.ClassNotFoundException e) {\n" - // The immutable class can not be found. Custom options are left - // as unknown fields. - // TODO(xiaofeng): inform the user with a warning? - "}\n", - "immutable_classname", name_resolver_->GetImmutableClassName(file_)); - } + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalBuildGeneratedFileFrom(descriptorData,\n" + " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); - // Force descriptor initialization of all dependencies. for (int i = 0; i < file_->dependency_count(); i++) { - if (ShouldIncludeDependency(file_->dependency(i), false)) { - string dependency = name_resolver_->GetMutableClassName( - file_->dependency(i)); + if (ShouldIncludeDependency(file_->dependency(i))) { printer->Print( - "$dependency$.getDescriptor();\n", - "dependency", dependency); + " $dependency$.getDescriptor(),\n", + "dependency", ClassName(file_->dependency(i))); } } + printer->Print( + " }, assigner);\n"); + printer->Outdent(); printer->Print( "}\n"); @@ -455,22 +372,18 @@ template<typename GeneratorClass, typename DescriptorClass> static void GenerateSibling(const string& package_dir, const string& java_package, const DescriptorClass* descriptor, - GeneratorContext* context, - vector<string>* file_list, - const string& name_suffix, - GeneratorClass* generator, - void (GeneratorClass::*pfn)(io::Printer* printer)) { - string filename = package_dir + descriptor->name() + name_suffix + ".java"; + OutputDirectory* output_directory, + vector<string>* file_list) { + string filename = package_dir + descriptor->name() + ".java"; file_list->push_back(filename); - scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); + scoped_ptr<io::ZeroCopyOutputStream> output( + output_directory->Open(filename)); io::Printer printer(output.get(), '$'); printer.Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n", - "filename", descriptor->file()->name()); + "\n"); if (!java_package.empty()) { printer.Print( "package $package$;\n" @@ -478,53 +391,34 @@ static void GenerateSibling(const string& package_dir, "package", java_package); } - (generator->*pfn)(&printer); + GeneratorClass(descriptor).Generate(&printer); } void FileGenerator::GenerateSiblings(const string& package_dir, - GeneratorContext* context, + OutputDirectory* output_directory, vector<string>* file_list) { - if (MultipleJavaFiles(file_, immutable_api_)) { + if (file_->options().java_multiple_files()) { for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator generator(file_->enum_type(i), immutable_api_, - context_.get()); GenerateSibling<EnumGenerator>(package_dir, java_package_, file_->enum_type(i), - context, file_list, "", - &generator, - &EnumGenerator::Generate); + output_directory, file_list); } for (int i = 0; i < file_->message_type_count(); i++) { - if (immutable_api_) { - GenerateSibling<MessageGenerator>(package_dir, java_package_, - file_->message_type(i), - context, file_list, - "OrBuilder", - message_generators_[i].get(), - &MessageGenerator::GenerateInterface); - } GenerateSibling<MessageGenerator>(package_dir, java_package_, file_->message_type(i), - context, file_list, "", - message_generators_[i].get(), - &MessageGenerator::Generate); + output_directory, file_list); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { - scoped_ptr<ServiceGenerator> generator( - generator_factory_->NewServiceGenerator(file_->service(i))); GenerateSibling<ServiceGenerator>(package_dir, java_package_, file_->service(i), - context, file_list, "", - generator.get(), - &ServiceGenerator::Generate); + output_directory, file_list); } } } } -bool FileGenerator::ShouldIncludeDependency( - const FileDescriptor* descriptor, bool immutable_api) { +bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) { return true; } diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index c805b9a..9e35d33 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,26 +35,18 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ -#include <memory> #include <string> #include <vector> #include <google/protobuf/stubs/common.h> namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h + class FileDescriptor; // descriptor.h namespace io { - class Printer; // printer.h + class Printer; // printer.h } namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class Context; // context.h - class MessageGenerator; // message.h - class GeneratorFactory; // generator_factory.h - class ExtensionGenerator; // extension.h - class ClassNameResolver; // name_resolver.h - } + class OutputDirectory; // code_generator.h } } @@ -64,7 +56,7 @@ namespace java { class FileGenerator { public: - FileGenerator(const FileDescriptor* file, bool immutable_api = true); + explicit FileGenerator(const FileDescriptor* file); ~FileGenerator(); // Checks for problems that would otherwise lead to cryptic compile errors. @@ -78,31 +70,23 @@ class FileGenerator { // files other than the outer file (i.e. one for each message, enum, and // service type). void GenerateSiblings(const string& package_dir, - GeneratorContext* generator_context, + OutputDirectory* output_directory, vector<string>* file_list); const string& java_package() { return java_package_; } const string& classname() { return classname_; } - private: - void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer); - void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer); - - bool ShouldIncludeDependency(const FileDescriptor* descriptor, - bool immutable_api_); + // Returns whether the dependency should be included in the output file. + // Always returns true for opensource, but used internally at Google to help + // improve compatibility with version 1 of protocol buffers. + bool ShouldIncludeDependency(const FileDescriptor* descriptor); const FileDescriptor* file_; string java_package_; string classname_; - scoped_array<scoped_ptr<MessageGenerator> > message_generators_; - scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_; - scoped_ptr<GeneratorFactory> generator_factory_; - scoped_ptr<Context> context_; - ClassNameResolver* name_resolver_; - bool immutable_api_; - + void GenerateEmbeddedDescriptor(io::Printer* printer); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index c3a47e3..745b55a 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,13 +33,8 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/java/java_generator.h> - -#include <memory> - #include <google/protobuf/compiler/java/java_file.h> -#include <google/protobuf/compiler/java/java_generator_factory.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_shared_code_generator.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/descriptor.pb.h> @@ -56,8 +51,11 @@ JavaGenerator::~JavaGenerator() {} bool JavaGenerator::Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { + vector<pair<string, string> > options; + ParseGeneratorParameter(parameter, &options); + // ----------------------------------------------------------------- // parse generator options @@ -65,84 +63,50 @@ bool JavaGenerator::Generate(const FileDescriptor* file, // per line. string output_list_file; - - vector<pair<string, string> > options; - ParseGeneratorParameter(parameter, &options); - - bool generate_immutable_code = false; - bool generate_mutable_code = false; - bool generate_shared_code = false; for (int i = 0; i < options.size(); i++) { if (options[i].first == "output_list_file") { output_list_file = options[i].second; - } else if (options[i].first == "immutable") { - generate_immutable_code = true; - } else if (options[i].first == "mutable") { - generate_mutable_code = true; - } else if (options[i].first == "shared") { - generate_shared_code = true; } else { *error = "Unknown generator option: " + options[i].first; return false; } } - // By default we generate immutable code and shared code for immutable API. - if (!generate_immutable_code && !generate_mutable_code && - !generate_shared_code) { - generate_immutable_code = true; - generate_shared_code = true; - } // ----------------------------------------------------------------- - vector<string> all_files; - - vector<FileGenerator*> file_generators; - if (generate_immutable_code) { - file_generators.push_back(new FileGenerator(file, /* immutable = */ true)); - } - for (int i = 0; i < file_generators.size(); ++i) { - if (!file_generators[i]->Validate(error)) { - for (int j = 0; j < file_generators.size(); ++j) { - delete file_generators[j]; - } - return false; - } + FileGenerator file_generator(file); + if (!file_generator.Validate(error)) { + return false; } - for (int i = 0; i < file_generators.size(); ++i) { - FileGenerator* file_generator = file_generators[i]; + string package_dir = + StringReplace(file_generator.java_package(), ".", "/", true); + if (!package_dir.empty()) package_dir += "/"; - string package_dir = JavaPackageToDir(file_generator->java_package()); - - string java_filename = package_dir; - java_filename += file_generator->classname(); - java_filename += ".java"; - all_files.push_back(java_filename); + vector<string> all_files; - // Generate main java file. - scoped_ptr<io::ZeroCopyOutputStream> output( - context->Open(java_filename)); - io::Printer printer(output.get(), '$'); - file_generator->Generate(&printer); + string java_filename = package_dir; + java_filename += file_generator.classname(); + java_filename += ".java"; + all_files.push_back(java_filename); - // Generate sibling files. - file_generator->GenerateSiblings(package_dir, context, &all_files); - } + // Generate main java file. + scoped_ptr<io::ZeroCopyOutputStream> output( + output_directory->Open(java_filename)); + io::Printer printer(output.get(), '$'); + file_generator.Generate(&printer); - for (int i = 0; i < file_generators.size(); ++i) { - delete file_generators[i]; - } - file_generators.clear(); + // Generate sibling files. + file_generator.GenerateSiblings(package_dir, output_directory, &all_files); // Generate output list if requested. if (!output_list_file.empty()) { // Generate output list. This is just a simple text file placed in a // deterministic location which lists the .java files being generated. scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output( - context->Open(output_list_file)); + output_directory->Open(output_list_file)); io::Printer srclist_printer(srclist_raw_output.get(), '$'); for (int i = 0; i < all_files.size(); i++) { srclist_printer.Print("$filename$\n", "filename", all_files[i]); diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h index 47f76be..c91c905 100644 --- a/src/google/protobuf/compiler/java/java_generator.h +++ b/src/google/protobuf/compiler/java/java_generator.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const; private: diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc deleted file mode 100644 index 2d1437f..0000000 --- a/src/google/protobuf/compiler/java/java_generator_factory.cc +++ /dev/null @@ -1,77 +0,0 @@ -// 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. - -// Author: liujisi@google.com (Pherl Liu) - -#include <google/protobuf/compiler/java/java_generator_factory.h> - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_enum_field.h> -#include <google/protobuf/compiler/java/java_extension.h> -#include <google/protobuf/compiler/java/java_field.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_message.h> -#include <google/protobuf/compiler/java/java_service.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -GeneratorFactory::GeneratorFactory() {} -GeneratorFactory::~GeneratorFactory() {} - -// =================================================================== - -ImmutableGeneratorFactory::ImmutableGeneratorFactory( - Context* context) : context_(context) { -} -ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {} - -MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator( - const Descriptor* descriptor) const { - return new ImmutableMessageGenerator(descriptor, context_); -} - -ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator( - const FieldDescriptor* descriptor) const { - return new ImmutableExtensionGenerator(descriptor, context_); -} - -ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator( - const ServiceDescriptor* descriptor) const { - return new ImmutableServiceGenerator(descriptor, context_); -} - - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h deleted file mode 100644 index 55365a9..0000000 --- a/src/google/protobuf/compiler/java/java_generator_factory.h +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -// Author: liujisi@google.com (Pherl Liu) - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ - -#include <google/protobuf/stubs/common.h> - -namespace google { -namespace protobuf { - class FieldDescriptor; // descriptor.h - class Descriptor; // descriptor.h - class ServiceDescriptor; // descriptor.h - namespace compiler { - namespace java { - class MessageGenerator; // message.h - class ExtensionGenerator; // extension.h - class ServiceGenerator; // service.h - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class GeneratorFactory { - public: - GeneratorFactory(); - virtual ~GeneratorFactory(); - - virtual MessageGenerator* NewMessageGenerator( - const Descriptor* descriptor) const = 0; - - virtual ExtensionGenerator* NewExtensionGenerator( - const FieldDescriptor* descriptor) const = 0; - - virtual ServiceGenerator* NewServiceGenerator( - const ServiceDescriptor* descriptor) const = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory); -}; - -// Factory that creates generators for immutable-default messages. -class ImmutableGeneratorFactory : public GeneratorFactory { - public: - ImmutableGeneratorFactory(Context* context); - virtual ~ImmutableGeneratorFactory(); - - virtual MessageGenerator* NewMessageGenerator( - const Descriptor* descriptor) const; - - virtual ExtensionGenerator* NewExtensionGenerator( - const FieldDescriptor* descriptor) const; - - virtual ServiceGenerator* NewServiceGenerator( - const ServiceDescriptor* descriptor) const; - - private: - Context* context_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory); -}; - - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 3efd7ed..7ed0c3c 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,15 +32,11 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <limits> #include <vector> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> @@ -49,9 +45,6 @@ namespace protobuf { namespace compiler { namespace java { -using internal::WireFormat; -using internal::WireFormatLite; - const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -61,47 +54,18 @@ namespace { const char* kDefaultPackage = ""; -// Names that should be avoided as field names. -// Using them will cause the compiler to generate accessors whose names are -// colliding with methods defined in base classes. -const char* kForbiddenWordList[] = { - // message base class: - "cached_size", "serialized_size", - // java.lang.Object: - "class", -}; - -bool IsForbidden(const string& field_name) { - for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { - if (field_name == kForbiddenWordList[i]) { - return true; - } - } - return false; -} - -string FieldName(const FieldDescriptor* field) { - string field_name; +const string& FieldName(const FieldDescriptor* field) { // Groups are hacky: The name of the field is just the lower-cased name // of the group type. In Java, though, we would like to retain the original // capitalization of the type name. if (GetType(field) == FieldDescriptor::TYPE_GROUP) { - field_name = field->message_type()->name(); + return field->message_type()->name(); } else { - field_name = field->name(); + return field->name(); } - if (IsForbidden(field_name)) { - // Append a trailing "#" to indicate that the name should be decorated to - // avoid collision with other names. - field_name += "#"; - } - return field_name; } - -} // namespace - -string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { +string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -129,27 +93,21 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { cap_next_letter = true; } } - // Add a trailing "_" if the name should be altered. - if (input[input.size() - 1] == '#') { - result += '_'; - } return result; } +} // namespace + string UnderscoresToCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCase(FieldName(field), false); + return UnderscoresToCamelCaseImpl(FieldName(field), false); } string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCase(FieldName(field), true); + return UnderscoresToCamelCaseImpl(FieldName(field), true); } string UnderscoresToCamelCase(const MethodDescriptor* method) { - return UnderscoresToCamelCase(method->name(), false); -} - -string UniqueFileScopeIdentifier(const Descriptor* descriptor) { - return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); + return UnderscoresToCamelCaseImpl(method->name(), false); } string StripProto(const string& filename) { @@ -160,38 +118,35 @@ string StripProto(const string& filename) { } } -string FileClassName(const FileDescriptor* file, bool immutable) { - ClassNameResolver name_resolver; - return name_resolver.GetFileClassName(file, immutable); +string FileClassName(const FileDescriptor* file) { + if (file->options().has_java_outer_classname()) { + return file->options().java_outer_classname(); + } else { + string basename; + string::size_type last_slash = file->name().find_last_of('/'); + if (last_slash == string::npos) { + basename = file->name(); + } else { + basename = file->name().substr(last_slash + 1); + } + return UnderscoresToCamelCaseImpl(StripProto(basename), true); + } } -string FileJavaPackage(const FileDescriptor* file, bool immutable) { - string result; - +string FileJavaPackage(const FileDescriptor* file) { if (file->options().has_java_package()) { - result = file->options().java_package(); + return file->options().java_package(); } else { - result = kDefaultPackage; + string result = kDefaultPackage; if (!file->package().empty()) { if (!result.empty()) result += '.'; result += file->package(); } + return result; } - - return result; -} - -string JavaPackageToDir(string package_name) { - string package_dir = - StringReplace(package_name, ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; - return package_dir; } -// TODO(xiaofeng): This function is only kept for it's publicly referenced. -// It should be removed after mutable API up-integration. -string ToJavaName(const string& full_name, - const FileDescriptor* file) { +string ToJavaName(const string& full_name, const FileDescriptor* file) { string result; if (file->options().java_multiple_files()) { result = FileJavaPackage(file); @@ -211,43 +166,11 @@ string ToJavaName(const string& full_name, return result; } -string ClassName(const Descriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -string ClassName(const EnumDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -string ClassName(const ServiceDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - string ClassName(const FileDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -string ExtraMessageInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(message_implements:" - + descriptor->full_name() + ")"; - return interfaces; -} - - -string ExtraBuilderInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(builder_implements:" - + descriptor->full_name() + ")"; - return interfaces; -} - -string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(interface_extends:" - + descriptor->full_name() + ")"; - return interfaces; + string result = FileJavaPackage(descriptor); + if (!result.empty()) result += '.'; + result += FileClassName(descriptor); + return result; } string FieldConstantName(const FieldDescriptor *field) { @@ -326,35 +249,6 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } -const char* FieldTypeName(FieldDescriptor::Type field_type) { - switch (field_type) { - case FieldDescriptor::TYPE_INT32 : return "INT32"; - case FieldDescriptor::TYPE_UINT32 : return "UINT32"; - case FieldDescriptor::TYPE_SINT32 : return "SINT32"; - case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; - case FieldDescriptor::TYPE_INT64 : return "INT64"; - case FieldDescriptor::TYPE_UINT64 : return "UINT64"; - case FieldDescriptor::TYPE_SINT64 : return "SINT64"; - case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; - case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; - case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; - case FieldDescriptor::TYPE_BOOL : return "BOOL"; - case FieldDescriptor::TYPE_STRING : return "STRING"; - case FieldDescriptor::TYPE_BYTES : return "BYTES"; - case FieldDescriptor::TYPE_ENUM : return "ENUM"; - case FieldDescriptor::TYPE_GROUP : return "GROUP"; - case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - bool AllAscii(const string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { @@ -364,8 +258,7 @@ bool AllAscii(const string& text) { return true; } -string DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver) { +string DefaultValue(const FieldDescriptor* field) { // Switch on CppType since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { @@ -422,18 +315,17 @@ string DefaultValue(const FieldDescriptor* field, bool immutable, } else { // See comments in Internal.java for gory details. return strings::Substitute( - "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", - CEscape(field->default_value_string())); + "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", + CEscape(field->default_value_string())); } } case FieldDescriptor::CPPTYPE_ENUM: - return name_resolver->GetClassName(field->enum_type(), immutable) + "." + - field->default_value_enum()->name(); + return ClassName(field->enum_type()) + "." + + field->default_value_enum()->name(); case FieldDescriptor::CPPTYPE_MESSAGE: - return name_resolver->GetClassName(field->message_type(), immutable) + - ".getDefaultInstance()"; + return ClassName(field->message_type()) + ".getDefaultInstance()"; // No default because we want the compiler to complain if any new // types are added. @@ -443,294 +335,6 @@ string DefaultValue(const FieldDescriptor* field, bool immutable, return ""; } -bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { - // Switch on CppType since we need to know which default_value_* method - // of FieldDescriptor to call. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return field->default_value_int32() == 0; - case FieldDescriptor::CPPTYPE_UINT32: - return field->default_value_uint32() == 0; - case FieldDescriptor::CPPTYPE_INT64: - return field->default_value_int64() == 0L; - case FieldDescriptor::CPPTYPE_UINT64: - return field->default_value_uint64() == 0L; - case FieldDescriptor::CPPTYPE_DOUBLE: - return field->default_value_double() == 0.0; - case FieldDescriptor::CPPTYPE_FLOAT: - return field->default_value_float() == 0.0; - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() == false; - - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - return false; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -const char* bit_masks[] = { - "0x00000001", - "0x00000002", - "0x00000004", - "0x00000008", - "0x00000010", - "0x00000020", - "0x00000040", - "0x00000080", - - "0x00000100", - "0x00000200", - "0x00000400", - "0x00000800", - "0x00001000", - "0x00002000", - "0x00004000", - "0x00008000", - - "0x00010000", - "0x00020000", - "0x00040000", - "0x00080000", - "0x00100000", - "0x00200000", - "0x00400000", - "0x00800000", - - "0x01000000", - "0x02000000", - "0x04000000", - "0x08000000", - "0x10000000", - "0x20000000", - "0x40000000", - "0x80000000", -}; - -string GetBitFieldName(int index) { - string varName = "bitField"; - varName += SimpleItoa(index); - varName += "_"; - return varName; -} - -string GetBitFieldNameForBit(int bitIndex) { - return GetBitFieldName(bitIndex / 32); -} - -namespace { - -string GenerateGetBitInternal(const string& prefix, int bitIndex) { - string varName = prefix + GetBitFieldNameForBit(bitIndex); - int bitInVarIndex = bitIndex % 32; - - string mask = bit_masks[bitInVarIndex]; - string result = "((" + varName + " & " + mask + ") == " + mask + ")"; - return result; -} - -string GenerateSetBitInternal(const string& prefix, int bitIndex) { - string varName = prefix + GetBitFieldNameForBit(bitIndex); - int bitInVarIndex = bitIndex % 32; - - string mask = bit_masks[bitInVarIndex]; - string result = varName + " |= " + mask; - return result; -} - -} // namespace - -string GenerateGetBit(int bitIndex) { - return GenerateGetBitInternal("", bitIndex); -} - -string GenerateSetBit(int bitIndex) { - return GenerateSetBitInternal("", bitIndex); -} - -string GenerateClearBit(int bitIndex) { - string varName = GetBitFieldNameForBit(bitIndex); - int bitInVarIndex = bitIndex % 32; - - string mask = bit_masks[bitInVarIndex]; - string result = varName + " = (" + varName + " & ~" + mask + ")"; - return result; -} - -string GenerateGetBitFromLocal(int bitIndex) { - return GenerateGetBitInternal("from_", bitIndex); -} - -string GenerateSetBitToLocal(int bitIndex) { - return GenerateSetBitInternal("to_", bitIndex); -} - -string GenerateGetBitMutableLocal(int bitIndex) { - return GenerateGetBitInternal("mutable_", bitIndex); -} - -string GenerateSetBitMutableLocal(int bitIndex) { - return GenerateSetBitInternal("mutable_", bitIndex); -} - -bool IsReferenceType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return true; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { - switch (GetType(field)) { - case FieldDescriptor::TYPE_INT32 : return "Int32"; - case FieldDescriptor::TYPE_UINT32 : return "UInt32"; - case FieldDescriptor::TYPE_SINT32 : return "SInt32"; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_INT64 : return "Int64"; - case FieldDescriptor::TYPE_UINT64 : return "UInt64"; - case FieldDescriptor::TYPE_SINT64 : return "SInt64"; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float"; - case FieldDescriptor::TYPE_DOUBLE : return "Double"; - case FieldDescriptor::TYPE_BOOL : return "Bool"; - case FieldDescriptor::TYPE_STRING : return "String"; - case FieldDescriptor::TYPE_BYTES : { - return "Bytes"; - } - case FieldDescriptor::TYPE_ENUM : return "Enum"; - case FieldDescriptor::TYPE_GROUP : return "Group"; - case FieldDescriptor::TYPE_MESSAGE : return "Message"; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; -} - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. The caller should delete the returned array. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); - return fields; -} - -// Returns true if the message type has any required fields. If it doesn't, -// we can optimize out calls to its isInitialized() method. -// -// already_seen is used to avoid checking the same type multiple times -// (and also to protect against recursion). -bool HasRequiredFields( - const Descriptor* type, - hash_set<const Descriptor*>* already_seen) { - if (already_seen->count(type) > 0) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(type); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (type->extension_range_count() > 0) return true; - - for (int i = 0; i < type->field_count(); i++) { - const FieldDescriptor* field = type->field(i); - if (field->is_required()) { - return true; - } - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - - return false; -} - -bool HasRequiredFields(const Descriptor* type) { - hash_set<const Descriptor*> already_seen; - return HasRequiredFields(type, &already_seen); -} - -bool HasRepeatedFields(const Descriptor* descriptor) { - for (int i = 0; i < descriptor->field_count(); ++i) { - const FieldDescriptor* field = descriptor->field(i); - if (field->is_repeated()) { - return true; - } - } - return false; -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 93f23a9..3c8974c 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -49,9 +49,6 @@ namespace java { extern const char kThickSeparator[]; extern const char kThinSeparator[]; -// Converts a name to camel-case. If cap_first_letter is true, capitalize the -// first letter. -string UnderscoresToCamelCase(const string& name, bool cap_first_letter); // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. string UnderscoresToCamelCase(const FieldDescriptor* field); @@ -61,70 +58,36 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); // of lower-casing the first letter of the name.) string UnderscoresToCamelCase(const MethodDescriptor* method); -// Get an identifier that uniquely identifies this type within the file. -// This is used to declare static variables related to this type at the -// outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor); - // Strips ".proto" or ".protodevel" from the end of a filename. string StripProto(const string& filename); -// Gets the unqualified class name for the file. For each .proto file, there -// will be one Java class containing all the immutable messages and another -// Java class containing all the mutable messages. -// TODO(xiaofeng): remove the default value after updating client code. -string FileClassName(const FileDescriptor* file, bool immutable = true); +// Gets the unqualified class name for the file. Each .proto file becomes a +// single Java class, with all its contents nested in that class. +string FileClassName(const FileDescriptor* file); // Returns the file's Java package name. -string FileJavaPackage(const FileDescriptor* file, bool immutable = true); - -// Returns output directory for the given package name. -string JavaPackageToDir(string package_name); +string FileJavaPackage(const FileDescriptor* file); // Converts the given fully-qualified name in the proto namespace to its // fully-qualified name in the Java namespace, given that it is in the given // file. -// TODO(xiaofeng): this method is deprecated and should be removed in the -// future. -string ToJavaName(const string& full_name, - const FileDescriptor* file); - -// TODO(xiaofeng): the following methods are kept for they are exposed -// publicly in //google/protobuf/compiler/java/names.h. They return -// immutable names only and should be removed after mutable API is -// integrated into google3. -string ClassName(const Descriptor* descriptor); -string ClassName(const EnumDescriptor* descriptor); -string ClassName(const ServiceDescriptor* descriptor); -string ClassName(const FileDescriptor* descriptor); - -// Comma-separate list of option-specified interfaces implemented by the -// Message, to follow the "implements" declaration of the Message definition. -string ExtraMessageInterfaces(const Descriptor* descriptor); -// Comma-separate list of option-specified interfaces implemented by the -// MutableMessage, to follow the "implements" declaration of the MutableMessage -// definition. -string ExtraMutableMessageInterfaces(const Descriptor* descriptor); -// Comma-separate list of option-specified interfaces implemented by the -// Builder, to follow the "implements" declaration of the Builder definition. -string ExtraBuilderInterfaces(const Descriptor* descriptor); -// Comma-separate list of option-specified interfaces extended by the -// MessageOrBuilder, to follow the "extends" declaration of the -// MessageOrBuilder definition. -string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); +string ToJavaName(const string& full_name, const FileDescriptor* file); -// Get the unqualified Java class name for mutable messages. i.e. without -// package or outer classnames. -inline string ShortMutableJavaClassName(const Descriptor* descriptor) { - return descriptor->name(); +// These return the fully-qualified class name corresponding to the given +// descriptor. +inline string ClassName(const Descriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); } - - -// Whether we should generate multiple java files for messages. -inline bool MultipleJavaFiles( - const FileDescriptor* descriptor, bool immutable) { - return descriptor->options().java_multiple_files(); +inline string ClassName(const EnumDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} +inline string ClassName(const ServiceDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} +inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); } +string ClassName(const FileDescriptor* descriptor); // Get the unqualified name that should be used for a field's field // number constant. @@ -154,23 +117,10 @@ JavaType GetJavaType(const FieldDescriptor* field); // types. const char* BoxedPrimitiveTypeName(JavaType type); -// Get the name of the java enum constant representing this type. E.g., -// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full -// name is "com.google.protobuf.WireFormat.FieldType.INT32". -const char* FieldTypeName(const FieldDescriptor::Type field_type); +string DefaultValue(const FieldDescriptor* field); -class ClassNameResolver; -string DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver); -inline string ImmutableDefaultValue(const FieldDescriptor* field, - ClassNameResolver* name_resolver) { - return DefaultValue(field, true, name_resolver); -} -bool IsDefaultValueJavaDefault(const FieldDescriptor* field); - -// Does this message class use UnknownFieldSet? -// Otherwise, unknown fields will be stored in a ByteString object -inline bool UseUnknownFieldSet(const Descriptor* descriptor) { +// Does this message class keep track of unknown fields? +inline bool HasUnknownFields(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != FileOptions::LITE_RUNTIME; } @@ -182,11 +132,6 @@ inline bool HasGeneratedMethods(const Descriptor* descriptor) { FileOptions::CODE_SIZE; } -// Does this message have specialized equals() and hashCode() methods? -inline bool HasEqualsAndHashCode(const Descriptor* descriptor) { - return descriptor->file()->options().java_generate_equals_and_hash(); -} - // Does this message class have descriptor and reflection methods? inline bool HasDescriptorMethods(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != @@ -201,12 +146,6 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { FileOptions::LITE_RUNTIME; } -inline bool HasNestedBuilders(const Descriptor* descriptor) { - // The proto-lite version doesn't support nested builders. - return descriptor->file()->options().optimize_for() != - FileOptions::LITE_RUNTIME; -} - // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -214,106 +153,6 @@ inline bool HasGenericServices(const FileDescriptor *file) { file->options().java_generic_services(); } -inline bool IsLazy(const FieldDescriptor* descriptor) { - // Currently, the proto-lite version suports lazy field. - // TODO(niwasaki): Support lazy fields also for other proto runtimes. - if (descriptor->file()->options().optimize_for() != - FileOptions::LITE_RUNTIME) { - return false; - } - return descriptor->options().lazy(); -} - -// Methods for shared bitfields. - -// Gets the name of the shared bitfield for the given index. -string GetBitFieldName(int index); - -// Gets the name of the shared bitfield for the given bit index. -// Effectively, GetBitFieldName(bitIndex / 32) -string GetBitFieldNameForBit(int bitIndex); - -// Generates the java code for the expression that returns the boolean value -// of the bit of the shared bitfields for the given bit index. -// Example: "((bitField1_ & 0x04) == 0x04)" -string GenerateGetBit(int bitIndex); - -// Generates the java code for the expression that sets the bit of the shared -// bitfields for the given bit index. -// Example: "bitField1_ = (bitField1_ | 0x04)" -string GenerateSetBit(int bitIndex); - -// Generates the java code for the expression that clears the bit of the shared -// bitfields for the given bit index. -// Example: "bitField1_ = (bitField1_ & ~0x04)" -string GenerateClearBit(int bitIndex); - -// Does the same as GenerateGetBit but operates on the bit field on a local -// variable. This is used by the builder to copy the value in the builder to -// the message. -// Example: "((from_bitField1_ & 0x04) == 0x04)" -string GenerateGetBitFromLocal(int bitIndex); - -// Does the same as GenerateSetBit but operates on the bit field on a local -// variable. This is used by the builder to copy the value in the builder to -// the message. -// Example: "to_bitField1_ = (to_bitField1_ | 0x04)" -string GenerateSetBitToLocal(int bitIndex); - -// Does the same as GenerateGetBit but operates on the bit field on a local -// variable. This is used by the parsing constructor to record if a repeated -// field is mutable. -// Example: "((mutable_bitField1_ & 0x04) == 0x04)" -string GenerateGetBitMutableLocal(int bitIndex); - -// Does the same as GenerateSetBit but operates on the bit field on a local -// variable. This is used by the parsing constructor to record if a repeated -// field is mutable. -// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" -string GenerateSetBitMutableLocal(int bitIndex); - -// Returns whether the JavaType is a reference type. -bool IsReferenceType(JavaType type); - -// Returns the capitalized name for calling relative functions in -// CodedInputStream -const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type); - -// Comparators used to sort fields in MessageGenerator -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -struct ExtensionRangeOrdering { - bool operator()(const Descriptor::ExtensionRange* a, - const Descriptor::ExtensionRange* b) const { - return a->start < b->start; - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. The caller should delete the returned array. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); - -// Check a message type and its sub-message types recursively to see if any of -// them has a required field. Return true if a required field is found. -bool HasRequiredFields(const Descriptor* descriptor); - -// Whether a .proto file supports field presence test for non-message types. -inline bool SupportFieldPresence(const FileDescriptor* descriptor) { - return true; -} - -// Check whether a mesasge has repeated fields. -bool HasRepeatedFields(const Descriptor* descriptor); - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc deleted file mode 100644 index 21cab7d..0000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ /dev/null @@ -1,826 +0,0 @@ -// 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. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_lazy_message_field.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/io/printer.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -ImmutableLazyMessageFieldGenerator:: -ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - -ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " return $name$_;\n" - "}\n"); - } -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - } - - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$name$_.setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "$name$_.setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($get_has_field_bit_builder$ &&\n" - " !$name$_.containsDefaultInstance()) {\n" - " $name$_.setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " $name$_.setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_.clear();\n" - "$on_changed$\n", - - NULL, - - "$clear_has_field_bit_builder$;\n" - "return this;\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$;\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } -} - - -void ImmutableLazyMessageFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $name$_.merge(other.$name$_);\n" - " $set_has_field_bit_builder$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - - printer->Print(variables_, - "result.$name$_.setByteString(\n" - " $name$_.toByteString(),\n" - " $name$_.getExtensionRegistry());\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); - printer->Print(variables_, - "$set_has_field_bit_message$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " output.writeBytes($number$, $name$_.toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_);\n" - "}\n"); -} - -// =================================================================== - -ImmutableLazyMessageOneofFieldGenerator:: -ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableLazyMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); - variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; -} - -ImmutableLazyMessageOneofFieldGenerator:: -~ImmutableLazyMessageOneofFieldGenerator() {} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($has_oneof_case_message$ &&\n" - " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" - " (($lazy_type$) $oneof_name$_).setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - "}\n", - - NULL, - - "return this;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).merge(\n" - " ($lazy_type$) other.$oneof_name$_);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n"); - printer->Indent(); - - printer->Print(variables_, - "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).setByteString(\n" - " (($lazy_type$) $oneof_name$_).toByteString(),\n" - " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setByteString(\n" - " input.readBytes(), extensionRegistry);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes(\n" - " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" - "}\n"); -} - -// =================================================================== - -RepeatedImmutableLazyMessageFieldGenerator:: -RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : RepeatedImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - - -RepeatedImmutableLazyMessageFieldGenerator:: -~RepeatedImmutableLazyMessageFieldGenerator() {} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$>\n" - " get$capitalized_name$List() {\n" - " java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - " }\n" - " return list;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder>\n" - " get$capitalized_name$OrBuilderList() {\n" - " return get$capitalized_name$List();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return ($type$)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return ($type$OrBuilder)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ =\n" - " new java.util.ArrayList<com.google.protobuf.LazyFieldLite>(\n" - " $name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n" - "\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); - } - - // The comments above the methods below are based on a hypothetical - // repeated field of type "Field" called "RepeatedField". - - // List<Field> getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", - - "java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - "}\n" - "return java.util.Collections.unmodifiableList(list);\n", - - "return $name$Builder_.getMessageList();\n", - - NULL); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public int get$capitalized_name$Count()", - - "return $name$_.size();\n", - "return $name$Builder_.getCount();\n", - - NULL); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$(int index)", - - "return ($type$) $name$_.get(index).getValue(\n" - " $type$.getDefaultInstance());\n", - - "return $name$Builder_.getMessage(index);\n", - - NULL); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - "$name$Builder_.setMessage(index, value);\n", - "return this;\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" - - "$on_changed$\n", - - "$name$Builder_.addMessage(value);\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, value);\n", - - "return this;\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addAllRepeatedField(Iterable<Field> values) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable<? extends $type$> values)", - - "ensure$capitalized_name$IsMutable();\n" - "for (com.google.protobuf.MessageLite v : values) {\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" - "}\n" - "$on_changed$\n", - - "$name$Builder_.addAllMessages(values);\n", - - "return this;\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n" - "$on_changed$\n", - - "$name$Builder_.clear();\n", - - "return this;\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder remove$capitalized_name$(int index)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.remove(index);\n" - "$on_changed$\n", - - "$name$Builder_.remove(index);\n", - - "return this;\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder> \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ =\n" - " new java.util.ArrayList<com.google.protobuf.LazyFieldLite>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" - " extensionRegistry, input.readBytes()));\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.get(i).toByteString());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_.get(i));\n" - "}\n"); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h deleted file mode 100644 index b1b7f28..0000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.h +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ - -#include <google/protobuf/compiler/java/java_field.h> -#include <google/protobuf/compiler/java/java_message_field.h> - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableLazyMessageFieldGenerator - : public ImmutableMessageFieldGenerator { - public: - explicit ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageFieldGenerator(); - - // overroads ImmutableMessageFieldGenerator --------------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator); -}; - -class ImmutableLazyMessageOneofFieldGenerator - : public ImmutableLazyMessageFieldGenerator { - public: - ImmutableLazyMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageOneofFieldGenerator(); - - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator); -}; - -class RepeatedImmutableLazyMessageFieldGenerator - : public RepeatedImmutableMessageFieldGenerator { - public: - explicit RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableLazyMessageFieldGenerator(); - - // overroads RepeatedImmutableMessageFieldGenerator ------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 8aa89ac..a326057 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,27 +32,17 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/java_message.h> - #include <algorithm> #include <google/protobuf/stubs/hash.h> -#include <map> -#include <memory> -#include <vector> - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> +#include <google/protobuf/compiler/java/java_message.h> #include <google/protobuf/compiler/java/java_enum.h> #include <google/protobuf/compiler/java/java_extension.h> -#include <google/protobuf/compiler/java/java_generator_factory.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/descriptor.pb.h> namespace google { namespace protobuf { @@ -63,31 +53,107 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { -bool GenerateHasBits(const Descriptor* descriptor) { - return SupportFieldPresence(descriptor->file()) || - HasRepeatedFields(descriptor); + +void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { + // Print the field's proto-syntax definition as a comment. We don't want to + // print group bodies so we cut off after the first line. + string def = field->DebugString(); + printer->Print("// $def$\n", + "def", def.substr(0, def.find_first_of('\n'))); } -} // namespace -// =================================================================== +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; -MessageGenerator::MessageGenerator(const Descriptor* descriptor) - : descriptor_(descriptor) {} +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; -MessageGenerator::~MessageGenerator() {} +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Get an identifier that uniquely identifies this type within the file. +// This is used to declare static variables related to this type at the +// outermost file scope. +string UniqueFileScopeIdentifier(const Descriptor* descriptor) { + return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its isInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +static bool HasRequiredFields( + const Descriptor* type, + hash_set<const Descriptor*>* already_seen) { + if (already_seen->count(type) > 0) { + // The type is already in cache. This means that either: + // a. The type has no required fields. + // b. We are in the midst of checking if the type has required fields, + // somewhere up the stack. In this case, we know that if the type + // has any required fields, they'll be found when we return to it, + // and the whole call to HasRequiredFields() will return true. + // Therefore, we don't have to check if this type has required fields + // here. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (GetJavaType(field) == JAVATYPE_MESSAGE) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + + return false; +} + +static bool HasRequiredFields(const Descriptor* type) { + hash_set<const Descriptor*> already_seen; + return HasRequiredFields(type, &already_seen); +} + +} // namespace // =================================================================== -// TODO(api): Move this class to a separate immutable_message.cc file. -ImmutableMessageGenerator::ImmutableMessageGenerator( - const Descriptor* descriptor, Context* context) - : MessageGenerator(descriptor), context_(context), - name_resolver_(context->GetNameResolver()), - field_generators_(descriptor, context_) { + +MessageGenerator::MessageGenerator(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_(descriptor) { } -ImmutableMessageGenerator::~ImmutableMessageGenerator() {} +MessageGenerator::~MessageGenerator() {} -void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { +void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping @@ -99,12 +165,12 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { map<string, string> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); + vars["classname"] = ClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); } - if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + if (descriptor_->file()->options().java_multiple_files()) { // We can only make these package-private since the classes that use them // are in separate files. vars["private"] = ""; @@ -114,28 +180,31 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { // The descriptor for this type. printer->Print(vars, - "$private$static final com.google.protobuf.Descriptors.Descriptor\n" + "$private$static com.google.protobuf.Descriptors.Descriptor\n" " internal_$identifier$_descriptor;\n"); // And the FieldAccessorTable. - GenerateFieldAccessorTable(printer); + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) + MessageGenerator(descriptor_->nested_type(i)) .GenerateStaticVariables(printer); } } -void ImmutableMessageGenerator::GenerateStaticVariableInitializers( +void MessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { map<string, string> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); + vars["classname"] = ClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); @@ -153,191 +222,82 @@ void ImmutableMessageGenerator::GenerateStaticVariableInitializers( } // And the FieldAccessorTable. - GenerateFieldAccessorTableInitializer(printer); + printer->Print(vars, + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print( + "\"$field_name$\", ", + "field_name", + UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + } + printer->Print("},\n" + " $classname$.class,\n" + " $classname$.Builder.class);\n", + "classname", ClassName(descriptor_)); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) + MessageGenerator(descriptor_->nested_type(i)) .GenerateStaticVariableInitializers(printer); } -} - -void ImmutableMessageGenerator:: -GenerateFieldAccessorTable(io::Printer* printer) { - map<string, string> vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { - // We can only make these package-private since the classes that use them - // are in separate files. - vars["private"] = ""; - } else { - vars["private"] = "private "; - } - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); -} -void ImmutableMessageGenerator:: -GenerateFieldAccessorTableInitializer(io::Printer* printer) { - printer->Print( - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { ", - "identifier", - UniqueFileScopeIdentifier(descriptor_)); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - printer->Print( - "\"$field_name$\", ", - "field_name", info->capitalized_name); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "\"$oneof_name$\", ", - "oneof_name", info->capitalized_name); - } - printer->Print("});\n"); -} - -// =================================================================== - -void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { - if (descriptor_->extension_range_count() > 0) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessage.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } else { - printer->Print( - "public interface $classname$OrBuilder extends \n" - " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } - } else { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.MessageOrBuilder {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } else { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.MessageLiteOrBuilder {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } + for (int i = 0; i < descriptor_->extension_count(); i++) { + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(descriptor_->extension(i)) + .GenerateInitializationCode(printer); } - - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateInterfaceMembers(printer); - } - printer->Outdent(); - - printer->Print("}\n"); } -// =================================================================== - -void ImmutableMessageGenerator::Generate(io::Printer* printer) { +void MessageGenerator::Generate(io::Printer* printer) { bool is_own_file = descriptor_->containing_type() == NULL && - MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); - - WriteMessageDocComment(printer, descriptor_); + descriptor_->file()->options().java_multiple_files(); - // The builder_type stores the super type name of the nested Builder class. - string builder_type; if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public$static$final class $classname$ extends\n" + "public $static$ final class $classname$ extends\n" " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "static", is_own_file ? " " : " static ", - "classname", descriptor_->name(), - "extra_interfaces", ExtraMessageInterfaces(descriptor_)); - builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_)); + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); } else { printer->Print( - "public$static$final class $classname$ extends\n" + "public $static$ final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "static", is_own_file ? " " : " static ", - "classname", descriptor_->name(), - "extra_interfaces", ExtraMessageInterfaces(descriptor_)); - builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_)); + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public$static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "static", is_own_file ? " " : " static ", - "classname", descriptor_->name(), - "extra_interfaces", ExtraMessageInterfaces(descriptor_)); - builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>"; + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); } else { printer->Print( - "public$static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "static", is_own_file ? " " : " static ", - "classname", descriptor_->name(), - "extra_interfaces", ExtraMessageInterfaces(descriptor_)); - builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); } } printer->Indent(); - // Using builder_type, instead of Builder, prevents the Builder class from - // being loaded into PermGen space when the default instance is created. - // This optimizes the PermGen space usage for clients that do not modify - // messages. printer->Print( "// Use $classname$.newBuilder() to construct.\n" - "private $classname$($buildertype$ builder) {\n" - " super(builder);\n" - "$set_unknown_fields$\n" - "}\n", - "classname", descriptor_->name(), - "buildertype", builder_type, - "set_unknown_fields", - " this.unknownFields = builder.getUnknownFields();"); - printer->Print( + "private $classname$() {\n" + " initFields();\n" + "}\n" // Used when constructing the default instance, which cannot be initialized // immediately because it may cyclically refer to other default instances. - "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n" + "private $classname$(boolean noInit) {}\n" "\n" "private static final $classname$ defaultInstance;\n" "public static $classname$ getDefaultInstance() {\n" @@ -348,131 +308,40 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { " return defaultInstance;\n" "}\n" "\n", - "classname", descriptor_->name(), - "set_default_unknown_fields", UseUnknownFieldSet(descriptor_) - ? " this.unknownFields =" - " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " - : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;"); + "classname", descriptor_->name()); - if (UseUnknownFieldSet(descriptor_)) { - printer->Print( - "private final com.google.protobuf.UnknownFieldSet unknownFields;\n" - "" - "@java.lang.Override\n" - "public final com.google.protobuf.UnknownFieldSet\n" - " getUnknownFields() {\n" - " return this.unknownFields;\n" - "}\n"); - } else { + if (HasDescriptorMethods(descriptor_)) { printer->Print( - "private final com.google.protobuf.ByteString unknownFields;\n"); - } - - if (HasGeneratedMethods(descriptor_)) { - GenerateParsingConstructor(printer); + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); } - GenerateDescriptorMethods(printer); - GenerateParser(printer); - - // Nested types + // Nested types and extensions for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i), true, context_) - .Generate(printer); + EnumGenerator(descriptor_->enum_type(i)).Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - ImmutableMessageGenerator messageGenerator( - descriptor_->nested_type(i), context_); - messageGenerator.GenerateInterface(printer); - messageGenerator.Generate(printer); - } - - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + MessageGenerator(descriptor_->nested_type(i)).Generate(printer); } - // oneof - map<string, string> vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - // oneofCase_ and oneof_ - printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); - // OneofCase enum - printer->Print(vars, - "public enum $oneof_capitalized_name$Case\n" - " implements com.google.protobuf.Internal.EnumLite {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "$field_name$($field_number$),\n", - "field_name", - ToUpper(field->name()), - "field_number", - SimpleItoa(field->number())); - } - printer->Print( - "$cap_oneof_name$_NOT_SET(0);\n", - "cap_oneof_name", - ToUpper(vars["oneof_name"])); - printer->Print(vars, - "private int value = 0;\n" - "private $oneof_capitalized_name$Case(int value) {\n" - " this.value = value;\n" - "}\n"); - printer->Print(vars, - "public static $oneof_capitalized_name$Case valueOf(int value) {\n" - " switch (value) {\n"); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - " case $field_number$: return $field_name$;\n", - "field_number", - SimpleItoa(field->number()), - "field_name", - ToUpper(field->name())); - } - printer->Print( - " case 0: return $cap_oneof_name$_NOT_SET;\n" - " default: throw new java.lang.IllegalArgumentException(\n" - " \"Value is undefined for this oneof enum.\");\n" - " }\n" - "}\n" - "public int getNumber() {\n" - " return this.value;\n" - "}\n", - "cap_oneof_name", ToUpper(vars["oneof_name"])); - printer->Outdent(); - printer->Print("};\n\n"); - // oneofCase() - printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - "get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.valueOf(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n"); + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator(descriptor_->extension(i)).Generate(printer); } // Fields for (int i = 0; i < descriptor_->field_count(); i++) { + PrintFieldComment(printer, descriptor_->field(i)); printer->Print("public static final int $constant_name$ = $number$;\n", "constant_name", FieldConstantName(descriptor_->field(i)), "number", SimpleItoa(descriptor_->field(i)->number())); @@ -485,60 +354,48 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { printer->Print("private void initFields() {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateInitializationCode(printer); - } + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); } - printer->Outdent(); printer->Print("}\n"); if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer, MEMOIZE); + GenerateIsInitialized(printer); GenerateMessageSerializationMethods(printer); } - if (HasEqualsAndHashCode(descriptor_)) { - GenerateEqualsAndHashCode(printer); - } - - GenerateParseFromMethods(printer); GenerateBuilder(printer); - // Carefully initialize the default instance in such a way that it doesn't - // conflict with other initialization. + // Force initialization of outer class. Otherwise, nested extensions may + // not be initialized. Also carefully initialize the default instance in + // such a way that it doesn't conflict with other initialization. printer->Print( "\n" "static {\n" " defaultInstance = new $classname$(true);\n" + " $file$.internalForceInit();\n" " defaultInstance.initFields();\n" - "}\n" + "}\n", + "file", ClassName(descriptor_->file()), + "classname", descriptor_->name()); + + printer->Print( "\n" "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "classname", descriptor_->name(), "full_name", descriptor_->full_name()); - // Extensions must be declared after the defaultInstance is initialized - // because the defaultInstance is used by the extension to lazily retrieve - // the outer class's FileDescriptor. - for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionGenerator(descriptor_->extension(i), context_) - .Generate(printer); - } - printer->Outdent(); printer->Print("}\n\n"); } - // =================================================================== -void ImmutableMessageGenerator:: +void MessageGenerator:: GenerateMessageSerializationMethods(io::Printer* printer) { scoped_array<const FieldDescriptor*> sorted_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector<const Descriptor::ExtensionRange*> sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -563,18 +420,15 @@ GenerateMessageSerializationMethods(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter =\n" " newMessageSetExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); } else { printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter = newExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); } } @@ -593,7 +447,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (UseUnknownFieldSet(descriptor_)) { + if (HasUnknownFields(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "getUnknownFields().writeAsMessageSetTo(output);\n"); @@ -601,9 +455,6 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "getUnknownFields().writeTo(output);\n"); } - } else { - printer->Print( - "output.writeRawBytes(unknownFields);\n"); } printer->Outdent(); @@ -632,7 +483,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (UseUnknownFieldSet(descriptor_)) { + if (HasUnknownFields(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); @@ -640,9 +491,6 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "size += getUnknownFields().getSerializedSize();\n"); } - } else { - printer->Print( - "size += unknownFields.size();\n"); } printer->Outdent(); @@ -651,18 +499,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " return size;\n" "}\n" "\n"); - - printer->Print( - "private static final long serialVersionUID = 0L;\n" - "@java.lang.Override\n" - "protected java.lang.Object writeReplace()\n" - " throws java.io.ObjectStreamException {\n" - " return super.writeReplace();\n" - "}\n" - "\n"); } -void ImmutableMessageGenerator:: +void MessageGenerator:: GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized @@ -671,65 +510,79 @@ GenerateParseFromMethods(io::Printer* printer) { "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" + " return newBuilder().mergeFrom(data).buildParsed();\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data, extensionRegistry);\n" + " return newBuilder().mergeFrom(data, extensionRegistry)\n" + " .buildParsed();\n" "}\n" "public static $classname$ parseFrom(byte[] data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" + " return newBuilder().mergeFrom(data).buildParsed();\n" "}\n" "public static $classname$ parseFrom(\n" " byte[] data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data, extensionRegistry);\n" + " return newBuilder().mergeFrom(data, extensionRegistry)\n" + " .buildParsed();\n" "}\n" "public static $classname$ parseFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return PARSER.parseFrom(input);\n" + " return newBuilder().mergeFrom(input).buildParsed();\n" "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return PARSER.parseFrom(input, extensionRegistry);\n" + " return newBuilder().mergeFrom(input, extensionRegistry)\n" + " .buildParsed();\n" "}\n" "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return PARSER.parseDelimitedFrom(input);\n" + " Builder builder = newBuilder();\n" + " if (builder.mergeDelimitedFrom(input)) {\n" + " return builder.buildParsed();\n" + " } else {\n" + " return null;\n" + " }\n" "}\n" "public static $classname$ parseDelimitedFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n" + " Builder builder = newBuilder();\n" + " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n" + " return builder.buildParsed();\n" + " } else {\n" + " return null;\n" + " }\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input)\n" " throws java.io.IOException {\n" - " return PARSER.parseFrom(input);\n" + " return newBuilder().mergeFrom(input).buildParsed();\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return PARSER.parseFrom(input, extensionRegistry);\n" + " return newBuilder().mergeFrom(input, extensionRegistry)\n" + " .buildParsed();\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); } -void ImmutableMessageGenerator::GenerateSerializeOneField( +void MessageGenerator::GenerateSerializeOneField( io::Printer* printer, const FieldDescriptor* field) { field_generators_.get(field).GenerateSerializationCode(printer); } -void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( +void MessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { printer->Print( "extensionWriter.writeUntil($end$, output);\n", @@ -738,7 +591,7 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== -void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { +void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static Builder newBuilder() { return Builder.create(); }\n" "public Builder newBuilderForType() { return newBuilder(); }\n" @@ -747,119 +600,47 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - if (HasNestedBuilders(descriptor_)) { - printer->Print( - "@java.lang.Override\n" - "protected Builder newBuilderForType(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" - " Builder builder = new Builder(parent);\n" - " return builder;\n" - "}\n"); - } - - WriteMessageDocComment(printer, descriptor_); + "classname", ClassName(descriptor_)); if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + " com.google.protobuf.GeneratedMessage.Builder<Builder> {\n", + "classname", ClassName(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.Builder<\n" - " $classname$, Builder>\n" - " implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); } } printer->Indent(); - GenerateDescriptorMethods(printer); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer, DONT_MEMOIZE); GenerateBuilderParsingMethods(printer); } - // oneof - map<string, string> vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - // oneofCase_ and oneof_ - printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); - // oneofCase() and clearOneof() - printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - " get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.valueOf(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n" - "public Builder clear$oneof_capitalized_name$() {\n" - " $oneof_name$Case_ = 0;\n" - " $oneof_name$_ = null;\n"); - if (HasDescriptorMethods(descriptor_)) { - printer->Print(" onChanged();\n"); - } - printer->Print( - " return this;\n" - "}\n" - "\n"); - } - - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); + PrintFieldComment(printer, descriptor_->field(i)); field_generators_.get(descriptor_->field(i)) .GenerateBuilderMembers(printer); } @@ -873,209 +654,98 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print("}\n"); } -void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_)) { - if (!descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); - } - printer->Print( - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" - " .ensureFieldAccessorsInitialized(\n" - " $classname$.class, $classname$.Builder.class);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); - } -} - // =================================================================== -void ImmutableMessageGenerator:: -GenerateCommonBuilderMethods(io::Printer* printer) { +void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( + "private $classname$ result;\n" + "\n" "// Construct using $classname$.newBuilder()\n" - "private Builder() {\n" - " maybeForceBuilderInitialization();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "private Builder(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" - " super(parent);\n" - " maybeForceBuilderInitialization();\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } - - - if (HasNestedBuilders(descriptor_)) { - printer->Print( - "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); - - printer->Indent(); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateFieldBuilderInitializationCode(printer); - } - } - printer->Outdent(); - printer->Outdent(); - - printer->Print( - " }\n" - "}\n"); - } else { - printer->Print( - "private void maybeForceBuilderInitialization() {\n" - "}\n"); - } - - printer->Print( + "private Builder() {}\n" + "\n" "private static Builder create() {\n" - " return new Builder();\n" + " Builder builder = new Builder();\n" + " builder.result = new $classname$();\n" + " return builder;\n" + "}\n" + "\n" + "protected $classname$ internalGetResult() {\n" + " return result;\n" "}\n" "\n" "public Builder clear() {\n" - " super.clear();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderClearCode(printer); - } - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "$oneof_name$Case_ = 0;\n" - "$oneof_name$_ = null;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - } - - printer->Outdent(); - - printer->Print( + " if (result == null) {\n" + " throw new IllegalStateException(\n" + " \"Cannot call clear() after build().\");\n" + " }\n" + " result = new $classname$();\n" " return this;\n" "}\n" "\n" "public Builder clone() {\n" - " return create().mergeFrom(buildPartial());\n" + " return create().mergeFrom(result);\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public com.google.protobuf.Descriptors.Descriptor\n" " getDescriptorForType() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" + " return $classname$.getDescriptor();\n" "}\n" "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "classname", ClassName(descriptor_)); } printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return $classname$.getDefaultInstance();\n" "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "\n" + "public boolean isInitialized() {\n" + " return result.isInitialized();\n" + "}\n", + "classname", ClassName(descriptor_)); // ----------------------------------------------------------------- printer->Print( "public $classname$ build() {\n" - " $classname$ result = buildPartial();\n" - " if (!result.isInitialized()) {\n" + // If result == null, we'll throw an appropriate exception later. + " if (result != null && !isInitialized()) {\n" " throw newUninitializedMessageException(result);\n" " }\n" - " return result;\n" + " return buildPartial();\n" + "}\n" + "\n" + "private $classname$ buildParsed()\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " if (!isInitialized()) {\n" + " throw newUninitializedMessageException(\n" + " result).asInvalidProtocolBufferException();\n" + " }\n" + " return buildPartial();\n" "}\n" "\n" "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - + " if (result == null) {\n" + " throw new IllegalStateException(\n" + " \"build() has already been called on this Builder.\");\n" + " }\n", + "classname", ClassName(descriptor_)); printer->Indent(); - int totalBuilderBits = 0; - int totalMessageBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - totalMessageBits += field.GetNumBitsForMessage(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - int totalMessageInts = (totalMessageBits + 31) / 32; - - if (GenerateHasBits(descriptor_)) { - // Local vars for from and to bit fields to avoid accessing the builder and - // message over and over for these fields. Seems to provide a slight - // perforamance improvement in micro benchmark and this is also what proto1 - // code does. - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("int to_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - // Output generation code for each field. for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); } - if (GenerateHasBits(descriptor_)) { - // Copy the bit field results to the generated message - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - } - printer->Outdent(); - - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - " onBuilt();\n"); - } - printer->Print( - " return result;\n" + " $classname$ returnMe = result;\n" + " result = null;\n" + " return returnMe;\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); // ----------------------------------------------------------------- @@ -1093,7 +763,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) { " }\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); } printer->Print( @@ -1101,48 +771,11 @@ GenerateCommonBuilderMethods(io::Printer* printer) { // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get( - descriptor_->field(i)).GenerateMergingCode(printer); - } - } - - // Merge oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (other.get$oneof_capitalized_name$Case()) {\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_name$: {\n", - "field_name", - ToUpper(field->name())); - printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name)); - printer->Outdent(); - printer->Print( - "}\n"); + field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer); } printer->Outdent(); @@ -1153,13 +786,9 @@ GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } - if (UseUnknownFieldSet(descriptor_)) { + if (HasUnknownFields(descriptor_)) { printer->Print( " this.mergeUnknownFields(other.getUnknownFields());\n"); - } else { - printer->Print( - " setUnknownFields(\n" - " getUnknownFields().concat(other.unknownFields));\n"); } printer->Print( @@ -1171,359 +800,58 @@ GenerateCommonBuilderMethods(io::Printer* printer) { // =================================================================== -void ImmutableMessageGenerator:: -GenerateBuilderParsingMethods(io::Printer* printer) { +void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { + scoped_array<const FieldDescriptor*> sorted_fields( + SortFieldsByNumber(descriptor_)); + printer->Print( "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " $classname$ parsedMessage = null;\n" - " try {\n" - " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" - " throw e;\n" - " } finally {\n" - " if (parsedMessage != null) {\n" - " mergeFrom(parsedMessage);\n" - " }\n" - " }\n" - " return this;\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); -} - -// =================================================================== - -void ImmutableMessageGenerator::GenerateIsInitialized( - io::Printer* printer, UseMemoization useMemoization) { - bool memoization = useMemoization == MEMOIZE; - if (memoization) { - // Memoizes whether the protocol buffer is fully initialized (has all - // required fields). -1 means not yet computed. 0 means false and 1 means - // true. - printer->Print( - "private byte memoizedIsInitialized = -1;\n"); - } - printer->Print( - "public final boolean isInitialized() {\n"); + " throws java.io.IOException {\n"); printer->Indent(); - if (memoization) { - // Don't directly compare to -1 to avoid an Android x86 JIT bug. - printer->Print( - "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized == 1) return true;\n" - "if (isInitialized == 0) return false;\n" - "\n"); - } - - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - - if (field->is_required()) { - printer->Print( - "if (!has$name$()) {\n" - " $memoize$\n" - " return false;\n" - "}\n", - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); - } - } - - // Now check that all embedded messages are initialized. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - if (GetJavaType(field) == JAVATYPE_MESSAGE && - HasRequiredFields(field->message_type())) { - switch (field->label()) { - case FieldDescriptor::LABEL_REQUIRED: - printer->Print( - "if (!get$name$().isInitialized()) {\n" - " $memoize$\n" - " return false;\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); - break; - case FieldDescriptor::LABEL_OPTIONAL: - printer->Print( - "if (has$name$()) {\n" - " if (!get$name$().isInitialized()) {\n" - " $memoize$\n" - " return false;\n" - " }\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); - break; - case FieldDescriptor::LABEL_REPEATED: - printer->Print( - "for (int i = 0; i < get$name$Count(); i++) {\n" - " if (!get$name$(i).isInitialized()) {\n" - " $memoize$\n" - " return false;\n" - " }\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); - break; - } - } - } - - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if (!extensionsAreInitialized()) {\n" - " $memoize$\n" - " return false;\n" - "}\n", - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); - } - - printer->Outdent(); - - if (memoization) { + if (HasUnknownFields(descriptor_)) { printer->Print( - " memoizedIsInitialized = 1;\n"); - } - - printer->Print( - " return true;\n" - "}\n" - "\n"); -} - -// =================================================================== - -namespace { -bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { - if (field->is_repeated()) { - return false; - } - if (SupportFieldPresence(field->file())) { - return true; + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder(\n" + " this.getUnknownFields());\n"); } - return GetJavaType(field) == JAVATYPE_MESSAGE && - field->containing_oneof() == NULL; -} -} // namespace -void ImmutableMessageGenerator:: -GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print( - "@java.lang.Override\n" - "public boolean equals(final java.lang.Object obj) {\n"); + "while (true) {\n"); printer->Indent(); - printer->Print( - "if (obj == this) {\n" - " return true;\n" - "}\n" - "if (!(obj instanceof $classname$)) {\n" - " return super.equals(obj);\n" - "}\n" - "$classname$ other = ($classname$) obj;\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Print("boolean result = true;\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); - if (check_has_bits) { - printer->Print( - "result = result && (has$name$() == other.has$name$());\n" - "if (has$name$()) {\n", - "name", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateEqualsCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print( - "}\n"); - } - } - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "result = result &&\n" - " getUnknownFields().equals(other.getUnknownFields());\n"); - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "result = result &&\n" - " getExtensionFields().equals(other.getExtensionFields());\n"); - } - } - printer->Print( - "return result;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); printer->Print( - "@java.lang.Override\n" - "public int hashCode() {\n"); - printer->Indent(); - printer->Print( - "if (memoizedHashCode != 0) {\n"); - printer->Indent(); - printer->Print( - "return memoizedHashCode;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "int hash = 41;\n"); - - if (HasDescriptorMethods(descriptor_)) { - printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); - } else { - // Include the hash of the class so that two objects with different types - // but the same field values will probably have different hashes. - printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); - if (check_has_bits) { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateHashCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print("}\n"); - } - } - if (HasDescriptorMethods(descriptor_)) { - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "hash = hashFields(hash, getExtensionFields());\n"); - } - } - - if (UseUnknownFieldSet(descriptor_)) { - printer->Print( - "hash = (29 * hash) + getUnknownFields().hashCode();\n"); - } else { - printer->Print( - "hash = (29 * hash) + unknownFields.hashCode();\n"); - } - printer->Print( - "memoizedHashCode = hash;\n" - "return hash;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); -} - -// =================================================================== - -void ImmutableMessageGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); - } -} - -// =================================================================== -void ImmutableMessageGenerator:: -GenerateParsingConstructor(io::Printer* printer) { - scoped_array<const FieldDescriptor*> sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "private $classname$(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", - "classname", descriptor_->name()); + "int tag = input.readTag();\n" + "switch (tag) {\n"); printer->Indent(); - // Initialize all fields to default. - printer->Print( - "initFields();\n"); - - // Use builder bits to track mutable repeated fields. - int totalBuilderBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int mutable_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } - - if (UseUnknownFieldSet(descriptor_)) { + if (HasUnknownFields(descriptor_)) { printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); + "case 0:\n" // zero signals EOF / limit reached + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); } else { printer->Print( - "com.google.protobuf.ByteString.Output unknownFieldsOutput =\n" - " com.google.protobuf.ByteString.newOutput();\n" - "com.google.protobuf.CodedOutputStream unknownFieldsCodedOutput =\n" - " com.google.protobuf.CodedOutputStream.newInstance(\n" - " unknownFieldsOutput);\n"); + "case 0:\n" // zero signals EOF / limit reached + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, extensionRegistry, tag)) {\n" + " return this;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); } - printer->Print( - "try {\n"); - printer->Indent(); - - printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); - printer->Indent(); - - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); - printer->Indent(); - - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n" - "default: {\n" - " if (!parseUnknownField(input,$unknown_fields$\n" - " extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n", - "unknown_fields", UseUnknownFieldSet(descriptor_) - ? " unknownFields," : " unknownFieldsCodedOutput,"); - for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; uint32 tag = WireFormatLite::MakeTag(field->number(), @@ -1562,104 +890,92 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Outdent(); printer->Outdent(); + printer->Outdent(); printer->Print( - " }\n" // switch (tag) - "}\n"); // while (!done) + " }\n" // switch (tag) + " }\n" // while (true) + "}\n" + "\n"); +} - printer->Outdent(); +// =================================================================== + +void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { printer->Print( - "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(this);\n" - "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(this);\n" - "} finally {\n"); + "public final boolean isInitialized() {\n"); printer->Indent(); - // Make repeated field list immutable. + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - field_generators_.get(field).GenerateParsingDoneCode(printer); + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_required()) { + printer->Print( + "if (!has$name$) return false;\n", + "name", UnderscoresToCapitalizedCamelCase(field)); + } } - // Make unknown fields immutable. - if (UseUnknownFieldSet(descriptor_)) { - printer->Print( - "this.unknownFields = unknownFields.build();\n"); - } else { - printer->Print( - "try {\n" - " unknownFieldsCodedOutput.flush();\n" - "} catch (java.io.IOException e) {\n" - "// Should not happen\n" - "} finally {\n" - " unknownFields = unknownFieldsOutput.toByteString();\n" - "}\n"); + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type())) { + switch (field->label()) { + case FieldDescriptor::LABEL_REQUIRED: + printer->Print( + "if (!get$name$().isInitialized()) return false;\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field)); + break; + case FieldDescriptor::LABEL_OPTIONAL: + printer->Print( + "if (has$name$()) {\n" + " if (!get$name$().isInitialized()) return false;\n" + "}\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field)); + break; + case FieldDescriptor::LABEL_REPEATED: + printer->Print( + "for ($type$ element : get$name$List()) {\n" + " if (!element.isInitialized()) return false;\n" + "}\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field)); + break; + } + } } - // Make extensions immutable. - printer->Print( - "makeExtensionsImmutable();\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if (!extensionsAreInitialized()) return false;\n"); + } printer->Outdent(); - printer->Outdent(); printer->Print( - " }\n" // finally - "}\n"); + " return true;\n" + "}\n" + "\n"); } // =================================================================== -void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { - printer->Print( - "public static com.google.protobuf.Parser<$classname$> PARSER =\n" - " new com.google.protobuf.AbstractParser<$classname$>() {\n", - "classname", descriptor_->name()); - printer->Indent(); - printer->Print( - "public $classname$ parsePartialFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", - "classname", descriptor_->name()); - if (HasGeneratedMethods(descriptor_)) { - printer->Print( - " return new $classname$(input, extensionRegistry);\n", - "classname", descriptor_->name()); - } else { - // When parsing constructor isn't generated, use builder to parse messages. - // Note, will fallback to use reflection based mergeFieldFrom() in - // AbstractMessage.Builder. - printer->Indent(); - printer->Print( - "Builder builder = newBuilder();\n" - "try {\n" - " builder.mergeFrom(input, extensionRegistry);\n" - "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(builder.buildPartial());\n" - "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n" - "}\n" - "return builder.buildPartial();\n"); - printer->Outdent(); + +void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator(descriptor_->extension(i)) + .GenerateRegistrationCode(printer); } - printer->Print( - "}\n"); - printer->Outdent(); - printer->Print( - "};\n" - "\n"); - printer->Print( - "@java.lang.Override\n" - "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" - " return PARSER;\n" - "}\n" - "\n", - "classname", descriptor_->name()); + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator(descriptor_->nested_type(i)) + .GenerateExtensionRegistrationCode(printer); + } } - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index fece1c2..50ffae0 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -36,17 +36,11 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ #include <string> -#include <map> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/java/java_field.h> namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } namespace io { class Printer; // printer.h } @@ -59,55 +53,25 @@ namespace java { class MessageGenerator { public: explicit MessageGenerator(const Descriptor* descriptor); - virtual ~MessageGenerator(); + ~MessageGenerator(); // All static variables have to be declared at the top-level of the file // so that we can control initialization order, which is important for // DescriptorProto bootstrapping to work. - virtual void GenerateStaticVariables(io::Printer* printer) = 0; + void GenerateStaticVariables(io::Printer* printer); // Output code which initializes the static variables generated by // GenerateStaticVariables(). - virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0; + void GenerateStaticVariableInitializers(io::Printer* printer); // Generate the class itself. - virtual void Generate(io::Printer* printer) = 0; - - // Generates the base interface that both the class and its builder implement - virtual void GenerateInterface(io::Printer* printer) = 0; + void Generate(io::Printer* printer); // Generate code to register all contained extensions with an // ExtensionRegistry. - virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0; - - protected: - const Descriptor* descriptor_; + void GenerateExtensionRegistrationCode(io::Printer* printer); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); -}; - -class ImmutableMessageGenerator : public MessageGenerator { - public: - explicit ImmutableMessageGenerator(const Descriptor* descriptor, - Context* context); - virtual ~ImmutableMessageGenerator(); - - virtual void Generate(io::Printer* printer); - virtual void GenerateInterface(io::Printer* printer); - virtual void GenerateExtensionRegistrationCode(io::Printer* printer); - virtual void GenerateStaticVariables(io::Printer* printer); - virtual void GenerateStaticVariableInitializers(io::Printer* printer); - - private: - enum UseMemoization { - MEMOIZE, - DONT_MEMOIZE - }; - - void GenerateFieldAccessorTable(io::Printer* printer); - void GenerateFieldAccessorTableInitializer(io::Printer* printer); - void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); void GenerateSerializeOneField(io::Printer* printer, @@ -117,19 +81,13 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateDescriptorMethods(io::Printer* printer); void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer, - UseMemoization useMemoization); - void GenerateEqualsAndHashCode(io::Printer* printer); - void GenerateParser(io::Printer* printer); - void GenerateParsingConstructor(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer); - Context* context_; - ClassNameResolver* name_resolver_; - FieldGeneratorMap<ImmutableFieldGenerator> field_generators_; + const Descriptor* descriptor_; + FieldGeneratorMap field_generators_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index e681314..71edc02 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,11 +35,8 @@ #include <map> #include <string> -#include <google/protobuf/compiler/java/java_context.h> #include <google/protobuf/compiler/java/java_message_field.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> @@ -51,413 +48,88 @@ namespace java { namespace { +// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of +// repeat code between this and the other field types. void SetMessageVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, map<string, string>* variables) { - SetCommonFieldVariables(descriptor, info, variables); - - (*variables)["type"] = - name_resolver->GetImmutableClassName(descriptor->message_type()); - (*variables)["mutable_type"] = - name_resolver->GetMutableClassName(descriptor->message_type()); + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = ClassName(descriptor->message_type()); (*variables)["group_or_message"] = (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported - // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; - (*variables)["on_changed"] = - HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - - if (SupportFieldPresence(descriptor->file())) { - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - - // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - - (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); - } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != null"; - } - - // For repated builders, one bit is used for whether the array is immutable. - (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - - (*variables)["get_has_field_bit_from_local"] = - GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); } } // namespace // =================================================================== -ImmutableMessageFieldGenerator:: -ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +MessageFieldGenerator:: +MessageFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetMessageVariables(descriptor, &variables_); } -ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} +MessageFieldGenerator::~MessageFieldGenerator() {} -int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} - -void ImmutableMessageFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - // TODO(jonp): In the future, consider having a method specific to the - // interface so that builders can choose dynamically to either return a - // message or a nested builder, so that asking for the interface doesn't - // cause a message to ever be built. - if (SupportFieldPresence(descriptor_->file()) || - descriptor_->containing_oneof() == NULL) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); - } -} - -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private $type$ $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "get$capitalized_name$OrBuilder() {\n" - " return $name$_;\n" - "}\n"); - } - } else { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $name$_ != null;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "get$capitalized_name$OrBuilder() {\n" - " return get$capitalized_name$();\n" - "}\n"); - } - } + "private boolean has$capitalized_name$;\n" + "private $type$ $name$_;\n" + "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" + "public $type$ get$capitalized_name$() { return $name$_; }\n"); } -void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( - io::Printer* printer, - const char* regular_case, - const char* nested_builder_case) const { - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, "if ($name$Builder_ == null) {\n"); - printer->Indent(); - printer->Print(variables_, regular_case); - printer->Outdent(); - printer->Print("} else {\n"); - printer->Indent(); - printer->Print(variables_, nested_builder_case); - printer->Outdent(); - printer->Print("}\n"); - } else { - printer->Print(variables_, regular_case); - } -} - -void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( - io::Printer* printer, - const char* method_prototype, - const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const { - printer->Print(variables_, method_prototype); - printer->Print(" {\n"); - printer->Indent(); - PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); - if (trailing_code != NULL) { - printer->Print(variables_, trailing_code); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - bool support_field_presence = SupportFieldPresence(descriptor_->file()); - - if (support_field_presence) { - printer->Print(variables_, - // Used when the builder is null. - "private $type$ $name$_ = $type$.getDefaultInstance();\n"); - } else { - printer->Print(variables_, - "private $type$ $name$_ = null;\n"); - } - - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - } - - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - if (support_field_presence) { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - } else { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $name$Builder_ != null || $name$_ != null;\n" - "}\n"); - } - - // Field getField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$()", - - support_field_presence - ? "return $name$_;\n" - : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n", - - "return $name$Builder_.getMessage();\n", - - NULL); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" + printer->Print(variables_, + "public boolean has$capitalized_name$() {\n" + " return result.has$capitalized_name$();\n" "}\n" - "$name$_ = value;\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(value);\n", - - "$set_has_field_bit_builder$\n" - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "$name$_ = builderForValue.build();\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(builderForValue.build());\n", - - "$set_has_field_bit_builder$\n" - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - support_field_presence - ? "if ($get_has_field_bit_builder$ &&\n" - " $name$_ != $type$.getDefaultInstance()) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n" - : "if ($name$_ != null) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n", - - "$name$Builder_.mergeFrom(value);\n", - - "$set_has_field_bit_builder$\n" - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - support_field_presence - ? "$name$_ = $type$.getDefaultInstance();\n" - "$on_changed$\n" - : "$name$_ = null;\n" - "$on_changed$\n", - - support_field_presence - ? "$name$Builder_.clear();\n" - : "$name$_ = null;\n" - "$name$Builder_ = null;\n", - - "$clear_has_field_bit_builder$\n" - "return this;\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n"); - if (support_field_presence) { - printer->Print(variables_, - " return $name$_;\n"); - } else { - printer->Print(variables_, - " return $name$_ == null ?\n" - " $type$.getDefaultInstance() : $name$_;\n"); - } - printer->Print(variables_, - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " get$capitalized_name$(),\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } -} - -void ImmutableMessageFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); - } + "public $type$ get$capitalized_name$() {\n" + " return result.get$capitalized_name$();\n" + "}\n" + "public Builder set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " result.has$capitalized_name$ = true;\n" + " result.$name$_ = value;\n" + " return this;\n" + "}\n" + "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n" + " result.has$capitalized_name$ = true;\n" + " result.$name$_ = builderForValue.build();\n" + " return this;\n" + "}\n" + "public Builder merge$capitalized_name$($type$ value) {\n" + " if (result.has$capitalized_name$() &&\n" + " result.$name$_ != $type$.getDefaultInstance()) {\n" + " result.$name$_ =\n" + " $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n" + " } else {\n" + " result.$name$_ = value;\n" + " }\n" + " result.has$capitalized_name$ = true;\n" + " return this;\n" + "}\n" + "public Builder clear$capitalized_name$() {\n" + " result.has$capitalized_name$ = false;\n" + " result.$name$_ = $type$.getDefaultInstance();\n" + " return this;\n" + "}\n"); } - -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); - } + printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); } -void ImmutableMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - PrintNestedBuilderCondition(printer, - "$name$_ = $type$.getDefaultInstance();\n", - - "$name$Builder_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$\n"); - } else { - PrintNestedBuilderCondition(printer, - "$name$_ = null;\n", - - "$name$_ = null;\n" - "$name$Builder_ = null;\n"); - } -} - -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, "if (other.has$capitalized_name$()) {\n" @@ -465,876 +137,196 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - } - - PrintNestedBuilderCondition(printer, - "result.$name$_ = $name$_;\n", - - "result.$name$_ = $name$Builder_.build();\n"); + // Nothing to do for singular fields. } -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" + "$type$.Builder subBuilder = $type$.newBuilder();\n" + "if (has$capitalized_name$()) {\n" + " subBuilder.mergeFrom(get$capitalized_name$());\n" "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.PARSER,\n" - " extensionRegistry);\n"); + "input.readGroup($number$, subBuilder, extensionRegistry);\n"); } else { printer->Print(variables_, - "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + "input.readMessage(subBuilder, extensionRegistry);\n"); } printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom($name$_);\n" - " $name$_ = subBuilder.buildPartial();\n" - "}\n" - "$set_has_field_bit_message$\n"); + "set$capitalized_name$(subBuilder.buildPartial());\n"); } -void ImmutableMessageFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for messages. -} - -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$group_or_message$($number$, $name$_);\n" + "if (has$capitalized_name$()) {\n" + " output.write$group_or_message$($number$, get$capitalized_name$());\n" "}\n"); } -void ImmutableMessageFieldGenerator:: +void MessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" + "if (has$capitalized_name$()) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, $name$_);\n" + " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" "}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); -} - -void ImmutableMessageFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); -} - -string ImmutableMessageFieldGenerator::GetBoxedType() const { - return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +string MessageFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->message_type()); } // =================================================================== -ImmutableMessageOneofFieldGenerator:: -ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); +RepeatedMessageFieldGenerator:: +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetMessageVariables(descriptor, &variables_); } -ImmutableMessageOneofFieldGenerator:: -~ImmutableMessageOneofFieldGenerator() {} +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} -void ImmutableMessageOneofFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + "public java.util.List<$type$> get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n" + "public int get$capitalized_name$Count() { return $name$_.size(); }\n" + "public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" "}\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - } } -void ImmutableMessageOneofFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - } - - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - if (SupportFieldPresence(descriptor_->file())) { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - - // Field getField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$()", - - "if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" + printer->Print(variables_, + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + "public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(result.$name$_);\n" "}\n" - "return $type$.getDefaultInstance();\n", - - "if ($has_oneof_case_message$) {\n" - " return $name$Builder_.getMessage();\n" + "public int get$capitalized_name$Count() {\n" + " return result.get$capitalized_name$Count();\n" "}\n" - "return $type$.getDefaultInstance();\n", - - NULL); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$oneof_name$_ = value;\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(value);\n", - - "$set_oneof_case_message$;\n" - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "$oneof_name$_ = builderForValue.build();\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(builderForValue.build());\n", - - "$set_oneof_case_message$;\n" - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($has_oneof_case_message$ &&\n" - " $oneof_name$_ != $type$.getDefaultInstance()) {\n" - " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" - " .mergeFrom(value).buildPartial();\n" - "} else {\n" - " $oneof_name$_ = value;\n" + "public $type$ get$capitalized_name$(int index) {\n" + " return result.get$capitalized_name$(index);\n" "}\n" - "$on_changed$\n", - - "if ($has_oneof_case_message$) {\n" - " $name$Builder_.mergeFrom(value);\n" - "}\n" - "$name$Builder_.setMessage(value);\n", - - "$set_oneof_case_message$;\n" - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - "}\n", - - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" + "public Builder set$capitalized_name$(int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " result.$name$_.set(index, value);\n" + " return this;\n" "}\n" - "$name$Builder_.clear();\n", - - "return this;\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = $type$.getDefaultInstance();\n" - " }\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " ($type$) $oneof_name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $oneof_name$_ = null;\n" - " }\n" - " $set_oneof_case_message$;\n" - " return $name$Builder_;\n" - "}\n"); - } -} - -void ImmutableMessageOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n"); - printer->Indent(); - - PrintNestedBuilderCondition(printer, - "result.$oneof_name$_ = $oneof_name$_;\n", - - "result.$oneof_name$_ = $name$Builder_.build();\n"); - - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableMessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "merge$capitalized_name$(other.get$capitalized_name$());\n"); -} - -void ImmutableMessageOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($has_oneof_case_message$) {\n" - " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" - "}\n"); - - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" - " extensionRegistry);\n"); - } else { - printer->Print(variables_, - "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); - } - - printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" - " $oneof_name$_ = subBuilder.buildPartial();\n" - "}\n"); - printer->Print(variables_, - "$set_oneof_case_message$;\n"); -} - -void ImmutableMessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" - "}\n"); -} - -void ImmutableMessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" - "}\n"); -} - -// =================================================================== - -RepeatedImmutableMessageFieldGenerator:: -RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} - -RepeatedImmutableMessageFieldGenerator:: -~RepeatedImmutableMessageFieldGenerator() {} - -int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const { - return 0; -} - -int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - // TODO(jonp): In the future, consider having methods specific to the - // interface so that builders can choose dynamically to either return a - // message or a nested builder, so that asking for the interface doesn't - // cause a message to ever be built. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<$type$> \n" - " get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<? extends $type$OrBuilder> \n" - " get$capitalized_name$OrBuilderList();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index);\n"); - } -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List<$type$> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder> \n" - " get$capitalized_name$OrBuilderList() {\n" - " return $name$_;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - -} - -void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( - io::Printer* printer, - const char* regular_case, - const char* nested_builder_case) const { - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, "if ($name$Builder_ == null) {\n"); - printer->Indent(); - printer->Print(variables_, regular_case); - printer->Outdent(); - printer->Print("} else {\n"); - printer->Indent(); - printer->Print(variables_, nested_builder_case); - printer->Outdent(); - printer->Print("}\n"); - } else { - printer->Print(variables_, regular_case); - } -} - -void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( - io::Printer* printer, - const char* method_prototype, - const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const { - printer->Print(variables_, method_prototype); - printer->Print(" {\n"); - printer->Indent(); - PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); - if (trailing_code != NULL) { - printer->Print(variables_, trailing_code); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - // Used when the builder is null. - // One field is the list and the other field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" + "public Builder set$capitalized_name$(int index, " + "$type$.Builder builderForValue) {\n" + " result.$name$_.set(index, builderForValue.build());\n" + " return this;\n" "}\n" - "\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); - } - - // The comments above the methods below are based on a hypothetical - // repeated field of type "Field" called "RepeatedField". - - // List<Field> getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", - - "return java.util.Collections.unmodifiableList($name$_);\n", - "return $name$Builder_.getMessageList();\n", - - NULL); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public int get$capitalized_name$Count()", - - "return $name$_.size();\n", - "return $name$Builder_.getCount();\n", - - NULL); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$(int index)", - - "return $name$_.get(index);\n", - - "return $name$Builder_.getMessage(index);\n", - - NULL); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" + "public Builder add$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " }\n" + " result.$name$_.add(value);\n" + " return this;\n" "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, value);\n" - "$on_changed$\n", - "$name$Builder_.setMessage(index, value);\n", - "return this;\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, builderForValue.build());\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" + "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " }\n" + " result.$name$_.add(builderForValue.build());\n" + " return this;\n" "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(value);\n" - - "$on_changed$\n", - - "$name$Builder_.addMessage(value);\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" + "public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable<? extends $type$> values) {\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " }\n" + " super.addAll(values, result.$name$_);\n" + " return this;\n" "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, value);\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, value);\n", - - "return this;\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(builderForValue.build());\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, builderForValue.build());\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addAllRepeatedField(Iterable<Field> values) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable<? extends $type$> values)", - - "ensure$capitalized_name$IsMutable();\n" - "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - "$on_changed$\n", - - "$name$Builder_.addAllMessages(values);\n", - - "return this;\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n" - "$on_changed$\n", - - "$name$Builder_.clear();\n", - - "return this;\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder remove$capitalized_name$(int index)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.remove(index);\n" - "$on_changed$\n", - - "$name$Builder_.remove(index);\n", - - "return this;\n"); - - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder> \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); + "public Builder clear$capitalized_name$() {\n" + " result.$name$_ = java.util.Collections.emptyList();\n" + " return this;\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - PrintNestedBuilderCondition(printer, - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n", - - "$name$Builder_.clear();\n"); + // Initialized inline. } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations (non-nested builder case): - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - PrintNestedBuilderCondition(printer, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n", - + printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if ($name$Builder_.isEmpty()) {\n" - " $name$Builder_.dispose();\n" - " $name$Builder_ = null;\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " $name$Builder_ = \n" - " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n" - " get$capitalized_name$FieldBuilder() : null;\n" - " } else {\n" - " $name$Builder_.addAllMessages(other.$name$_);\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$type$>();\n" " }\n" + " result.$name$_.addAll(other.$name$_);\n" "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // The code below (non-nested builder case) ensures that the result has an - // immutable list. If our list is immutable, we can just reuse it. If not, - // we make it immutable. - PrintNestedBuilderCondition(printer, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n", - - "result.$name$_ = $name$Builder_.build();\n"); + printer->Print(variables_, + "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" + " result.$name$_ =\n" + " java.util.Collections.unmodifiableList(result.$name$_);\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); + "$type$.Builder subBuilder = $type$.newBuilder();\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" - " extensionRegistry));\n"); + "input.readGroup($number$, subBuilder, extensionRegistry);\n"); } else { printer->Print(variables_, - "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); + "input.readMessage(subBuilder, extensionRegistry);\n"); } -} -void RepeatedImmutableMessageFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); + "add$capitalized_name$(subBuilder.buildPartial());\n"); } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$group_or_message$($number$, $name$_.get(i));\n" + "for ($type$ element : get$capitalized_name$List()) {\n" + " output.write$group_or_message$($number$, element);\n" "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: +void RepeatedMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" + "for ($type$ element : get$capitalized_name$List()) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, $name$_.get(i));\n" - "}\n"); -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutableMessageFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + " .compute$group_or_message$Size($number$, element);\n" "}\n"); } -string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { - return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +string RepeatedMessageFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->message_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index ea8225a..66bdd88 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -41,128 +41,55 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} - -namespace protobuf { namespace compiler { namespace java { -class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { +class MessageFieldGenerator : public FieldGenerator { public: - explicit ImmutableMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableMessageFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + explicit MessageFieldGenerator(const FieldDescriptor* descriptor); + ~MessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - - void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; - void PrintNestedBuilderFunction(io::Printer* printer, - const char* method_prototype, const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; -class ImmutableMessageOneofFieldGenerator - : public ImmutableMessageFieldGenerator { +class RepeatedMessageFieldGenerator : public FieldGenerator { public: - ImmutableMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableMessageOneofFieldGenerator(); + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + ~RepeatedMessageFieldGenerator(); - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator); -}; - -class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { - public: - explicit RepeatedImmutableMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableMessageFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - - void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; - void PrintNestedBuilderFunction(io::Printer* printer, - const char* method_prototype, const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc deleted file mode 100644 index 0c363f9..0000000 --- a/src/google/protobuf/compiler/java/java_name_resolver.cc +++ /dev/null @@ -1,266 +0,0 @@ -// 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 <google/protobuf/compiler/java/java_name_resolver.h> - -#include <map> -#include <string> - -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/stubs/substitute.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -namespace { -// A suffix that will be appended to the file's outer class name if the name -// conflicts with some other types defined in the file. -const char* kOuterClassNameSuffix = "OuterClass"; - -// Strip package name from a descriptor's full name. -// For example: -// Full name : foo.Bar.Baz -// Package name: foo -// After strip : Bar.Baz -string StripPackageName(const string& full_name, - const FileDescriptor* file) { - if (file->package().empty()) { - return full_name; - } else { - // Strip package name - return full_name.substr(file->package().size() + 1); - } -} - -// Get the name of a message's Java class without package name prefix. -string ClassNameWithoutPackage(const Descriptor* descriptor, - bool immutable) { - return StripPackageName(descriptor->full_name(), - descriptor->file()); -} - -// Get the name of an enum's Java class without package name prefix. -string ClassNameWithoutPackage(const EnumDescriptor* descriptor, - bool immutable) { - // Doesn't append "Mutable" for enum type's name. - const Descriptor* message_descriptor = descriptor->containing_type(); - if (message_descriptor == NULL) { - return descriptor->name(); - } else { - return ClassNameWithoutPackage(message_descriptor, immutable) + - "." + descriptor->name(); - } -} - -// Get the name of a service's Java class without package name prefix. -string ClassNameWithoutPackage(const ServiceDescriptor* descriptor, - bool immutable) { - string full_name = StripPackageName(descriptor->full_name(), - descriptor->file()); - // We don't allow nested service definitions. - GOOGLE_CHECK(full_name.find('.') == string::npos); - return full_name; -} - -// Check whether a given message or its nested types has the given class name. -bool MessageHasConflictingClassName(const Descriptor* message, - const string& classname) { - if (message->name() == classname) return true; - for (int i = 0; i < message->nested_type_count(); ++i) { - if (MessageHasConflictingClassName(message->nested_type(i), classname)) { - return true; - } - } - for (int i = 0; i < message->enum_type_count(); ++i) { - if (message->enum_type(i)->name() == classname) { - return true; - } - } - return false; -} - -} // namespace - -ClassNameResolver::ClassNameResolver() { -} - -ClassNameResolver::~ClassNameResolver() { -} - -string ClassNameResolver::GetFileDefaultImmutableClassName( - const FileDescriptor* file) { - string basename; - string::size_type last_slash = file->name().find_last_of('/'); - if (last_slash == string::npos) { - basename = file->name(); - } else { - basename = file->name().substr(last_slash + 1); - } - return UnderscoresToCamelCase(StripProto(basename), true); -} - -string ClassNameResolver::GetFileImmutableClassName( - const FileDescriptor* file) { - string& class_name = file_immutable_outer_class_names_[file]; - if (class_name.empty()) { - if (file->options().has_java_outer_classname()) { - class_name = file->options().java_outer_classname(); - } else { - class_name = GetFileDefaultImmutableClassName(file); - if (HasConflictingClassName(file, class_name)) { - class_name += kOuterClassNameSuffix; - } - } - } - return class_name; -} - -string ClassNameResolver::GetFileClassName(const FileDescriptor* file, - bool immutable) { - if (immutable) { - return GetFileImmutableClassName(file); - } else { - return "Mutable" + GetFileImmutableClassName(file); - } -} - -// Check whether there is any type defined in the proto file that has -// the given class name. -bool ClassNameResolver::HasConflictingClassName( - const FileDescriptor* file, const string& classname) { - for (int i = 0; i < file->enum_type_count(); i++) { - if (file->enum_type(i)->name() == classname) { - return true; - } - } - for (int i = 0; i < file->service_count(); i++) { - if (file->service(i)->name() == classname) { - return true; - } - } - for (int i = 0; i < file->message_type_count(); i++) { - if (MessageHasConflictingClassName(file->message_type(i), classname)) { - return true; - } - } - return false; -} - -string ClassNameResolver::GetDescriptorClassName( - const FileDescriptor* descriptor) { - return GetFileImmutableClassName(descriptor); -} - -string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, - bool immutable) { - string result = FileJavaPackage(descriptor, immutable); - if (!result.empty()) result += '.'; - result += GetFileClassName(descriptor, immutable); - return result; -} - -// Get the full name of a Java class by prepending the Java package name -// or outer class name. -string ClassNameResolver::GetClassFullName(const string& name_without_package, - const FileDescriptor* file, - bool immutable, - bool multiple_files) { - string result; - if (multiple_files) { - result = FileJavaPackage(file, immutable); - } else { - result = GetClassName(file, immutable); - } - if (!result.empty()) { - result += '.'; - } - result += name_without_package; - return result; -} - -string ClassNameResolver::GetClassName(const Descriptor* descriptor, - bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); -} - -string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, - bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); -} - -string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, - bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); -} - -// Get the Java Class style full name of a message. -string ClassNameResolver::GetJavaClassFullName( - const string& name_without_package, - const FileDescriptor* file, - bool immutable) { - string result; - if (MultipleJavaFiles(file, immutable)) { - result = FileJavaPackage(file, immutable); - if (!result.empty()) result += '.'; - } else { - result = GetClassName(file, immutable); - if (!result.empty()) result += '$'; - } - result += StringReplace(name_without_package, ".", "$", true); - return result; -} - -string ClassNameResolver::GetExtensionIdentifierName( - const FieldDescriptor* descriptor, bool immutable) { - return GetClassName(descriptor->containing_type(), immutable) + "." + - descriptor->name(); -} - - -string ClassNameResolver::GetJavaImmutableClassName( - const Descriptor* descriptor) { - return GetJavaClassFullName( - ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); -} - - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h deleted file mode 100644 index ab60b0a..0000000 --- a/src/google/protobuf/compiler/java/java_name_resolver.h +++ /dev/null @@ -1,124 +0,0 @@ -// 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. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ - -#include <map> -#include <string> - -#include <google/protobuf/stubs/common.h> - -namespace google { -namespace protobuf { -class Descriptor; -class EnumDescriptor; -class FieldDescriptor; -class FileDescriptor; -class ServiceDescriptor; - -namespace compiler { -namespace java { - -// Used to get the Java class related names for a given descriptor. It caches -// the results to avoid redundant calculation across multiple name queries. -// Thread-safety note: This class is *not* thread-safe. -class ClassNameResolver { - public: - ClassNameResolver(); - ~ClassNameResolver(); - - // Gets the unqualified outer class name for the file. - string GetFileClassName(const FileDescriptor* file, bool immutable); - // Gets the unqualified immutable outer class name of a file. - string GetFileImmutableClassName(const FileDescriptor* file); - // Gets the unqualified default immutable outer class name of a file - // (converted from the proto file's name). - string GetFileDefaultImmutableClassName(const FileDescriptor* file); - - // Check whether there is any type defined in the proto file that has - // the given class name. - bool HasConflictingClassName(const FileDescriptor* file, - const string& classname); - - // Gets the name of the outer class that holds descriptor information. - // Descriptors are shared between immutable messages and mutable messages. - // Since both of them are generated optionally, the descriptors need to be - // put in another common place. - string GetDescriptorClassName(const FileDescriptor* file); - - // Gets the fully-qualified class name corresponding to the given descriptor. - string GetClassName(const Descriptor* descriptor, bool immutable); - string GetClassName(const EnumDescriptor* descriptor, bool immutable); - string GetClassName(const ServiceDescriptor* descriptor, bool immutable); - string GetClassName(const FileDescriptor* descriptor, bool immutable); - - template<class DescriptorType> - string GetImmutableClassName(const DescriptorType* descriptor) { - return GetClassName(descriptor, true); - } - template<class DescriptorType> - string GetMutableClassName(const DescriptorType* descriptor) { - return GetClassName(descriptor, false); - } - - // Gets the fully qualified name of an extension identifier. - string GetExtensionIdentifierName(const FieldDescriptor* descriptor, - bool immutable); - - // Gets the fully qualified name for generated classes in Java convention. - // Nested classes will be separated using '$' instead of '.' - // For example: - // com.package.OuterClass$OuterMessage$InnerMessage - string GetJavaImmutableClassName(const Descriptor* descriptor); - private: - // Get the full name of a Java class by prepending the Java package name - // or outer class name. - string GetClassFullName(const string& name_without_package, - const FileDescriptor* file, - bool immutable, - bool multiple_files); - // Get the Java Class style full name of a message. - string GetJavaClassFullName( - const string& name_without_package, - const FileDescriptor* file, - bool immutable); - // Caches the result to provide better performance. - map<const FileDescriptor*, string> file_immutable_outer_class_names_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index c4d6995..cfe0188 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -34,8 +34,6 @@ // It seemed like parameterizing it would add more complexity than it is // worth. -#include <memory> - #include <google/protobuf/compiler/java/java_generator.h> #include <google/protobuf/compiler/command_line_interface.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -58,22 +56,21 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { - string filename = "Test.java"; - TryInsert(filename, "outer_class_scope", context); - TryInsert(filename, "class_scope:foo.Bar", context); - TryInsert(filename, "class_scope:foo.Bar.Baz", context); - TryInsert(filename, "builder_scope:foo.Bar", context); - TryInsert(filename, "builder_scope:foo.Bar.Baz", context); - TryInsert(filename, "enum_scope:foo.Qux", context); + TryInsert("Test.java", "outer_class_scope", output_directory); + TryInsert("Test.java", "class_scope:foo.Bar", output_directory); + TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory); + TryInsert("Test.java", "builder_scope:foo.Bar", output_directory); + TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory); + TryInsert("Test.java", "enum_scope:foo.Qux", output_directory); return true; } void TryInsert(const string& filename, const string& insertion_point, - GeneratorContext* context) const { + OutputDirectory* output_directory) const { scoped_ptr<io::ZeroCopyOutputStream> output( - context->OpenForInsert(filename, insertion_point)); + output_directory->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -83,16 +80,16 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(JavaPluginTest, PluginTest) { - GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", - "syntax = \"proto2\";\n" - "package foo;\n" - "option java_package = \"\";\n" - "option java_outer_classname = \"Test\";\n" - "message Bar {\n" - " message Baz {}\n" - "}\n" - "enum Qux { BLAH = 1; }\n", - true)); + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "option java_package = \"\";\n" + "option java_outer_classname = \"Test\";\n" + "message Bar {\n" + " message Baz {}\n" + "}\n" + "enum Qux { BLAH = 1; }\n", + TestTempDir() + "/test.proto"); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 6713d29..f6179bf 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -35,12 +35,9 @@ #include <map> #include <string> +#include <google/protobuf/compiler/java/java_primitive_field.h> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/compiler/java/java_primitive_field.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> @@ -75,25 +72,98 @@ const char* PrimitiveTypeName(JavaType type) { return NULL; } +bool IsReferenceType(JavaType type) { + switch (type) { + case JAVATYPE_INT : return false; + case JAVATYPE_LONG : return false; + case JAVATYPE_FLOAT : return false; + case JAVATYPE_DOUBLE : return false; + case JAVATYPE_BOOLEAN: return false; + case JAVATYPE_STRING : return true; + case JAVATYPE_BYTES : return true; + case JAVATYPE_ENUM : return true; + case JAVATYPE_MESSAGE: return true; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* GetCapitalizedType(const FieldDescriptor* field) { + switch (GetType(field)) { + case FieldDescriptor::TYPE_INT32 : return "Int32" ; + case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; + case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; + case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; + case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; + case FieldDescriptor::TYPE_INT64 : return "Int64" ; + case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; + case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; + case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; + case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT : return "Float" ; + case FieldDescriptor::TYPE_DOUBLE : return "Double" ; + case FieldDescriptor::TYPE_BOOL : return "Bool" ; + case FieldDescriptor::TYPE_STRING : return "String" ; + case FieldDescriptor::TYPE_BYTES : return "Bytes" ; + case FieldDescriptor::TYPE_ENUM : return "Enum" ; + case FieldDescriptor::TYPE_GROUP : return "Group" ; + case FieldDescriptor::TYPE_MESSAGE : return "Message" ; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, map<string, string>* variables) { - SetCommonFieldVariables(descriptor, info, variables); - + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); - (*variables)["field_type"] = (*variables)["type"]; - (*variables)["field_list_type"] = "java.util.List<" + - (*variables)["boxed_type"] + ">"; - (*variables)["empty_list"] = "java.util.Collections.emptyList()"; - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? - "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); - (*variables)["capitalized_type"] = - GetCapitalizedType(descriptor, /* immutable = */ true); + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); @@ -105,517 +175,129 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } else { (*variables)["null_check"] = ""; } - // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported - // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); } - (*variables)["on_changed"] = - HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - - if (SupportFieldPresence(descriptor->file())) { - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - - // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - - (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); - } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { - (*variables)["is_field_present_message"] = - "!" + (*variables)["name"] + "_.isEmpty()"; - } else { - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"]; - } - } - - // For repated builders, one bit is used for whether the array is immutable. - (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - - (*variables)["get_has_field_bit_from_local"] = - GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); } - } // namespace // =================================================================== -ImmutablePrimitiveFieldGenerator:: -ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +PrimitiveFieldGenerator:: +PrimitiveFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, &variables_); } -ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} - -int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} -void ImmutablePrimitiveFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); -} - -void ImmutablePrimitiveFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private $field_type$ $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); + "private boolean has$capitalized_name$;\n" + "private $type$ $name$_ = $default$;\n" + "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" + "public $type$ get$capitalized_name$() { return $name$_; }\n"); } -void ImmutablePrimitiveFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "private $field_type$ $name$_ $default_init$;\n"); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + "public boolean has$capitalized_name$() {\n" + " return result.has$capitalized_name$();\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " return result.get$capitalized_name$();\n" + "}\n" + "public Builder set$capitalized_name$($type$ value) {\n" "$null_check$" - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" + " result.has$capitalized_name$ = true;\n" + " result.$name$_ = value;\n" " return this;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$\n"); + "}\n" + "public Builder clear$capitalized_name$() {\n" + " result.has$capitalized_name$ = false;\n"); JavaType type = GetJavaType(descriptor_); if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, - " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); } else { printer->Print(variables_, - " $name$_ = $default$;\n"); + " result.$name$_ = $default$;\n"); } printer->Print(variables_, - " $on_changed$\n" " return this;\n" "}\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} - -void ImmutablePrimitiveFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); + // Initialized inline. } -void ImmutablePrimitiveFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } else { - printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$set_has_field_bit_message$\n" - "$name$_ = input.read$capitalized_type$();\n"); -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for primitives. -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$capitalized_type$($number$, $name$_);\n" - "}\n"); -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, $name$_);\n" + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" "}\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - switch (GetJavaType(descriptor_)) { - case JAVATYPE_INT: - case JAVATYPE_LONG: - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "result = result && (get$capitalized_name$()\n" - " == other.get$capitalized_name$());\n"); - break; - - case JAVATYPE_FLOAT: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" - " == java.lang.Float.floatToIntBits(\n" - " other.get$capitalized_name$()));\n"); - break; - - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" - " == java.lang.Double.doubleToLongBits(\n" - " other.get$capitalized_name$()));\n"); - break; - - case JAVATYPE_STRING: - case JAVATYPE_BYTES: - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); - break; - - case JAVATYPE_ENUM: - case JAVATYPE_MESSAGE: - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - break; - } -} - -void ImmutablePrimitiveFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); - switch (GetJavaType(descriptor_)) { - case JAVATYPE_INT: - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$();\n"); - break; - - case JAVATYPE_LONG: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_FLOAT: - printer->Print(variables_, - "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); - break; - - case JAVATYPE_STRING: - case JAVATYPE_BYTES: - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); - break; - - case JAVATYPE_ENUM: - case JAVATYPE_MESSAGE: - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - break; - } -} - -string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { - return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); -} - -// =================================================================== - -ImmutablePrimitiveOneofFieldGenerator:: -ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutablePrimitiveFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); -} - -ImmutablePrimitiveOneofFieldGenerator:: -~ImmutablePrimitiveOneofFieldGenerator() {} - -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($boxed_type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); -} - - -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($boxed_type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); -} - -void ImmutablePrimitiveOneofFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); -} - -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); + // Nothing to do here for primitive types. } -void ImmutablePrimitiveOneofFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = input.read$capitalized_type$();\n"); + "set$capitalized_name$(input.read$capitalized_type$());\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$capitalized_type$(\n" - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "if (has$capitalized_name$()) {\n" + " output.write$capitalized_type$($number$, get$capitalized_name$());\n" "}\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: +void PrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" + "if (has$capitalized_name$()) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size(\n" - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" "}\n"); } -// =================================================================== - -RepeatedImmutablePrimitiveFieldGenerator:: -RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} - -RepeatedImmutablePrimitiveFieldGenerator:: -~RepeatedImmutablePrimitiveFieldGenerator() {} - -int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { - return 0; +string PrimitiveFieldGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } -int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} +// =================================================================== -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); +RepeatedPrimitiveFieldGenerator:: +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, &variables_); } +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private $field_list_type$ $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " get$capitalized_name$List() {\n" + "private java.util.List<$boxed_type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + "}\n" + "public int get$capitalized_name$Count() { return $name$_.size(); }\n" + "public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -626,170 +308,92 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { - // One field is the list and the bit field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - printer->Print(variables_, - "private $field_list_type$ $name$_ = $empty_list$;\n"); - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); - // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value) {\n" + "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(result.$name$_);\n" + "}\n" + "public int get$capitalized_name$Count() {\n" + " return result.get$capitalized_name$Count();\n" + "}\n" + "public $type$ get$capitalized_name$(int index) {\n" + " return result.get$capitalized_name$(index);\n" + "}\n" + "public Builder set$capitalized_name$(int index, $type$ value) {\n" "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" + " result.$name$_.set(index, value);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + "}\n" + "public Builder add$capitalized_name$($type$ value) {\n" "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " }\n" + " result.$name$_.add(value);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder addAll$capitalized_name$(\n" + "}\n" + "public Builder addAll$capitalized_name$(\n" " java.lang.Iterable<? extends $boxed_type$> values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - " $on_changed$\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " }\n" + " super.addAll(values, result.$name$_);\n" " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $name$_ = $empty_list$;\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" + "}\n" + "public Builder clear$capitalized_name$() {\n" + " result.$name$_ = java.util.Collections.emptyList();\n" " return this;\n" "}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} - -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $empty_list$;\n"); + // Initialized inline. } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); -} - -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" + " if (result.$name$_.isEmpty()) {\n" + " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" " }\n" - " $on_changed$\n" + " result.$name$_.addAll(other.$name$_);\n" "}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // The code below ensures that the result has an immutable list. If our - // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" + " result.$name$_ =\n" + " java.util.Collections.unmodifiableList(result.$name$_);\n" + "}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(input.read$capitalized_type$());\n"); + "add$capitalized_name$(input.read$capitalized_type$());\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { printer->Print(variables_, "int length = input.readRawVarint32();\n" "int limit = input.pushLimit(length);\n" - "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" "while (input.getBytesUntilLimit() > 0) {\n" - " $name$_.add(input.read$capitalized_type$());\n" + " add$capitalized_name$(input.read$capitalized_type$());\n" "}\n" "input.popLimit(limit);\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); -} - -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -797,18 +401,18 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "for ($type$ element : get$capitalized_name$List()) {\n" + " output.write$capitalized_type$NoTag(element);\n" "}\n"); } else { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$($number$, $name$_.get(i));\n" + "for ($type$ element : get$capitalized_name$List()) {\n" + " output.write$capitalized_type$($number$, element);\n" "}\n"); } } -void RepeatedImmutablePrimitiveFieldGenerator:: +void RepeatedPrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -817,9 +421,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { if (FixedSize(GetType(descriptor_)) == -1) { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" + "for ($type$ element : get$capitalized_name$List()) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" + " .compute$capitalized_type$SizeNoTag(element);\n" "}\n"); } else { printer->Print(variables_, @@ -851,23 +455,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); -} - -string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { +string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index d0cd12d..4e482a0 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -41,115 +41,56 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} - -namespace protobuf { namespace compiler { namespace java { -class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { +class PrimitiveFieldGenerator : public FieldGenerator { public: - explicit ImmutablePrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutablePrimitiveFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + ~PrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - protected: + private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; -class ImmutablePrimitiveOneofFieldGenerator - : public ImmutablePrimitiveFieldGenerator { +class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - ImmutablePrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutablePrimitiveOneofFieldGenerator(); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + ~RepeatedPrimitiveFieldGenerator(); - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator); -}; - -class RepeatedImmutablePrimitiveFieldGenerator - : public ImmutableFieldGenerator { - public: - explicit RepeatedImmutablePrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - virtual ~RepeatedImmutablePrimitiveFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; + // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 7baead1..5545bf7 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,11 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/java/java_service.h> - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> #include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> @@ -52,18 +48,8 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) ServiceGenerator::~ServiceGenerator() {} -// =================================================================== -ImmutableServiceGenerator::ImmutableServiceGenerator( - const ServiceDescriptor* descriptor, Context* context) - : ServiceGenerator(descriptor), context_(context), - name_resolver_(context->GetNameResolver()) {} - -ImmutableServiceGenerator::~ImmutableServiceGenerator() {} - -void ImmutableServiceGenerator::Generate(io::Printer* printer) { - bool is_own_file = - MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); - WriteServiceDocComment(printer, descriptor_); +void ServiceGenerator::Generate(io::Printer* printer) { + bool is_own_file = descriptor_->file()->options().java_multiple_files(); printer->Print( "public $static$ abstract class $classname$\n" " implements com.google.protobuf.Service {\n", @@ -89,7 +75,7 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { " getDescriptor() {\n" " return $file$.getDescriptor().getServices().get($index$);\n" "}\n", - "file", name_resolver_->GetImmutableClassName(descriptor_->file()), + "file", ClassName(descriptor_->file()), "index", SimpleItoa(descriptor_->index())); GenerateGetDescriptorForType(printer); @@ -100,18 +86,11 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { GenerateStub(printer); GenerateBlockingStub(printer); - // Add an insertion point. - printer->Print( - "\n" - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); - printer->Outdent(); printer->Print("}\n\n"); } -void ImmutableServiceGenerator::GenerateGetDescriptorForType( - io::Printer* printer) { +void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { printer->Print( "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" " getDescriptorForType() {\n" @@ -119,7 +98,7 @@ void ImmutableServiceGenerator::GenerateGetDescriptorForType( "}\n"); } -void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { +void ServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("public interface Interface {\n"); printer->Indent(); GenerateAbstractMethods(printer); @@ -127,7 +106,7 @@ void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("}\n\n"); } -void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( +void ServiceGenerator::GenerateNewReflectiveServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.Service newReflectiveService(\n" @@ -139,7 +118,7 @@ void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - printer->Print("@java.lang.Override\n"); + printer->Print("@Override\n"); GenerateMethodSignature(printer, method, IS_CONCRETE); printer->Print( " {\n" @@ -154,7 +133,7 @@ void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( printer->Print("}\n\n"); } -void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( +void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.BlockingService\n" @@ -175,16 +154,15 @@ void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( printer->Print("}\n\n"); } -void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { +void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - WriteMethodDocComment(printer, method); GenerateMethodSignature(printer, method, IS_ABSTRACT); printer->Print(";\n\n"); } } -void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { +void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { printer->Print( "\n" "public final void callMethod(\n" @@ -207,10 +185,8 @@ void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { map<string, string> vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName( - method->input_type()); - vars["output"] = name_resolver_->GetImmutableClassName( - method->output_type()); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); printer->Print(vars, "case $index$:\n" " this.$method$(controller, ($input$)request,\n" @@ -232,8 +208,7 @@ void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { "\n"); } -void ImmutableServiceGenerator::GenerateCallBlockingMethod( - io::Printer* printer) { +void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { printer->Print( "\n" "public final com.google.protobuf.Message callBlockingMethod(\n" @@ -255,10 +230,8 @@ void ImmutableServiceGenerator::GenerateCallBlockingMethod( map<string, string> vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName( - method->input_type()); - vars["output"] = name_resolver_->GetImmutableClassName( - method->output_type()); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); printer->Print(vars, "case $index$:\n" " return impl.$method$(controller, ($input$)request);\n"); @@ -277,7 +250,7 @@ void ImmutableServiceGenerator::GenerateCallBlockingMethod( "\n"); } -void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, +void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { /* * TODO(cpovirk): The exception message says "Service.foo" when it may be @@ -301,7 +274,7 @@ void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, const MethodDescriptor* method = descriptor_->method(i); map<string, string> vars; vars["index"] = SimpleItoa(i); - vars["type"] = name_resolver_->GetImmutableClassName( + vars["type"] = ClassName( (which == REQUEST) ? method->input_type() : method->output_type()); printer->Print(vars, "case $index$:\n" @@ -321,7 +294,7 @@ void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, "\n"); } -void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { +void ServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print( "public static Stub newStub(\n" " com.google.protobuf.RpcChannel channel) {\n" @@ -330,7 +303,7 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { "\n" "public static final class Stub extends $classname$ implements Interface {" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", ClassName(descriptor_)); printer->Indent(); printer->Print( @@ -353,8 +326,7 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { map<string, string> vars; vars["index"] = SimpleItoa(i); - vars["output"] = name_resolver_->GetImmutableClassName( - method->output_type()); + vars["output"] = ClassName(method->output_type()); printer->Print(vars, "channel.callMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -376,7 +348,7 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { "\n"); } -void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { +void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print( "public static BlockingInterface newBlockingStub(\n" " com.google.protobuf.BlockingRpcChannel channel) {\n" @@ -418,8 +390,7 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { map<string, string> vars; vars["index"] = SimpleItoa(i); - vars["output"] = name_resolver_->GetImmutableClassName( - method->output_type()); + vars["output"] = ClassName(method->output_type()); printer->Print(vars, "return ($output$) channel.callBlockingMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -437,13 +408,13 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print("}\n"); } -void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer, +void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract) { map<string, string> vars; vars["name"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); - vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : ""; printer->Print(vars, "public $abstract$ void $name$(\n" @@ -452,13 +423,13 @@ void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer, " com.google.protobuf.RpcCallback<$output$> done)"); } -void ImmutableServiceGenerator::GenerateBlockingMethodSignature( +void ServiceGenerator::GenerateBlockingMethodSignature( io::Printer* printer, const MethodDescriptor* method) { map<string, string> vars; vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); - vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); printer->Print(vars, "\n" "public $output$ $method$(\n" diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h index 6707e82..e07eebf 100644 --- a/src/google/protobuf/compiler/java/java_service.h +++ b/src/google/protobuf/compiler/java/java_service.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -40,14 +40,8 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -58,27 +52,9 @@ namespace java { class ServiceGenerator { public: explicit ServiceGenerator(const ServiceDescriptor* descriptor); - virtual ~ServiceGenerator(); - - virtual void Generate(io::Printer* printer) = 0; - - enum RequestOrResponse { REQUEST, RESPONSE }; - enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; - - protected: - const ServiceDescriptor* descriptor_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); -}; + ~ServiceGenerator(); -class ImmutableServiceGenerator : public ServiceGenerator { - public: - explicit ImmutableServiceGenerator(const ServiceDescriptor* descriptor, - Context* context); - virtual ~ImmutableServiceGenerator(); - - virtual void Generate(io::Printer* printer); + void Generate(io::Printer* printer); private: @@ -104,6 +80,7 @@ class ImmutableServiceGenerator : public ServiceGenerator { void GenerateCallBlockingMethod(io::Printer* printer); // Generate the implementations of Service.get{Request,Response}Prototype(). + enum RequestOrResponse { REQUEST, RESPONSE }; void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); // Generate a stub implementation of the service. @@ -111,6 +88,7 @@ class ImmutableServiceGenerator : public ServiceGenerator { // Generate a method signature, possibly abstract, without body or trailing // semicolon. + enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; void GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract); @@ -122,9 +100,9 @@ class ImmutableServiceGenerator : public ServiceGenerator { void GenerateBlockingMethodSignature(io::Printer* printer, const MethodDescriptor* method); - Context* context_; - ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator); + const ServiceDescriptor* descriptor_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc deleted file mode 100644 index ea77f79..0000000 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc +++ /dev/null @@ -1,201 +0,0 @@ -// 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. - -// Author: xiaofeng@google.com (Feng Xiao) - -#include <google/protobuf/compiler/java/java_shared_code_generator.h> - -#include <memory> - -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file) - : name_resolver_(new ClassNameResolver), file_(file) { -} - -SharedCodeGenerator::~SharedCodeGenerator() { -} - -void SharedCodeGenerator::Generate(GeneratorContext* context, - vector<string>* file_list) { - string java_package = FileJavaPackage(file_); - string package_dir = JavaPackageToDir(java_package); - - if (HasDescriptorMethods(file_)) { - // Generate descriptors. - string classname = name_resolver_->GetDescriptorClassName(file_); - string filename = package_dir + classname + ".java"; - file_list->push_back(filename); - scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$')); - - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n", - "filename", file_->name()); - if (!java_package.empty()) { - printer->Print( - "package $package$;\n" - "\n", - "package", java_package); - } - printer->Print( - "public final class $classname$ {\n" - " public static com.google.protobuf.Descriptors.FileDescriptor\n" - " descriptor;\n" - " static {\n", - "classname", classname); - printer->Indent(); - printer->Indent(); - GenerateDescriptors(printer.get()); - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" - "}\n"); - - printer.reset(); - output.reset(); - } -} - - -void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { - // Embed the descriptor. We simply serialize the entire FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. We unfortunately have to put it in - // a string literal, not a byte array, because apparently using a literal - // byte array causes the Java compiler to generate *instructions* to - // initialize each and every byte of the array, e.g. as if you typed: - // b[0] = 123; b[1] = 456; b[2] = 789; - // This makes huge bytecode files and can easily hit the compiler's internal - // code size limits (error "code to large"). String literals are apparently - // embedded raw, which is what we want. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - - - string file_data; - file_proto.SerializeToString(&file_data); - - printer->Print( - "java.lang.String[] descriptorData = {\n"); - printer->Indent(); - - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - if (i > 0) { - // Every 400 lines, start a new string literal, in order to avoid the - // 64k length limit. - if (i % 400 == 0) { - printer->Print(",\n"); - } else { - printer->Print(" +\n"); - } - } - printer->Print("\"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); - } - - printer->Outdent(); - printer->Print("\n};\n"); - - // ----------------------------------------------------------------- - // Create the InternalDescriptorAssigner. - - printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner assigner =\n" - " new com.google.protobuf.Descriptors.FileDescriptor." - " InternalDescriptorAssigner() {\n" - " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" - " com.google.protobuf.Descriptors.FileDescriptor root) {\n" - " descriptor = root;\n" - // Custom options will be handled when immutable messages' outer class is - // loaded. Here we just return null and let custom options be unknown - // fields. - " return null;\n" - " }\n" - " };\n"); - - // ----------------------------------------------------------------- - // Find out all dependencies. - vector<pair<string, string> > dependencies; - for (int i = 0; i < file_->dependency_count(); i++) { - if (ShouldIncludeDependency(file_->dependency(i))) { - string filename = file_->dependency(i)->name(); - string classname = FileJavaPackage(file_->dependency(i)) + "." + - name_resolver_->GetDescriptorClassName( - file_->dependency(i)); - dependencies.push_back(make_pair(filename, classname)); - } - } - - // ----------------------------------------------------------------- - // Invoke internalBuildGeneratedFileFrom() to build the file. - printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalBuildGeneratedFileFrom(descriptorData,\n" - " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); - - for (int i = 0; i < dependencies.size(); i++) { - const string& dependency = dependencies[i].second; - printer->Print( - " $dependency$.getDescriptor(),\n", - "dependency", dependency); - } - - printer->Print( - " }, assigner);\n"); -} - -bool SharedCodeGenerator::ShouldIncludeDependency( - const FileDescriptor* descriptor) { - return true; -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h deleted file mode 100644 index 1bb2f3d..0000000 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.h +++ /dev/null @@ -1,90 +0,0 @@ -// 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. - -// Author: xiaofeng@google.com (Feng Xiao) -// -// Generators that generate shared code between immutable API and mutable API. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ - -#include <memory> -#include <string> -#include <vector> - -#include <google/protobuf/stubs/common.h> - -namespace google { -namespace protobuf { - class FileDescriptor; // descriptor.h - namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -// A generator that generates code that are shared between immutable API -// and mutable API. Currently only descriptors are shared. -class SharedCodeGenerator { - public: - explicit SharedCodeGenerator(const FileDescriptor* file); - ~SharedCodeGenerator(); - - void Generate(GeneratorContext* generator_context, - vector<string>* file_list); - void GenerateDescriptors(io::Printer* printer); - - private: - // Returns whether the dependency should be included in the output file. - // Always returns true for opensource, but used internally at Google to help - // improve compatibility with version 1 of protocol buffers. - bool ShouldIncludeDependency(const FileDescriptor* descriptor); - - scoped_ptr<ClassNameResolver> name_resolver_; - const FileDescriptor* file_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator); -}; - - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc deleted file mode 100644 index 8889a74..0000000 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ /dev/null @@ -1,1056 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Author: jonp@google.com (Jon Perlow) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <map> -#include <string> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/compiler/java/java_name_resolver.h> -#include <google/protobuf/compiler/java/java_string_field.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -using internal::WireFormat; -using internal::WireFormatLite; - -namespace { - -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - map<string, string>* variables) { - SetCommonFieldVariables(descriptor, info, variables); - - (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; - - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_init"] = - "= " + ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["capitalized_type"] = "String"; - (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), GetType(descriptor))); - (*variables)["null_check"] = - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n"; - - // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported - // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; - (*variables)["on_changed"] = - HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - - if (SupportFieldPresence(descriptor->file())) { - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - - // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - - (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); - } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - (*variables)["is_field_present_message"] = - "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; - } - - // For repeated builders, one bit is used for whether the array is immutable. - (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - - (*variables)["get_has_field_bit_from_local"] = - GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); -} - -bool CheckUtf8(const FieldDescriptor* descriptor) { - return descriptor->file()->options().java_string_check_utf8(); -} - -} // namespace - -// =================================================================== - -ImmutableStringFieldGenerator:: -ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} - -ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} - -int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} - -// A note about how strings are handled. This code used to just store a String -// in the Message. This had two issues: -// -// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded -// strings, but rather fields that were raw bytes incorrectly marked -// as strings in the proto file. This is common because in the proto1 -// syntax, string was the way to indicate bytes and C++ engineers can -// easily make this mistake without affecting the C++ API. By converting to -// strings immediately, some java code might corrupt these byte arrays as -// it passes through a java server even if the field was never accessed by -// application code. -// -// 2. There's a performance hit to converting between bytes and strings and -// it many cases, the field is never even read by the application code. This -// avoids unnecessary conversions in the common use cases. -// -// So now, the field for String is maintained as an Object reference which can -// either store a String or a ByteString. The code uses an instanceof check -// to see which one it has and converts to the other one if needed. It remembers -// the last value requested (in a thread safe manner) as this is most likely -// the one needed next. The thread safety is such that if two threads both -// convert the field because the changes made by each thread were not visible to -// the other, they may cause a conversion to happen more times than would -// otherwise be necessary. This was deemed better than adding synchronization -// overhead. It will not cause any corruption issues or affect the behavior of -// the API. The instanceof check is also highly optimized in the JVM and we -// decided it was better to reduce the memory overhead by not having two -// separate fields but rather use dynamic type checking. -// -// For single fields, the logic for this is done inside the generated code. For -// repeated fields, the logic is done in LazyStringArrayList and -// UnmodifiableLazyStringList. -void ImmutableStringFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes();\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.lang.Object $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof java.lang.String) {\n" - " return (java.lang.String) ref;\n" - " } else {\n" - " com.google.protobuf.ByteString bs = \n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $name$_ = s;\n"); - } else { - printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $name$_ = s;\n" - " }\n"); - } - printer->Print(variables_, - " return s;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof java.lang.String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " $name$_ = b;\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.lang.Object $name$_ $default_init$;\n"); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (!(ref instanceof java.lang.String)) {\n" - " com.google.protobuf.ByteString bs =\n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $name$_ = s;\n"); - } else { - printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $name$_ = s;\n" - " }\n"); - } - printer->Print(variables_, - " return s;\n" - " } else {\n" - " return (java.lang.String) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " $name$_ = b;\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$\n"); - // The default value is not a simple literal so we want to avoid executing - // it multiple times. Instead, get the default out of the default instance. - printer->Print(variables_, - " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); - printer->Print(variables_, - " $on_changed$\n" - " return this;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$Bytes(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); - } - printer->Print(variables_, - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} - -void ImmutableStringFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - // Allow a slight breach of abstraction here in order to avoid forcing - // all string fields to Strings when copying fields from a Message. - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $set_has_field_bit_builder$\n" - " $name$_ = other.$name$_;\n" - " $on_changed$\n" - "}\n"); - } else { - printer->Print(variables_, - "if (!other.get$capitalized_name$().isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $on_changed$\n" - "}\n"); - } -} - -void ImmutableStringFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "String s = input.readStringRequireUtf8();\n" - "$set_has_field_bit_message$\n" - "$name$_ = s;\n"); - } else { - printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n" - "$set_has_field_bit_message$\n" - "$name$_ = bs;\n"); - } -} - -void ImmutableStringFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for strings. -} - -void ImmutableStringFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" - "}\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" - "}\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); -} - -void ImmutableStringFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); -} - -string ImmutableStringFieldGenerator::GetBoxedType() const { - return "java.lang.String"; -} - -// =================================================================== - -ImmutableStringOneofFieldGenerator:: -ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableStringFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); -} - -ImmutableStringOneofFieldGenerator:: -~ImmutableStringOneofFieldGenerator() {} - -void ImmutableStringOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof java.lang.String) {\n" - " return (java.lang.String) ref;\n" - " } else {\n" - " com.google.protobuf.ByteString bs = \n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = s;\n" - " }\n"); - } else { - printer->Print(variables_, - " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" - " $oneof_name$_ = s;\n" - " }\n"); - } - printer->Print(variables_, - " return s;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof java.lang.String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = b;\n" - " }\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); -} - -void ImmutableStringOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (!(ref instanceof java.lang.String)) {\n" - " com.google.protobuf.ByteString bs =\n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n" - " if ($has_oneof_case_message$) {\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $oneof_name$_ = s;\n"); - } else { - printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $oneof_name$_ = s;\n" - " }\n"); - } - printer->Print(variables_, - " }\n" - " return s;\n" - " } else {\n" - " return (java.lang.String) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = b;\n" - " }\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$Bytes(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); - } - printer->Print(variables_, - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); -} - -void ImmutableStringOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // Allow a slight breach of abstraction here in order to avoid forcing - // all string fields to Strings when copying fields from a Message. - printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = other.$oneof_name$_;\n" - "$on_changed$\n"); -} - -void ImmutableStringOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); -} - -void ImmutableStringOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "String s = input.readStringRequireUtf8();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n}\n"); - } else { - printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = bs;\n"); - } -} - -void ImmutableStringOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes($number$, get$capitalized_name$Bytes());\n" - "}\n"); -} - -void ImmutableStringOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" - "}\n"); -} - -// =================================================================== - -RepeatedImmutableStringFieldGenerator:: -RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} - -RepeatedImmutableStringFieldGenerator:: -~RepeatedImmutableStringFieldGenerator() {} - -int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { - return 0; -} - -int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$com.google.protobuf.ProtocolStringList\n" - " get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index);\n"); -} - - -void RepeatedImmutableStringFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyStringList $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" - " get$capitalized_name$List() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index) {\n" - " return $name$_.getByteString(index);\n" - "}\n"); - - if (descriptor_->options().packed() && - HasGeneratedMethods(descriptor_->containing_type())) { - printer->Print(variables_, - "private int $name$MemoizedSerializedSize = -1;\n"); - } -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // One field is the list and the bit field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - printer->Print(variables_, - "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); - - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); - - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" - " get$capitalized_name$List() {\n" - " return $name$_.getUnmodifiableView();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index) {\n" - " return $name$_.getByteString(index);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable<java.lang.String> values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " $name$_ = $empty_list$;\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$Bytes(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); - } - printer->Print(variables_, - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $empty_list$;\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - // The code below ensures that the result has an immutable list. If our - // list is immutable, we can just reuse it. If not, we make it immutable. - - printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "String s = input.readStringRequireUtf8();\n"); - } else { - printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n"); - } - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "$name$_.add(s);\n"); - } else { - printer->Print(variables_, - "$name$_.add(bs);\n"); - } -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - printer->Print(variables_, - "int length = input.readRawVarint32();\n" - "int limit = input.pushLimit(length);\n" - "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "while (input.getBytesUntilLimit() > 0) {\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " String s = input.readStringRequireUtf8();\n"); - } else { - printer->Print(variables_, - " String s = input.readString();\n"); - } - printer->Print(variables_, - " $name$.add(s);\n"); - printer->Print(variables_, - "}\n" - "input.popLimit(limit);\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - "}\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->options().packed()) { - printer->Print(variables_, - "if (get$capitalized_name$List().size() > 0) {\n" - " output.writeRawVarint32($tag$);\n" - " output.writeRawVarint32($name$MemoizedSerializedSize);\n" - "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" - "}\n"); - } else { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.getByteString(i));\n" - "}\n"); - } -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); - printer->Indent(); - - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeBytesSizeNoTag($name$_.getByteString(i));\n" - "}\n"); - - printer->Print( - "size += dataSize;\n"); - - if (descriptor_->options().packed()) { - printer->Print(variables_, - "if (!get$capitalized_name$List().isEmpty()) {\n" - " size += $tag_size$;\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeInt32SizeNoTag(dataSize);\n" - "}\n"); - } else { - printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); - } - - // cache the data size for packed fields. - if (descriptor_->options().packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutableStringFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); -} - -string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { - return "String"; -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h deleted file mode 100644 index 1ea44de..0000000 --- a/src/google/protobuf/compiler/java/java_string_field.h +++ /dev/null @@ -1,160 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Author: jonp@google.com (Jon Perlow) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ - -#include <map> -#include <string> -#include <google/protobuf/compiler/java/java_field.h> - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { - public: - explicit ImmutableStringFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableStringFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - string GetBoxedType() const; - - protected: - const FieldDescriptor* descriptor_; - map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator); -}; - -class ImmutableStringOneofFieldGenerator - : public ImmutableStringFieldGenerator { - public: - ImmutableStringOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableStringOneofFieldGenerator(); - - private: - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator); -}; - -class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { - public: - explicit RepeatedImmutableStringFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableStringFieldGenerator(); - - // implements ImmutableFieldGenerator --------------------------------------- - int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; - void GenerateInterfaceMembers(io::Printer* printer) const; - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingCodeFromPacked(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - string GetBoxedType() const; - - private: - const FieldDescriptor* descriptor_; - map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; - ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.h b/src/google/protobuf/compiler/javamicro/javamicro_file.h index 1804abf..430172a 100644 --- a/src/google/protobuf/compiler/javamicro/javamicro_file.h +++ b/src/google/protobuf/compiler/javamicro/javamicro_file.h @@ -38,7 +38,6 @@ #include <string> #include <vector> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/javamicro/javamicro_params.h> namespace google { @@ -47,6 +46,9 @@ namespace protobuf { namespace io { class Printer; // printer.h } + namespace compiler { + class OutputDirectory; // code_generator.h + } } namespace protobuf { diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index c6e8dfe..f934b05 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -73,45 +73,13 @@ void EnumGenerator::Generate(io::Printer* printer) { "// enum $classname$\n", "classname", descriptor_->name()); - const string classname = RenameJavaKeywords(descriptor_->name()); - // Start of container interface - // If generating intdefs, we use the container interface as the intdef if - // present. Otherwise, we just make an empty @interface parallel to the - // constants. - bool use_intdef = params_.generate_intdefs(); bool use_shell_class = params_.java_enum_style(); - if (use_intdef) { - // @IntDef annotation so tools can enforce correctness - // Annotations will be discarded by the compiler - printer->Print("@java.lang.annotation.Retention(" - "java.lang.annotation.RetentionPolicy.SOURCE)\n" - "@android.support.annotation.IntDef({\n"); - printer->Indent(); - for (int i = 0; i < canonical_values_.size(); i++) { - const string constant_name = - RenameJavaKeywords(canonical_values_[i]->name()); - if (use_shell_class) { - printer->Print("$classname$.$name$,\n", - "classname", classname, - "name", constant_name); - } else { - printer->Print("$name$,\n", "name", constant_name); - } - } - printer->Outdent(); - printer->Print("})\n"); - } - if (use_shell_class || use_intdef) { + if (use_shell_class) { printer->Print( - "public $at_for_intdef$interface $classname$ {\n", - "classname", classname, - "at_for_intdef", use_intdef ? "@" : ""); - if (use_shell_class) { - printer->Indent(); - } else { - printer->Print("}\n\n"); - } + "public interface $classname$ {\n", + "classname", RenameJavaKeywords(descriptor_->name())); + printer->Indent(); } // Canonical values diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 7666db3..6a18834 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -59,7 +59,6 @@ void SetEnumVariables(const Params& params, RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); if (params.use_reference_types_for_primitives() - && !params.reftypes_primitive_enums() && !descriptor->is_repeated()) { (*variables)["type"] = "java.lang.Integer"; (*variables)["default"] = "null"; @@ -76,10 +75,6 @@ void SetEnumVariables(const Params& params, internal::WireFormatLite::MakeTag(descriptor->number(), internal::WireFormat::WireTypeForFieldType(descriptor->type()))); (*variables)["message_name"] = descriptor->containing_type()->name(); - const EnumDescriptor* enum_type = descriptor->enum_type(); - (*variables)["message_type_intdef"] = "@" - + ToJavaName(params, enum_type->name(), true, - enum_type->containing_type(), enum_type->file()); } void LoadEnumValues(const Params& params, @@ -120,10 +115,8 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - if (params_.generate_intdefs()) { - printer->Print(variables_, "$message_type_intdef$\n"); - } - printer->Print(variables_, "public $type$ $name$;\n"); + printer->Print(variables_, + "public $type$ $name$;\n"); if (params_.generate_has()) { printer->Print(variables_, @@ -204,8 +197,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { - if (params_.use_reference_types_for_primitives() - && !params_.reftypes_primitive_enums()) { + if (params_.use_reference_types_for_primitives()) { printer->Print(variables_, "if (this.$name$ == null) {\n" " if (other.$name$ != null) {\n" @@ -236,8 +228,7 @@ void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const { printer->Print( "result = 31 * result + "); - if (params_.use_reference_types_for_primitives() - && !params_.reftypes_primitive_enums()) { + if (params_.use_reference_types_for_primitives()) { printer->Print(variables_, "(this.$name$ == null ? 0 : this.$name$)"); } else { @@ -262,22 +253,12 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} void AccessorEnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, "private int $name$_;\n"); - if (params_.generate_intdefs()) { - printer->Print(variables_, "$message_type_intdef$\n"); - } printer->Print(variables_, + "private int $name$_;\n" "public int get$capitalized_name$() {\n" " return $name$_;\n" "}\n" - "public $message_name$ set$capitalized_name$("); - if (params_.generate_intdefs()) { - printer->Print(variables_, - "\n" - " $message_type_intdef$ "); - } - printer->Print(variables_, - "int value) {\n" + "public $message_name$ set$capitalized_name$(int value) {\n" " $name$_ = value;\n" " $set_has$;\n" " return this;\n" @@ -515,14 +496,6 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void RepeatedEnumFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (!com.google.protobuf.nano.InternalNano.equals(\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h index 8622463..55bf635 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h @@ -106,7 +106,6 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc index 0b9d1d8..754ed55 100644 --- a/src/google/protobuf/compiler/javanano/javanano_extension.cc +++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc @@ -140,7 +140,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) const { " com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n" " com.google.protobuf.nano.Extension.$type$,\n" " $class$.class,\n" - " $tag_params$L);\n"); + " $tag_params$);\n"); } } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index e015259..61fc621 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -82,7 +82,6 @@ class FieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCodeCode(io::Printer* printer) const = 0; - virtual void GenerateFixClonedCode(io::Printer* printer) const {} protected: const Params& params_; diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h index cfcd7c6..9472721 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.h +++ b/src/google/protobuf/compiler/javanano/javanano_file.h @@ -38,7 +38,6 @@ #include <string> #include <vector> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/javanano/javanano_params.h> namespace google { @@ -47,6 +46,9 @@ namespace protobuf { namespace io { class Printer; // printer.h } + namespace compiler { + class OutputDirectory; // code_generator.h + } } namespace protobuf { diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 99ebe12..61ef2ca 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -139,25 +139,13 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_java_enum_style(option_value == "java"); } else if (option_name == "optional_field_style") { params.set_optional_field_accessors(option_value == "accessors"); - params.set_use_reference_types_for_primitives(option_value == "reftypes" - || option_value == "reftypes_compat_mode"); - params.set_reftypes_primitive_enums( - option_value == "reftypes_compat_mode"); - if (option_value == "reftypes_compat_mode") { - params.set_generate_clear(false); - } + params.set_use_reference_types_for_primitives(option_value == "reftypes"); } else if (option_name == "generate_equals") { params.set_generate_equals(option_value == "true"); } else if (option_name == "ignore_services") { params.set_ignore_services(option_value == "true"); } else if (option_name == "parcelable_messages") { params.set_parcelable_messages(option_value == "true"); - } else if (option_name == "generate_clone") { - params.set_generate_clone(option_value == "true"); - } else if (option_name == "generate_intdefs") { - params.set_generate_intdefs(option_value == "true"); - } else if (option_name == "generate_clear") { - params.set_generate_clear(option_value == "true"); } else { *error = "Ignore unknown javanano generator option: " + option_name; } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 2149418..e8326a4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -336,14 +336,14 @@ string PrimitiveTypeName(JavaType type) { case JAVATYPE_STRING : return "java.lang.String"; case JAVATYPE_BYTES : return "byte[]"; case JAVATYPE_ENUM : return "int"; - case JAVATYPE_MESSAGE: return ""; + case JAVATYPE_MESSAGE: return NULL; // No default because we want the compiler to complain if any new // JavaTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; + return NULL; } string BoxedPrimitiveTypeName(JavaType type) { @@ -356,14 +356,14 @@ string BoxedPrimitiveTypeName(JavaType type) { case JAVATYPE_STRING : return "java.lang.String"; case JAVATYPE_BYTES : return "byte[]"; case JAVATYPE_ENUM : return "java.lang.Integer"; - case JAVATYPE_MESSAGE: return ""; + case JAVATYPE_MESSAGE: return NULL; // No default because we want the compiler to complain if any new // JavaTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; + return NULL; } string EmptyArrayName(const Params& params, const FieldDescriptor* field) { @@ -392,10 +392,6 @@ string DefaultValue(const Params& params, const FieldDescriptor* field) { } if (params.use_reference_types_for_primitives()) { - if (params.reftypes_primitive_enums() - && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return "Integer.MIN_VALUE"; - } return "null"; } diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 4026031..7a2b4a0 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -134,23 +134,18 @@ void MessageGenerator::Generate(io::Printer* printer) { } if (params_.store_unknown_fields() && params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>", + " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n", "classname", descriptor_->name()); } else if (params_.store_unknown_fields()) { printer->Print( - " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", + " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n", "classname", descriptor_->name()); } else if (params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableMessageNano"); + " com.google.protobuf.nano.android.ParcelableMessageNano {\n"); } else { printer->Print( - " com.google.protobuf.nano.MessageNano"); - } - if (params_.generate_clone()) { - printer->Print(" implements java.lang.Cloneable {\n"); - } else { - printer->Print(" {\n"); + " com.google.protobuf.nano.MessageNano {\n"); } printer->Indent(); @@ -250,34 +245,22 @@ void MessageGenerator::Generate(io::Printer* printer) { " _classInitialized = true;\n" " }\n" " }\n" - " }\n"); - if (params_.generate_clear()) { - printer->Print(" clear();\n"); - } - printer->Print("}\n"); + " }\n" + " clear();\n" + "}\n"); } else { printer->Print( "\n" - "public $classname$() {\n", + "public $classname$() {\n" + " clear();\n" + "}\n", "classname", descriptor_->name()); - if (params_.generate_clear()) { - printer->Print(" clear();\n"); - } else { - printer->Indent(); - GenerateFieldInitializers(printer); - printer->Outdent(); - } - printer->Print("}\n"); } // Other methods in this class GenerateClear(printer); - if (params_.generate_clone()) { - GenerateClone(printer); - } - if (params_.generate_equals()) { GenerateEquals(printer); GenerateHashCode(printer); @@ -457,24 +440,12 @@ void MessageGenerator::GenerateSerializeOneField( } void MessageGenerator::GenerateClear(io::Printer* printer) { - if (!params_.generate_clear()) { - return; - } printer->Print( "\n" "public $classname$ clear() {\n", "classname", descriptor_->name()); printer->Indent(); - GenerateFieldInitializers(printer); - - printer->Outdent(); - printer->Print( - " return this;\n" - "}\n"); -} - -void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { // Clear bit fields. int totalInts = (field_generators_.total_bits() + 31) / 32; for (int i = 0; i < totalInts; i++) { @@ -492,34 +463,12 @@ void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print("unknownFieldData = null;\n"); } - printer->Print("cachedSize = -1;\n"); -} - -void MessageGenerator::GenerateClone(io::Printer* printer) { - printer->Print( - "@Override\n" - "public $classname$ clone() {\n", - "classname", descriptor_->name()); - printer->Indent(); - - printer->Print( - "$classname$ cloned;\n" - "try {\n" - " cloned = ($classname$) super.clone();\n" - "} catch (java.lang.CloneNotSupportedException e) {\n" - " throw new java.lang.AssertionError(e);\n" - "}\n", - "classname", descriptor_->name()); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); - } printer->Outdent(); printer->Print( - " return cloned;\n" - "}\n" - "\n"); + " cachedSize = -1;\n" + " return this;\n" + "}\n"); } void MessageGenerator::GenerateEquals(io::Printer* printer) { @@ -552,11 +501,7 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" - " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" - "} else {\n" - " return unknownFieldData.equals(other.unknownFieldData);\n" - "}"); + "return unknownFieldDataEquals(other);\n"); } else { printer->Print( "return true;\n"); @@ -578,7 +523,6 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) { printer->Indent(); printer->Print("int result = 17;\n"); - printer->Print("result = 31 * result + getClass().getName().hashCode();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateHashCodeCode(printer); @@ -586,9 +530,7 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "result = 31 * result + \n" - " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" - " unknownFieldData.hashCode());\n"); + "result = 31 * result + unknownFieldDataHashCode();\n"); } printer->Print("return result;\n"); diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h index 1bb6557..f87f84f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.h +++ b/src/google/protobuf/compiler/javanano/javanano_message.h @@ -77,10 +77,8 @@ class MessageGenerator { const FieldDescriptor* field); void GenerateClear(io::Printer* printer); - void GenerateFieldInitializers(io::Printer* printer); void GenerateEquals(io::Printer* printer); void GenerateHashCode(io::Printer* printer); - void GenerateClone(io::Printer* printer); const Params& params_; const Descriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 4752644..a46081d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -127,14 +127,6 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void MessageFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - -void MessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (this.$name$ == null) { \n" @@ -246,19 +238,6 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void RepeatedMessageFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = new $type$[this.$name$.length];\n" - " for (int i = 0; i < this.$name$.length; i++) {\n" - " if (this.$name$[i] != null) {\n" - " cloned.$name$[i] = this.$name$[i].clone();\n" - " }\n" - " }\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (!com.google.protobuf.nano.InternalNano.equals(\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 1edff25..e94a37b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -58,7 +58,6 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; @@ -81,7 +80,6 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index e3b4bb9..d0626a2 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -64,10 +64,6 @@ class Params { bool generate_equals_; bool ignore_services_; bool parcelable_messages_; - bool reftypes_primitive_enums_; - bool generate_clear_; - bool generate_clone_; - bool generate_intdefs_; public: Params(const string & base_name) : @@ -81,11 +77,7 @@ class Params { use_reference_types_for_primitives_(false), generate_equals_(false), ignore_services_(false), - parcelable_messages_(false), - reftypes_primitive_enums_(false), - generate_clear_(true), - generate_clone_(false), - generate_intdefs_(false) { + parcelable_messages_(false) { } const string& base_name() const { @@ -221,34 +213,6 @@ class Params { bool parcelable_messages() const { return parcelable_messages_; } - - void set_reftypes_primitive_enums(bool value) { - reftypes_primitive_enums_ = value; - } - bool reftypes_primitive_enums() const { - return reftypes_primitive_enums_; - } - - void set_generate_clear(bool value) { - generate_clear_ = value; - } - bool generate_clear() const { - return generate_clear_; - } - - void set_generate_clone(bool value) { - generate_clone_ = value; - } - bool generate_clone() const { - return generate_clone_; - } - - void set_generate_intdefs(bool value) { - generate_intdefs_ = value; - } - bool generate_intdefs() const { - return generate_intdefs_; - } }; } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index bda52c6..a3bc3a8 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -385,14 +385,6 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } } -void RepeatedPrimitiveFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - void PrimitiveFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { // We define equality as serialized form equality. If generate_has(), diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h index 5ace0de..c04a19b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h @@ -108,7 +108,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 1fc60ce..8bd71b1 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) { // Proto2 C++ google::protobuf::compiler::cpp::CppGenerator cpp_generator; - cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator, + cli.RegisterGenerator("--cpp_out", &cpp_generator, "Generate C++ header and source."); // Proto2 Java diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 916b0cc..83d5a4e 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,32 +32,19 @@ #include <google/protobuf/compiler/mock_code_generator.h> -#include <memory> - #include <google/protobuf/testing/file.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> #include <gtest/gtest.h> -#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/stl_util-inl.h> namespace google { namespace protobuf { namespace compiler { -// Returns the list of the names of files in all_files in the form of a -// comma-separated string. -string CommaSeparatedList(const vector<const FileDescriptor*> all_files) { - vector<string> names; - for (int i = 0; i < all_files.size(); i++) { - names.push_back(all_files[i]->name()); - } - return Join(names, ","); -} - static const char* kFirstInsertionPointName = "first_mock_insertion_point"; static const char* kSecondInsertionPointName = "second_mock_insertion_point"; static const char* kFirstInsertionPoint = @@ -76,14 +63,13 @@ void MockCodeGenerator::ExpectGenerated( const string& insertions, const string& file, const string& first_message_name, - const string& first_parsed_file_name, const string& output_directory) { string content; - GOOGLE_CHECK_OK( - File::GetContents(output_directory + "/" + GetOutputFileName(name, file), - &content, true)); + ASSERT_TRUE(File::ReadFileToString( + output_directory + "/" + GetOutputFileName(name, file), &content)); - vector<string> lines = Split(content, "\n", true); + vector<string> lines; + SplitStringUsing(content, "\n", &lines); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); @@ -97,9 +83,8 @@ void MockCodeGenerator::ExpectGenerated( SplitStringUsing(insertions, ",", &insertion_list); } - EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2); - EXPECT_EQ(GetOutputFileContent(name, parameter, file, - first_parsed_file_name, first_message_name), + ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2); + EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name), lines[0]); EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); @@ -107,12 +92,12 @@ void MockCodeGenerator::ExpectGenerated( for (int i = 0; i < insertion_list.size(); i++) { EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", - file, file, first_message_name), + file, first_message_name), lines[1 + i]); // Second insertion point is indented, so the inserted text should // automatically be indented too. EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert", - file, file, first_message_name), + file, first_message_name), lines[2 + insertion_list.size() + i]); } } @@ -120,7 +105,7 @@ void MockCodeGenerator::ExpectGenerated( bool MockCodeGenerator::Generate( const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { for (int i = 0; i < file->message_type_count(); i++) { if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { @@ -135,15 +120,6 @@ bool MockCodeGenerator::Generate( } else if (command == "Abort") { cerr << "Saw message type MockCodeGenerator_Abort." << endl; abort(); - } else if (command == "HasSourceCodeInfo") { - FileDescriptorProto file_descriptor_proto; - file->CopySourceCodeInfoTo(&file_descriptor_proto); - bool has_source_code_info = - file_descriptor_proto.has_source_code_info() && - file_descriptor_proto.source_code_info().location_size() > 0; - cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " - << has_source_code_info << "." << endl; - abort(); } else { GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command; } @@ -157,11 +133,12 @@ bool MockCodeGenerator::Generate( for (int i = 0; i < insert_into.size(); i++) { { - scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert( - GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); + scoped_ptr<io::ZeroCopyOutputStream> output( + output_directory->OpenForInsert( + GetOutputFileName(insert_into[i], file), + kFirstInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "first_insert", - file, context)); + printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -170,11 +147,11 @@ bool MockCodeGenerator::Generate( { scoped_ptr<io::ZeroCopyOutputStream> output( - context->OpenForInsert(GetOutputFileName(insert_into[i], file), - kSecondInsertionPointName)); + output_directory->OpenForInsert( + GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "second_insert", - file, context)); + printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -183,11 +160,10 @@ bool MockCodeGenerator::Generate( } } else { scoped_ptr<io::ZeroCopyOutputStream> output( - context->Open(GetOutputFileName(name_, file))); + output_directory->Open(GetOutputFileName(name_, file))); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, parameter, - file, context)); + printer.PrintRaw(GetOutputFileContent(name_, parameter, file)); printer.PrintRaw(kFirstInsertionPoint); printer.PrintRaw(kSecondInsertionPoint); @@ -210,16 +186,11 @@ string MockCodeGenerator::GetOutputFileName(const string& generator_name, return file + ".MockCodeGenerator." + generator_name; } -string MockCodeGenerator::GetOutputFileContent( - const string& generator_name, - const string& parameter, - const FileDescriptor* file, - GeneratorContext *context) { - vector<const FileDescriptor*> all_files; - context->ListParsedFiles(&all_files); +string MockCodeGenerator::GetOutputFileContent(const string& generator_name, + const string& parameter, + const FileDescriptor* file) { return GetOutputFileContent( generator_name, parameter, file->name(), - CommaSeparatedList(all_files), file->message_type_count() > 0 ? file->message_type(0)->name() : "(none)"); } @@ -228,11 +199,9 @@ string MockCodeGenerator::GetOutputFileContent( const string& generator_name, const string& parameter, const string& file, - const string& parsed_file_list, const string& first_message_name) { - return strings::Substitute("$0: $1, $2, $3, $4\n", - generator_name, parameter, file, - first_message_name, parsed_file_list); + return strings::Substitute("$0: $1, $2, $3\n", + generator_name, parameter, file, first_message_name); } } // namespace compiler diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index 8c8348d..01d69dd 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -59,10 +59,6 @@ namespace compiler { // MockCodeGenerator_Exit." to stderr and then calls exit(123). // MockCodeGenerator_Abort: Generate() prints "Saw message type // MockCodeGenerator_Abort." to stderr and then calls abort(). -// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after -// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to -// stderr, where FOO is "1" if the supplied FileDescriptorProto has source -// code info, and "0" otherwise. class MockCodeGenerator : public CodeGenerator { public: MockCodeGenerator(const string& name); @@ -73,14 +69,11 @@ class MockCodeGenerator : public CodeGenerator { // // |insertions| is a comma-separated list of names of MockCodeGenerators which // should have inserted lines into this file. - // |parsed_file_list| is a comma-separated list of names of the files - // that are being compiled together in this run. static void ExpectGenerated(const string& name, const string& parameter, const string& insertions, const string& file, const string& first_message_name, - const string& parsed_file_list, const string& output_directory); // Get the name of the file which would be written by the given generator. @@ -93,7 +86,7 @@ class MockCodeGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const; private: @@ -101,12 +94,10 @@ class MockCodeGenerator : public CodeGenerator { static string GetOutputFileContent(const string& generator_name, const string& parameter, - const FileDescriptor* file, - GeneratorContext *context); + const FileDescriptor* file); static string GetOutputFileContent(const string& generator_name, const string& parameter, const string& file, - const string& parsed_file_list, const string& first_message_name); }; diff --git a/src/google/protobuf/compiler/package_info.h b/src/google/protobuf/compiler/package_info.h index fb6b473..b897126 100644 --- a/src/google/protobuf/compiler/package_info.h +++ b/src/google/protobuf/compiler/package_info.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 474a8f8..758f70d 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -46,7 +46,7 @@ #include <google/protobuf/io/tokenizer.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/map-util.h> namespace google { namespace protobuf { @@ -174,20 +174,6 @@ bool Parser::ConsumeInteger(int* output, const char* error) { } } -bool Parser::ConsumeSignedInteger(int* output, const char* error) { - bool is_negative = false; - uint64 max_value = kint32max; - if (TryConsume("-")) { - is_negative = true; - max_value += 1; - } - uint64 value = 0; - DO(ConsumeInteger64(max_value, &value, error)); - if (is_negative) value *= -1; - *output = value; - return true; -} - bool Parser::ConsumeInteger64(uint64 max_value, uint64* output, const char* error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { @@ -251,35 +237,6 @@ bool Parser::ConsumeString(string* output, const char* error) { } } -bool Parser::TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { - if (LookingAt(text)) { - string leading, trailing; - input_->NextWithComments(&trailing, NULL, &leading); - - // Save the leading comments for next time, and recall the leading comments - // from last time. - leading.swap(upcoming_doc_comments_); - - if (location != NULL) { - location->AttachComments(&leading, &trailing); - } - return true; - } else { - return false; - } -} - -bool Parser::ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { - if (TryConsumeEndOfDeclaration(text, location)) { - return true; - } else { - AddError("Expected \"" + string(text) + "\"."); - return false; - } -} - // ------------------------------------------------------------------- void Parser::AddError(int line, int column, const string& error) { @@ -293,87 +250,20 @@ void Parser::AddError(const string& error) { AddError(input_->current().line, input_->current().column, error); } -// ------------------------------------------------------------------- - -Parser::LocationRecorder::LocationRecorder(Parser* parser) - : parser_(parser), - location_(parser_->source_code_info_->add_location()) { - location_->add_span(parser_->input_->current().line); - location_->add_span(parser_->input_->current().column); -} - -Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) { - Init(parent); -} - -Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, - int path1) { - Init(parent); - AddPath(path1); -} - -Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, - int path1, int path2) { - Init(parent); - AddPath(path1); - AddPath(path2); -} - -void Parser::LocationRecorder::Init(const LocationRecorder& parent) { - parser_ = parent.parser_; - location_ = parser_->source_code_info_->add_location(); - location_->mutable_path()->CopyFrom(parent.location_->path()); - - location_->add_span(parser_->input_->current().line); - location_->add_span(parser_->input_->current().column); -} - -Parser::LocationRecorder::~LocationRecorder() { - if (location_->span_size() <= 2) { - EndAt(parser_->input_->previous()); - } -} - -void Parser::LocationRecorder::AddPath(int path_component) { - location_->add_path(path_component); -} - -void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { - location_->set_span(0, token.line); - location_->set_span(1, token.column); -} - -void Parser::LocationRecorder::StartAt(const LocationRecorder& other) { - location_->set_span(0, other.location_->span(0)); - location_->set_span(1, other.location_->span(1)); -} - -void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { - if (token.line != location_->span(0)) { - location_->add_span(token.line); +void Parser::RecordLocation( + const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int line, int column) { + if (source_location_table_ != NULL) { + source_location_table_->Add(descriptor, location, line, column); } - location_->add_span(token.end_column); } -void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, +void Parser::RecordLocation( + const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location) { - if (parser_->source_location_table_ != NULL) { - parser_->source_location_table_->Add( - descriptor, location, location_->span(0), location_->span(1)); - } -} - -void Parser::LocationRecorder::AttachComments( - string* leading, string* trailing) const { - GOOGLE_CHECK(!location_->has_leading_comments()); - GOOGLE_CHECK(!location_->has_trailing_comments()); - - if (!leading->empty()) { - location_->mutable_leading_comments()->swap(*leading); - } - if (!trailing->empty()) { - location_->mutable_trailing_comments()->swap(*trailing); - } + RecordLocation(descriptor, location, + input_->current().line, input_->current().column); } // ------------------------------------------------------------------- @@ -383,7 +273,7 @@ void Parser::SkipStatement() { if (AtEnd()) { return; } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { - if (TryConsumeEndOfDeclaration(";", NULL)) { + if (TryConsume(";")) { return; } else if (TryConsume("{")) { SkipRestOfBlock(); @@ -401,7 +291,7 @@ void Parser::SkipRestOfBlock() { if (AtEnd()) { return; } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { - if (TryConsumeEndOfDeclaration("}", NULL)) { + if (TryConsume("}")) { return; } else if (TryConsume("{")) { SkipRestOfBlock(); @@ -418,51 +308,38 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { had_errors_ = false; syntax_identifier_.clear(); - // Note that |file| could be NULL at this point if - // stop_after_syntax_identifier_ is true. So, we conservatively allocate - // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto - // later on. - SourceCodeInfo source_code_info; - source_code_info_ = &source_code_info; - if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + input_->Next(); } - { - LocationRecorder root_location(this); - - if (require_syntax_identifier_ || LookingAt("syntax")) { - if (!ParseSyntaxIdentifier()) { - // Don't attempt to parse the file if we didn't recognize the syntax - // identifier. - return false; - } - } else if (!stop_after_syntax_identifier_) { - syntax_identifier_ = "proto2"; + if (require_syntax_identifier_ || LookingAt("syntax")) { + if (!ParseSyntaxIdentifier()) { + // Don't attempt to parse the file if we didn't recognize the syntax + // identifier. + return false; } + } else if (!stop_after_syntax_identifier_) { + syntax_identifier_ = "proto2"; + } - if (stop_after_syntax_identifier_) return !had_errors_; + if (stop_after_syntax_identifier_) return !had_errors_; - // Repeatedly parse statements until we reach the end of the file. - while (!AtEnd()) { - if (!ParseTopLevelStatement(file, root_location)) { - // This statement failed to parse. Skip it, but keep looping to parse - // other statements. - SkipStatement(); + // Repeatedly parse statements until we reach the end of the file. + while (!AtEnd()) { + if (!ParseTopLevelStatement(file)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); - if (LookingAt("}")) { - AddError("Unmatched \"}\"."); - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); - } + if (LookingAt("}")) { + AddError("Unmatched \"}\"."); + input_->Next(); } } } input_ = NULL; - source_code_info_ = NULL; - source_code_info.Swap(file->mutable_source_code_info()); return !had_errors_; } @@ -472,7 +349,7 @@ bool Parser::ParseSyntaxIdentifier() { io::Tokenizer::Token syntax_token = input_->current(); string syntax; DO(ConsumeString(&syntax, "Expected syntax identifier.")); - DO(ConsumeEndOfDeclaration(";", NULL)); + DO(Consume(";")); syntax_identifier_ = syntax; @@ -486,43 +363,25 @@ bool Parser::ParseSyntaxIdentifier() { return true; } -bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, - const LocationRecorder& root_location) { - if (TryConsumeEndOfDeclaration(";", NULL)) { +bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) { + if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("message")) { - LocationRecorder location(root_location, - FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); - return ParseMessageDefinition(file->add_message_type(), location, file); + return ParseMessageDefinition(file->add_message_type()); } else if (LookingAt("enum")) { - LocationRecorder location(root_location, - FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); - return ParseEnumDefinition(file->add_enum_type(), location, file); + return ParseEnumDefinition(file->add_enum_type()); } else if (LookingAt("service")) { - LocationRecorder location(root_location, - FileDescriptorProto::kServiceFieldNumber, file->service_size()); - return ParseServiceDefinition(file->add_service(), location, file); + return ParseServiceDefinition(file->add_service()); } else if (LookingAt("extend")) { - LocationRecorder location(root_location, - FileDescriptorProto::kExtensionFieldNumber); return ParseExtend(file->mutable_extension(), - file->mutable_message_type(), - root_location, - FileDescriptorProto::kMessageTypeFieldNumber, - location, file); + file->mutable_message_type()); } else if (LookingAt("import")) { - return ParseImport(file->mutable_dependency(), - file->mutable_public_dependency(), - file->mutable_weak_dependency(), - root_location, file); + return ParseImport(file->add_dependency()); } else if (LookingAt("package")) { - return ParsePackage(file, root_location, file); + return ParsePackage(file); } else if (LookingAt("option")) { - LocationRecorder location(root_location, - FileDescriptorProto::kOptionsFieldNumber); - return ParseOption(file->mutable_options(), location, file, - OPTION_STATEMENT); + return ParseOption(file->mutable_options()); } else { AddError("Expected top-level statement (e.g. \"message\")."); return false; @@ -532,234 +391,93 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, // ------------------------------------------------------------------- // Messages -bool Parser::ParseMessageDefinition( - DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseMessageDefinition(DescriptorProto* message) { DO(Consume("message")); - { - LocationRecorder location(message_location, - DescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - message, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); - } - DO(ParseMessageBlock(message, message_location, containing_file)); + RecordLocation(message, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); + DO(ParseMessageBlock(message)); return true; } -namespace { - -const int kMaxExtensionRangeSentinel = -1; - -bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { - const MessageOptions& options = message.options(); - for (int i = 0; i < options.uninterpreted_option_size(); ++i) { - const UninterpretedOption& uninterpreted = options.uninterpreted_option(i); - if (uninterpreted.name_size() == 1 && - uninterpreted.name(0).name_part() == "message_set_wire_format" && - uninterpreted.identifier_value() == "true") { - return true; - } - } - return false; -} - -// Modifies any extension ranges that specified 'max' as the end of the -// extension range, and sets them to the type-specific maximum. The actual max -// tag number can only be determined after all options have been parsed. -void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { - const bool is_message_set = IsMessageSetWireFormatMessage(*message); - const int max_extension_number = is_message_set ? - kint32max : - FieldDescriptor::kMaxNumber + 1; - for (int i = 0; i < message->extension_range_size(); ++i) { - if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) { - message->mutable_extension_range(i)->set_end(max_extension_number); - } - } -} - -} // namespace - -bool Parser::ParseMessageBlock(DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file) { - DO(ConsumeEndOfDeclaration("{", &message_location)); +bool Parser::ParseMessageBlock(DescriptorProto* message) { + DO(Consume("{")); - while (!TryConsumeEndOfDeclaration("}", NULL)) { + while (!TryConsume("}")) { if (AtEnd()) { AddError("Reached end of input in message definition (missing '}')."); return false; } - if (!ParseMessageStatement(message, message_location, containing_file)) { + if (!ParseMessageStatement(message)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); } } - if (message->extension_range_size() > 0) { - AdjustExtensionRangesWithMaxEndNumber(message); - } return true; } -bool Parser::ParseMessageStatement(DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file) { - if (TryConsumeEndOfDeclaration(";", NULL)) { +bool Parser::ParseMessageStatement(DescriptorProto* message) { + if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("message")) { - LocationRecorder location(message_location, - DescriptorProto::kNestedTypeFieldNumber, - message->nested_type_size()); - return ParseMessageDefinition(message->add_nested_type(), location, - containing_file); + return ParseMessageDefinition(message->add_nested_type()); } else if (LookingAt("enum")) { - LocationRecorder location(message_location, - DescriptorProto::kEnumTypeFieldNumber, - message->enum_type_size()); - return ParseEnumDefinition(message->add_enum_type(), location, - containing_file); + return ParseEnumDefinition(message->add_enum_type()); } else if (LookingAt("extensions")) { - LocationRecorder location(message_location, - DescriptorProto::kExtensionRangeFieldNumber); - return ParseExtensions(message, location, containing_file); + return ParseExtensions(message); } else if (LookingAt("extend")) { - LocationRecorder location(message_location, - DescriptorProto::kExtensionFieldNumber); return ParseExtend(message->mutable_extension(), - message->mutable_nested_type(), - message_location, - DescriptorProto::kNestedTypeFieldNumber, - location, containing_file); + message->mutable_nested_type()); } else if (LookingAt("option")) { - LocationRecorder location(message_location, - DescriptorProto::kOptionsFieldNumber); - return ParseOption(message->mutable_options(), location, - containing_file, OPTION_STATEMENT); - } else if (LookingAt("oneof")) { - int oneof_index = message->oneof_decl_size(); - LocationRecorder oneof_location(message_location, - DescriptorProto::kOneofDeclFieldNumber, - oneof_index); - - return ParseOneof(message->add_oneof_decl(), message, - oneof_index, oneof_location, message_location, - containing_file); + return ParseOption(message->mutable_options()); } else { - LocationRecorder location(message_location, - DescriptorProto::kFieldFieldNumber, - message->field_size()); return ParseMessageField(message->add_field(), - message->mutable_nested_type(), - message_location, - DescriptorProto::kNestedTypeFieldNumber, - location, - containing_file); + message->mutable_nested_type()); } } bool Parser::ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file) { - { - LocationRecorder location(field_location, - FieldDescriptorProto::kLabelFieldNumber); - FieldDescriptorProto::Label label; - DO(ParseLabel(&label, containing_file)); - field->set_label(label); - } - - return ParseMessageFieldNoLabel(field, messages, parent_location, - location_field_number_for_nested_type, - field_location, - containing_file); -} - -bool Parser::ParseMessageFieldNoLabel( - FieldDescriptorProto* field, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file) { - // Parse type. - { - LocationRecorder location(field_location); // add path later - location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); - - FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; - string type_name; - DO(ParseType(&type, &type_name)); - if (type_name.empty()) { - location.AddPath(FieldDescriptorProto::kTypeFieldNumber); - field->set_type(type); - } else { - location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber); - field->set_type_name(type_name); - } + RepeatedPtrField<DescriptorProto>* messages) { + // Parse label and type. + FieldDescriptorProto::Label label; + DO(ParseLabel(&label)); + field->set_label(label); + + RecordLocation(field, DescriptorPool::ErrorCollector::TYPE); + FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; + string type_name; + DO(ParseType(&type, &type_name)); + if (type_name.empty()) { + field->set_type(type); + } else { + field->set_type_name(type_name); } // Parse name and '='. + RecordLocation(field, DescriptorPool::ErrorCollector::NAME); io::Tokenizer::Token name_token = input_->current(); - { - LocationRecorder location(field_location, - FieldDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); - } + DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); DO(Consume("=", "Missing field number.")); // Parse field number. - { - LocationRecorder location(field_location, - FieldDescriptorProto::kNumberFieldNumber); - location.RecordLegacyLocation( - field, DescriptorPool::ErrorCollector::NUMBER); - int number; - DO(ConsumeInteger(&number, "Expected field number.")); - field->set_number(number); - } + RecordLocation(field, DescriptorPool::ErrorCollector::NUMBER); + int number; + DO(ConsumeInteger(&number, "Expected field number.")); + field->set_number(number); // Parse options. - DO(ParseFieldOptions(field, field_location, containing_file)); + DO(ParseFieldOptions(field)); // Deal with groups. - if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { - // Awkward: Since a group declares both a message type and a field, we - // have to create overlapping locations. - LocationRecorder group_location(parent_location); - group_location.StartAt(field_location); - group_location.AddPath(location_field_number_for_nested_type); - group_location.AddPath(messages->size()); - + if (type_name.empty() && type == FieldDescriptorProto::TYPE_GROUP) { DescriptorProto* group = messages->Add(); group->set_name(field->name()); - // Record name location to match the field name's location. - { - LocationRecorder location(group_location, - DescriptorProto::kNameFieldNumber); - location.StartAt(name_token); - location.EndAt(name_token); - location.RecordLegacyLocation( - group, DescriptorPool::ErrorCollector::NAME); - } - - // The field's type_name also comes from the name. Confusing! - { - LocationRecorder location(field_location, - FieldDescriptorProto::kTypeNameFieldNumber); - location.StartAt(name_token); - location.EndAt(name_token); - } + RecordLocation(group, DescriptorPool::ErrorCollector::NAME, + name_token.line, name_token.column); // As a hack for backwards-compatibility, we force the group name to start // with a capital letter and lower-case the field name. New code should @@ -772,37 +490,27 @@ bool Parser::ParseMessageFieldNoLabel( field->set_type_name(group->name()); if (LookingAt("{")) { - DO(ParseMessageBlock(group, group_location, containing_file)); + DO(ParseMessageBlock(group)); } else { AddError("Missing group body."); return false; } } else { - DO(ConsumeEndOfDeclaration(";", &field_location)); + DO(Consume(";")); } return true; } -bool Parser::ParseFieldOptions(FieldDescriptorProto* field, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file) { - if (!LookingAt("[")) return true; - - LocationRecorder location(field_location, - FieldDescriptorProto::kOptionsFieldNumber); - - DO(Consume("[")); +bool Parser::ParseFieldOptions(FieldDescriptorProto* field) { + if (!TryConsume("[")) return true; // Parse field options. do { if (LookingAt("default")) { - // We intentionally pass field_location rather than location here, since - // the default value is not actually an option. - DO(ParseDefaultAssignment(field, field_location, containing_file)); + DO(ParseDefaultAssignment(field)); } else { - DO(ParseOption(field->mutable_options(), location, - containing_file, OPTION_ASSIGNMENT)); + DO(ParseOptionAssignment(field->mutable_options())); } } while (TryConsume(",")); @@ -810,10 +518,7 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field, return true; } -bool Parser::ParseDefaultAssignment( - FieldDescriptorProto* field, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { if (field->has_default_value()) { AddError("Already set option \"default\"."); field->clear_default_value(); @@ -822,24 +527,13 @@ bool Parser::ParseDefaultAssignment( DO(Consume("default")); DO(Consume("=")); - LocationRecorder location(field_location, - FieldDescriptorProto::kDefaultValueFieldNumber); - location.RecordLegacyLocation( - field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); + RecordLocation(field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); string* default_value = field->mutable_default_value(); if (!field->has_type()) { // The field has a type name, but we don't know if it is a message or an - // enum yet. (If it were a primitive type, |field| would have a type set - // already.) In this case, simply take the current string as the default - // value; we will catch the error later if it is not a valid enum value. - // (N.B. that we do not check whether the current token is an identifier: - // doing so throws strange errors when the user mistypes a primitive - // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default - // = 42]". In such a case the fundamental error is really that "int" is not - // a type, not that "42" is not an identifier. See b/12533582.) - *default_value = input_->current().text; - input_->Next(); + // enum yet. Assume an enum for now. + DO(ConsumeIdentifier(default_value, "Expected identifier.")); return true; } @@ -865,8 +559,7 @@ bool Parser::ParseDefaultAssignment( } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, - "Expected integer for field default value.")); + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -888,8 +581,7 @@ bool Parser::ParseDefaultAssignment( } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, - "Expected integer for field default value.")); + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -921,11 +613,7 @@ bool Parser::ParseDefaultAssignment( break; case FieldDescriptorProto::TYPE_STRING: - // Note: When file opton java_string_check_utf8 is true, if a - // non-string representation (eg byte[]) is later supported, it must - // be checked for UTF-8-ness. - DO(ConsumeString(default_value, "Expected string for field default " - "value.")); + DO(ConsumeString(default_value, "Expected string.")); break; case FieldDescriptorProto::TYPE_BYTES: @@ -934,8 +622,7 @@ bool Parser::ParseDefaultAssignment( break; case FieldDescriptorProto::TYPE_ENUM: - DO(ConsumeIdentifier(default_value, "Expected enum identifier for field " - "default value.")); + DO(ConsumeIdentifier(default_value, "Expected identifier.")); break; case FieldDescriptorProto::TYPE_MESSAGE: @@ -947,36 +634,26 @@ bool Parser::ParseDefaultAssignment( return true; } -bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, - const LocationRecorder& part_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) { UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); string identifier; // We parse identifiers into this string. if (LookingAt("(")) { // This is an extension. DO(Consume("(")); - - { - LocationRecorder location( - part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); - // An extension name consists of dot-separated identifiers, and may begin - // with a dot. - if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); - } - while (LookingAt(".")) { - DO(Consume(".")); - name->mutable_name_part()->append("."); - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); - } + // An extension name consists of dot-separated identifiers, and may begin + // with a dot. + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } + while (LookingAt(".")) { + DO(Consume(".")); + name->mutable_name_part()->append("."); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); } - DO(Consume(")")); name->set_is_extension(true); } else { // This is a regular field. - LocationRecorder location( - part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); DO(ConsumeIdentifier(&identifier, "Expected identifier.")); name->mutable_name_part()->append(identifier); name->set_is_extension(false); @@ -984,214 +661,116 @@ bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, return true; } -bool Parser::ParseUninterpretedBlock(string* value) { - // Note that enclosing braces are not added to *value. - // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting - // an expression, not a block of statements. - DO(Consume("{")); - int brace_depth = 1; - while (!AtEnd()) { - if (LookingAt("{")) { - brace_depth++; - } else if (LookingAt("}")) { - brace_depth--; - if (brace_depth == 0) { - input_->Next(); - return true; - } - } - // TODO(sanjay): Interpret line/column numbers to preserve formatting - if (!value->empty()) value->push_back(' '); - value->append(input_->current().text); - input_->Next(); - } - AddError("Unexpected end of stream while parsing aggregate value."); - return false; -} - // We don't interpret the option here. Instead we store it in an // UninterpretedOption, to be interpreted later. -bool Parser::ParseOption(Message* options, - const LocationRecorder& options_location, - const FileDescriptorProto* containing_file, - OptionStyle style) { +bool Parser::ParseOptionAssignment(Message* options) { // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> FindFieldByName("uninterpreted_option"); GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; - const Reflection* reflection = options->GetReflection(); - - LocationRecorder location( - options_location, uninterpreted_option_field->number(), - reflection->FieldSize(*options, uninterpreted_option_field)); - - if (style == OPTION_STATEMENT) { - DO(Consume("option")); - } - UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>( options->GetReflection()->AddMessage(options, uninterpreted_option_field)); // Parse dot-separated name. - { - LocationRecorder name_location(location, - UninterpretedOption::kNameFieldNumber); - name_location.RecordLegacyLocation( - uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); - - { - LocationRecorder part_location(name_location, - uninterpreted_option->name_size()); - DO(ParseOptionNamePart(uninterpreted_option, part_location, - containing_file)); - } + RecordLocation(uninterpreted_option, + DescriptorPool::ErrorCollector::OPTION_NAME); - while (LookingAt(".")) { - DO(Consume(".")); - LocationRecorder part_location(name_location, - uninterpreted_option->name_size()); - DO(ParseOptionNamePart(uninterpreted_option, part_location, - containing_file)); - } + DO(ParseOptionNamePart(uninterpreted_option)); + + while (LookingAt(".")) { + DO(Consume(".")); + DO(ParseOptionNamePart(uninterpreted_option)); } DO(Consume("=")); - { - LocationRecorder value_location(location); - value_location.RecordLegacyLocation( - uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); + RecordLocation(uninterpreted_option, + DescriptorPool::ErrorCollector::OPTION_VALUE); - // All values are a single token, except for negative numbers, which consist - // of a single '-' symbol, followed by a positive number. - bool is_negative = TryConsume("-"); + // All values are a single token, except for negative numbers, which consist + // of a single '-' symbol, followed by a positive number. + bool is_negative = TryConsume("-"); - switch (input_->current().type) { - case io::Tokenizer::TYPE_START: - GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; - return false; + switch (input_->current().type) { + case io::Tokenizer::TYPE_START: + GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; + return false; - case io::Tokenizer::TYPE_END: - AddError("Unexpected end of stream while parsing option value."); - return false; + case io::Tokenizer::TYPE_END: + AddError("Unexpected end of stream while parsing option value."); + return false; - case io::Tokenizer::TYPE_IDENTIFIER: { - value_location.AddPath( - UninterpretedOption::kIdentifierValueFieldNumber); - if (is_negative) { - AddError("Invalid '-' symbol before identifier."); - return false; - } - string value; - DO(ConsumeIdentifier(&value, "Expected identifier.")); - uninterpreted_option->set_identifier_value(value); - break; + case io::Tokenizer::TYPE_IDENTIFIER: { + if (is_negative) { + AddError("Invalid '-' symbol before identifier."); + return false; } + string value; + DO(ConsumeIdentifier(&value, "Expected identifier.")); + uninterpreted_option->set_identifier_value(value); + break; + } - case io::Tokenizer::TYPE_INTEGER: { - uint64 value; - uint64 max_value = - is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); - if (is_negative) { - value_location.AddPath( - UninterpretedOption::kNegativeIntValueFieldNumber); - uninterpreted_option->set_negative_int_value( - -static_cast<int64>(value)); - } else { - value_location.AddPath( - UninterpretedOption::kPositiveIntValueFieldNumber); - uninterpreted_option->set_positive_int_value(value); - } - break; + case io::Tokenizer::TYPE_INTEGER: { + uint64 value; + uint64 max_value = + is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max; + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + if (is_negative) { + uninterpreted_option->set_negative_int_value(-value); + } else { + uninterpreted_option->set_positive_int_value(value); } + break; + } - case io::Tokenizer::TYPE_FLOAT: { - value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); - double value; - DO(ConsumeNumber(&value, "Expected number.")); - uninterpreted_option->set_double_value(is_negative ? -value : value); - break; - } + case io::Tokenizer::TYPE_FLOAT: { + double value; + DO(ConsumeNumber(&value, "Expected number.")); + uninterpreted_option->set_double_value(is_negative ? -value : value); + break; + } - case io::Tokenizer::TYPE_STRING: { - value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); - if (is_negative) { - AddError("Invalid '-' symbol before string."); - return false; - } - string value; - DO(ConsumeString(&value, "Expected string.")); - uninterpreted_option->set_string_value(value); - break; + case io::Tokenizer::TYPE_STRING: { + if (is_negative) { + AddError("Invalid '-' symbol before string."); + return false; } - - case io::Tokenizer::TYPE_SYMBOL: - if (LookingAt("{")) { - value_location.AddPath( - UninterpretedOption::kAggregateValueFieldNumber); - DO(ParseUninterpretedBlock( - uninterpreted_option->mutable_aggregate_value())); - } else { - AddError("Expected option value."); - return false; - } - break; + string value; + DO(ConsumeString(&value, "Expected string.")); + uninterpreted_option->set_string_value(value); + break; } - } - if (style == OPTION_STATEMENT) { - DO(ConsumeEndOfDeclaration(";", &location)); + case io::Tokenizer::TYPE_SYMBOL: + AddError("Expected option value."); + return false; } - return true; } -bool Parser::ParseExtensions(DescriptorProto* message, - const LocationRecorder& extensions_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseExtensions(DescriptorProto* message) { // Parse the declaration. DO(Consume("extensions")); do { - // Note that kExtensionRangeFieldNumber was already pushed by the parent. - LocationRecorder location(extensions_location, - message->extension_range_size()); - DescriptorProto::ExtensionRange* range = message->add_extension_range(); - location.RecordLegacyLocation( - range, DescriptorPool::ErrorCollector::NUMBER); + RecordLocation(range, DescriptorPool::ErrorCollector::NUMBER); int start, end; - io::Tokenizer::Token start_token; - - { - LocationRecorder start_location( - location, DescriptorProto::ExtensionRange::kStartFieldNumber); - start_token = input_->current(); - DO(ConsumeInteger(&start, "Expected field number range.")); - } + DO(ConsumeInteger(&start, "Expected field number range.")); if (TryConsume("to")) { - LocationRecorder end_location( - location, DescriptorProto::ExtensionRange::kEndFieldNumber); if (TryConsume("max")) { - // Set to the sentinel value - 1 since we increment the value below. - // The actual value of the end of the range should be set with - // AdjustExtensionRangesWithMaxEndNumber. - end = kMaxExtensionRangeSentinel - 1; + end = FieldDescriptor::kMaxNumber; } else { DO(ConsumeInteger(&end, "Expected integer.")); } } else { - LocationRecorder end_location( - location, DescriptorProto::ExtensionRange::kEndFieldNumber); - end_location.StartAt(start_token); - end_location.EndAt(start_token); end = start; } @@ -1203,26 +782,24 @@ bool Parser::ParseExtensions(DescriptorProto* message, range->set_end(end); } while (TryConsume(",")); - DO(ConsumeEndOfDeclaration(";", &extensions_location)); + DO(Consume(";")); return true; } bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& extend_location, - const FileDescriptorProto* containing_file) { + RepeatedPtrField<DescriptorProto>* messages) { DO(Consume("extend")); + // We expect to see at least one extension field defined in the extend block. + // We need to create it now so we can record the extendee's location. + FieldDescriptorProto* first_field = extensions->Add(); + // Parse the extendee type. - io::Tokenizer::Token extendee_start = input_->current(); - string extendee; - DO(ParseUserDefinedType(&extendee)); - io::Tokenizer::Token extendee_end = input_->previous(); + RecordLocation(first_field, DescriptorPool::ErrorCollector::EXTENDEE); + DO(ParseUserDefinedType(first_field->mutable_extendee())); // Parse the block. - DO(ConsumeEndOfDeclaration("{", &extend_location)); + DO(Consume("{")); bool is_first = true; @@ -1232,92 +809,21 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, return false; } - // Note that kExtensionFieldNumber was already pushed by the parent. - LocationRecorder location(extend_location, extensions->size()); - - FieldDescriptorProto* field = extensions->Add(); - - { - LocationRecorder extendee_location( - location, FieldDescriptorProto::kExtendeeFieldNumber); - extendee_location.StartAt(extendee_start); - extendee_location.EndAt(extendee_end); - - if (is_first) { - extendee_location.RecordLegacyLocation( - field, DescriptorPool::ErrorCollector::EXTENDEE); - is_first = false; - } - } - - field->set_extendee(extendee); - - if (!ParseMessageField(field, messages, parent_location, - location_field_number_for_nested_type, - location, - containing_file)) { - // This statement failed to parse. Skip it, but keep looping to parse - // other statements. - SkipStatement(); - } - } while (!TryConsumeEndOfDeclaration("}", NULL)); - - return true; -} - -bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, - DescriptorProto* containing_type, - int oneof_index, - const LocationRecorder& oneof_location, - const LocationRecorder& containing_type_location, - const FileDescriptorProto* containing_file) { - DO(Consume("oneof")); - - { - LocationRecorder name_location(oneof_location, - OneofDescriptorProto::kNameFieldNumber); - DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name.")); - } - - DO(ConsumeEndOfDeclaration("{", &oneof_location)); - - do { - if (AtEnd()) { - AddError("Reached end of input in oneof definition (missing '}')."); - return false; - } - - // Print a nice error if the user accidentally tries to place a label - // on an individual member of a oneof. - if (LookingAt("required") || - LookingAt("optional") || - LookingAt("repeated")) { - AddError("Fields in oneofs must not have labels (required / optional " - "/ repeated)."); - // We can continue parsing here because we understand what the user - // meant. The error report will still make parsing fail overall. - input_->Next(); + FieldDescriptorProto* field; + if (is_first) { + field = first_field; + is_first = false; + } else { + field = extensions->Add(); + field->set_extendee(first_field->extendee()); } - LocationRecorder field_location(containing_type_location, - DescriptorProto::kFieldFieldNumber, - containing_type->field_size()); - - FieldDescriptorProto* field = containing_type->add_field(); - field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); - field->set_oneof_index(oneof_index); - - if (!ParseMessageFieldNoLabel(field, - containing_type->mutable_nested_type(), - containing_type_location, - DescriptorProto::kNestedTypeFieldNumber, - field_location, - containing_file)) { + if (!ParseMessageField(field, messages)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); } - } while (!TryConsumeEndOfDeclaration("}", NULL)); + } while(!TryConsume("}")); return true; } @@ -1325,35 +831,24 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, // ------------------------------------------------------------------- // Enums -bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type) { DO(Consume("enum")); - - { - LocationRecorder location(enum_location, - EnumDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - enum_type, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); - } - - DO(ParseEnumBlock(enum_type, enum_location, containing_file)); + RecordLocation(enum_type, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); + DO(ParseEnumBlock(enum_type)); return true; } -bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file) { - DO(ConsumeEndOfDeclaration("{", &enum_location)); +bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { + DO(Consume("{")); - while (!TryConsumeEndOfDeclaration("}", NULL)) { + while (!TryConsume("}")) { if (AtEnd()) { AddError("Reached end of input in enum definition (missing '}')."); return false; } - if (!ParseEnumStatement(enum_type, enum_location, containing_file)) { + if (!ParseEnumStatement(enum_type)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1363,73 +858,41 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, return true; } -bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file) { - if (TryConsumeEndOfDeclaration(";", NULL)) { +bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type) { + if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("option")) { - LocationRecorder location(enum_location, - EnumDescriptorProto::kOptionsFieldNumber); - return ParseOption(enum_type->mutable_options(), location, - containing_file, OPTION_STATEMENT); + return ParseOption(enum_type->mutable_options()); } else { - LocationRecorder location(enum_location, - EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); - return ParseEnumConstant(enum_type->add_value(), location, containing_file); + return ParseEnumConstant(enum_type->add_value()); } } -bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, - const LocationRecorder& enum_value_location, - const FileDescriptorProto* containing_file) { - // Parse name. - { - LocationRecorder location(enum_value_location, - EnumValueDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - enum_value, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_value->mutable_name(), - "Expected enum constant name.")); - } - +bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value) { + RecordLocation(enum_value, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_value->mutable_name(), + "Expected enum constant name.")); DO(Consume("=", "Missing numeric value for enum constant.")); - // Parse value. - { - LocationRecorder location( - enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); - location.RecordLegacyLocation( - enum_value, DescriptorPool::ErrorCollector::NUMBER); + bool is_negative = TryConsume("-"); + int number; + DO(ConsumeInteger(&number, "Expected integer.")); + if (is_negative) number *= -1; + enum_value->set_number(number); - int number; - DO(ConsumeSignedInteger(&number, "Expected integer.")); - enum_value->set_number(number); - } + DO(ParseEnumConstantOptions(enum_value)); - DO(ParseEnumConstantOptions(enum_value, enum_value_location, - containing_file)); - - DO(ConsumeEndOfDeclaration(";", &enum_value_location)); + DO(Consume(";")); return true; } -bool Parser::ParseEnumConstantOptions( - EnumValueDescriptorProto* value, - const LocationRecorder& enum_value_location, - const FileDescriptorProto* containing_file) { - if (!LookingAt("[")) return true; - - LocationRecorder location( - enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); - - DO(Consume("[")); +bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) { + if (!TryConsume("[")) return true; do { - DO(ParseOption(value->mutable_options(), location, - containing_file, OPTION_ASSIGNMENT)); + DO(ParseOptionAssignment(value->mutable_options())); } while (TryConsume(",")); DO(Consume("]")); @@ -1439,36 +902,24 @@ bool Parser::ParseEnumConstantOptions( // ------------------------------------------------------------------- // Services -bool Parser::ParseServiceDefinition( - ServiceDescriptorProto* service, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service) { DO(Consume("service")); - - { - LocationRecorder location(service_location, - ServiceDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - service, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); - } - - DO(ParseServiceBlock(service, service_location, containing_file)); + RecordLocation(service, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); + DO(ParseServiceBlock(service)); return true; } -bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file) { - DO(ConsumeEndOfDeclaration("{", &service_location)); +bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { + DO(Consume("{")); - while (!TryConsumeEndOfDeclaration("}", NULL)) { + while (!TryConsume("}")) { if (AtEnd()) { AddError("Reached end of input in service definition (missing '}')."); return false; } - if (!ParseServiceStatement(service, service_location, containing_file)) { + if (!ParseServiceStatement(service)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1478,98 +929,55 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, return true; } -bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file) { - if (TryConsumeEndOfDeclaration(";", NULL)) { +bool Parser::ParseServiceStatement(ServiceDescriptorProto* service) { + if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("option")) { - LocationRecorder location( - service_location, ServiceDescriptorProto::kOptionsFieldNumber); - return ParseOption(service->mutable_options(), location, - containing_file, OPTION_STATEMENT); + return ParseOption(service->mutable_options()); } else { - LocationRecorder location(service_location, - ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); - return ParseServiceMethod(service->add_method(), location, containing_file); + return ParseServiceMethod(service->add_method()); } } -bool Parser::ParseServiceMethod(MethodDescriptorProto* method, - const LocationRecorder& method_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseServiceMethod(MethodDescriptorProto* method) { DO(Consume("rpc")); - - { - LocationRecorder location(method_location, - MethodDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); - } + RecordLocation(method, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); // Parse input type. DO(Consume("(")); - { - LocationRecorder location(method_location, - MethodDescriptorProto::kInputTypeFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::INPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_input_type())); - } + RecordLocation(method, DescriptorPool::ErrorCollector::INPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_input_type())); DO(Consume(")")); // Parse output type. DO(Consume("returns")); DO(Consume("(")); - { - LocationRecorder location(method_location, - MethodDescriptorProto::kOutputTypeFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_output_type())); - } + RecordLocation(method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_output_type())); DO(Consume(")")); - if (LookingAt("{")) { + if (TryConsume("{")) { // Options! - DO(ParseOptions(method_location, - containing_file, - MethodDescriptorProto::kOptionsFieldNumber, - method->mutable_options())); - } else { - DO(ConsumeEndOfDeclaration(";", &method_location)); - } - - return true; -} - - -bool Parser::ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options) { - // Options! - ConsumeEndOfDeclaration("{", &parent_location); - while (!TryConsumeEndOfDeclaration("}", NULL)) { - if (AtEnd()) { - AddError("Reached end of input in method options (missing '}')."); - return false; - } + while (!TryConsume("}")) { + if (AtEnd()) { + AddError("Reached end of input in method options (missing '}')."); + return false; + } - if (TryConsumeEndOfDeclaration(";", NULL)) { - // empty statement; ignore - } else { - LocationRecorder location(parent_location, - optionsFieldNumber); - if (!ParseOption(mutable_options, location, containing_file, - OPTION_STATEMENT)) { - // This statement failed to parse. Skip it, but keep looping to - // parse other statements. - SkipStatement(); + if (TryConsume(";")) { + // empty statement; ignore + } else { + if (!ParseOption(method->mutable_options())) { + // This statement failed to parse. Skip it, but keep looping to + // parse other statements. + SkipStatement(); + } } } + } else { + DO(Consume(";")); } return true; @@ -1577,8 +985,7 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location, // ------------------------------------------------------------------- -bool Parser::ParseLabel(FieldDescriptorProto::Label* label, - const FileDescriptorProto* containing_file) { +bool Parser::ParseLabel(FieldDescriptorProto::Label* label) { if (TryConsume("optional")) { *label = FieldDescriptorProto::LABEL_OPTIONAL; return true; @@ -1646,9 +1053,7 @@ bool Parser::ParseUserDefinedType(string* type_name) { // =================================================================== -bool Parser::ParsePackage(FileDescriptorProto* file, - const LocationRecorder& root_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParsePackage(FileDescriptorProto* file) { if (file->has_package()) { AddError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not @@ -1658,57 +1063,32 @@ bool Parser::ParsePackage(FileDescriptorProto* file, DO(Consume("package")); - { - LocationRecorder location(root_location, - FileDescriptorProto::kPackageFieldNumber); - location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); - - while (true) { - string identifier; - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - file->mutable_package()->append(identifier); - if (!TryConsume(".")) break; - file->mutable_package()->append("."); - } - - location.EndAt(input_->previous()); + RecordLocation(file, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeEndOfDeclaration(";", &location)); + while (true) { + string identifier; + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + file->mutable_package()->append(identifier); + if (!TryConsume(".")) break; + file->mutable_package()->append("."); } + DO(Consume(";")); return true; } -bool Parser::ParseImport(RepeatedPtrField<string>* dependency, - RepeatedField<int32>* public_dependency, - RepeatedField<int32>* weak_dependency, - const LocationRecorder& root_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseImport(string* import_filename) { DO(Consume("import")); - if (LookingAt("public")) { - LocationRecorder location( - root_location, FileDescriptorProto::kPublicDependencyFieldNumber, - public_dependency->size()); - DO(Consume("public")); - *public_dependency->Add() = dependency->size(); - } else if (LookingAt("weak")) { - LocationRecorder location( - root_location, FileDescriptorProto::kWeakDependencyFieldNumber, - weak_dependency->size()); - DO(Consume("weak")); - *weak_dependency->Add() = dependency->size(); - } - { - LocationRecorder location(root_location, - FileDescriptorProto::kDependencyFieldNumber, - dependency->size()); - DO(ConsumeString(dependency->Add(), - "Expected a string naming the file to import.")); - - location.EndAt(input_->previous()); + DO(ConsumeString(import_filename, + "Expected a string naming the file to import.")); + DO(Consume(";")); + return true; +} - DO(ConsumeEndOfDeclaration(";", &location)); - } +bool Parser::ParseOption(Message* options) { + DO(Consume("option")); + DO(ParseOptionAssignment(options)); + DO(Consume(";")); return true; } diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index d0a2359..72c96d0 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -40,6 +40,7 @@ #include <map> #include <string> #include <utility> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/repeated_field.h> @@ -73,9 +74,6 @@ class LIBPROTOBUF_EXPORT Parser { // Optional fetaures: - // DEPRECATED: New code should use the SourceCodeInfo embedded in the - // FileDescriptorProto. - // // Requests that locations of certain definitions be recorded to the given // SourceLocationTable while parsing. This can be used to look up exact line // and column numbers for errors reported by DescriptorPool during validation. @@ -84,7 +82,7 @@ class LIBPROTOBUF_EXPORT Parser { source_location_table_ = location_table; } - // Requests that errors be recorded to the given ErrorCollector while + // Requsets that errors be recorded to the given ErrorCollector while // parsing. Set to NULL (the default) to discard error messages. void RecordErrorsTo(io::ErrorCollector* error_collector) { error_collector_ = error_collector; @@ -115,8 +113,6 @@ class LIBPROTOBUF_EXPORT Parser { } private: - class LocationRecorder; - // ================================================================= // Error recovery helpers @@ -165,8 +161,6 @@ class LIBPROTOBUF_EXPORT Parser { bool ConsumeIdentifier(string* output, const char* error); // Consume an integer and store its value in "output". bool ConsumeInteger(int* output, const char* error); - // Consume a signed integer and store its value in "output". - bool ConsumeSignedInteger(int* output, const char* error); // Consume a 64-bit integer and store its value in "output". If the value // is greater than max_value, an error will be reported. bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error); @@ -176,20 +170,6 @@ class LIBPROTOBUF_EXPORT Parser { // Consume a string literal and store its (unescaped) value in "output". bool ConsumeString(string* output, const char* error); - // Consume a token representing the end of the statement. Comments between - // this token and the next will be harvested for documentation. The given - // LocationRecorder should refer to the declaration that was just parsed; - // it will be populated with these comments. - // - // TODO(kenton): The LocationRecorder is const because historically locations - // have been passed around by const reference, for no particularly good - // reason. We should probably go through and change them all to mutable - // pointer to make this more intuitive. - bool TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); - bool ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); - // ----------------------------------------------------------------- // Error logging helpers @@ -200,67 +180,16 @@ class LIBPROTOBUF_EXPORT Parser { // of the current token. void AddError(const string& error); - // Records a location in the SourceCodeInfo.location table (see - // descriptor.proto). We use RAII to ensure that the start and end locations - // are recorded -- the constructor records the start location and the - // destructor records the end location. Since the parser is - // recursive-descent, this works out beautifully. - class LIBPROTOBUF_EXPORT LocationRecorder { - public: - // Construct the file's "root" location. - LocationRecorder(Parser* parser); - - // Construct a location that represents a declaration nested within the - // given parent. E.g. a field's location is nested within the location - // for a message type. The parent's path will be copied, so you should - // call AddPath() only to add the path components leading from the parent - // to the child (as opposed to leading from the root to the child). - LocationRecorder(const LocationRecorder& parent); - - // Convenience constructors that call AddPath() one or two times. - LocationRecorder(const LocationRecorder& parent, int path1); - LocationRecorder(const LocationRecorder& parent, int path1, int path2); - - ~LocationRecorder(); - - // Add a path component. See SourceCodeInfo.Location.path in - // descriptor.proto. - void AddPath(int path_component); - - // By default the location is considered to start at the current token at - // the time the LocationRecorder is created. StartAt() sets the start - // location to the given token instead. - void StartAt(const io::Tokenizer::Token& token); - - // Start at the same location as some other LocationRecorder. - void StartAt(const LocationRecorder& other); - - // By default the location is considered to end at the previous token at - // the time the LocationRecorder is destroyed. EndAt() sets the end - // location to the given token instead. - void EndAt(const io::Tokenizer::Token& token); - - // Records the start point of this location to the SourceLocationTable that - // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable - // is an older way of keeping track of source locations which is still - // used in some places. - void RecordLegacyLocation(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location); - - // Attaches leading and trailing comments to the location. The two strings - // will be swapped into place, so after this is called *leading and - // *trailing will be empty. - // - // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for - // why this is const. - void AttachComments(string* leading, string* trailing) const; - - private: - Parser* parser_; - SourceCodeInfo::Location* location_; - - void Init(const LocationRecorder& parent); - }; + // Record the given line and column and associate it with this descriptor + // in the SourceLocationTable. + void RecordLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int line, int column); + + // Record the current line and column and associate it with this descriptor + // in the SourceLocationTable. + void RecordLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location); // ================================================================= // Parsers for various language constructs @@ -281,131 +210,54 @@ class LIBPROTOBUF_EXPORT Parser { // makes logic much simpler for the caller. // Parse a top-level message, enum, service, etc. - bool ParseTopLevelStatement(FileDescriptorProto* file, - const LocationRecorder& root_location); + bool ParseTopLevelStatement(FileDescriptorProto* file); // Parse various language high-level language construrcts. - bool ParseMessageDefinition(DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file); - bool ParseEnumDefinition(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file); - bool ParseServiceDefinition(ServiceDescriptorProto* service, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file); - bool ParsePackage(FileDescriptorProto* file, - const LocationRecorder& root_location, - const FileDescriptorProto* containing_file); - bool ParseImport(RepeatedPtrField<string>* dependency, - RepeatedField<int32>* public_dependency, - RepeatedField<int32>* weak_dependency, - const LocationRecorder& root_location, - const FileDescriptorProto* containing_file); - bool ParseOption(Message* options, - const LocationRecorder& options_location, - const FileDescriptorProto* containing_file); + bool ParseMessageDefinition(DescriptorProto* message); + bool ParseEnumDefinition(EnumDescriptorProto* enum_type); + bool ParseServiceDefinition(ServiceDescriptorProto* service); + bool ParsePackage(FileDescriptorProto* file); + bool ParseImport(string* import_filename); + bool ParseOption(Message* options); // These methods parse the contents of a message, enum, or service type and // add them to the given object. They consume the entire block including // the beginning and ending brace. - bool ParseMessageBlock(DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file); - bool ParseEnumBlock(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file); - bool ParseServiceBlock(ServiceDescriptorProto* service, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file); + bool ParseMessageBlock(DescriptorProto* message); + bool ParseEnumBlock(EnumDescriptorProto* enum_type); + bool ParseServiceBlock(ServiceDescriptorProto* service); // Parse one statement within a message, enum, or service block, inclunding // final semicolon. - bool ParseMessageStatement(DescriptorProto* message, - const LocationRecorder& message_location, - const FileDescriptorProto* containing_file); - bool ParseEnumStatement(EnumDescriptorProto* message, - const LocationRecorder& enum_location, - const FileDescriptorProto* containing_file); - bool ParseServiceStatement(ServiceDescriptorProto* message, - const LocationRecorder& service_location, - const FileDescriptorProto* containing_file); + bool ParseMessageStatement(DescriptorProto* message); + bool ParseEnumStatement(EnumDescriptorProto* message); + bool ParseServiceStatement(ServiceDescriptorProto* message); // Parse a field of a message. If the field is a group, its type will be // added to "messages". - // - // parent_location and location_field_number_for_nested_type are needed when - // parsing groups -- we need to generate a nested message type within the - // parent and record its location accordingly. Since the parent could be - // either a FileDescriptorProto or a DescriptorProto, we must pass in the - // correct field number to use. bool ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file); - - // Like ParseMessageField() but expects the label has already been filled in - // by the caller. - bool ParseMessageFieldNoLabel(FieldDescriptorProto* field, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file); + RepeatedPtrField<DescriptorProto>* messages); // Parse an "extensions" declaration. - bool ParseExtensions(DescriptorProto* message, - const LocationRecorder& extensions_location, - const FileDescriptorProto* containing_file); + bool ParseExtensions(DescriptorProto* message); - // Parse an "extend" declaration. (See also comments for - // ParseMessageField().) + // Parse an "extend" declaration. bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, - RepeatedPtrField<DescriptorProto>* messages, - const LocationRecorder& parent_location, - int location_field_number_for_nested_type, - const LocationRecorder& extend_location, - const FileDescriptorProto* containing_file); - - // Parse a "oneof" declaration. The caller is responsible for setting - // oneof_decl->label() since it will have had to parse the label before it - // knew it was parsing a oneof. - bool ParseOneof(OneofDescriptorProto* oneof_decl, - DescriptorProto* containing_type, - int oneof_index, - const LocationRecorder& oneof_location, - const LocationRecorder& containing_type_location, - const FileDescriptorProto* containing_file); + RepeatedPtrField<DescriptorProto>* messages); // Parse a single enum value within an enum block. - bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, - const LocationRecorder& enum_value_location, - const FileDescriptorProto* containing_file); + bool ParseEnumConstant(EnumValueDescriptorProto* enum_value); // Parse enum constant options, i.e. the list in square brackets at the end // of the enum constant value definition. - bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, - const LocationRecorder& enum_value_location, - const FileDescriptorProto* containing_file); + bool ParseEnumConstantOptions(EnumValueDescriptorProto* value); // Parse a single method within a service definition. - bool ParseServiceMethod(MethodDescriptorProto* method, - const LocationRecorder& method_location, - const FileDescriptorProto* containing_file); - - - // Parse options of a single method or stream. - bool ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options); + bool ParseServiceMethod(MethodDescriptorProto* method); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. - bool ParseLabel(FieldDescriptorProto::Label* label, - const FileDescriptorProto* containing_file); + bool ParseLabel(FieldDescriptorProto::Label* label); // Parse a type name and fill in "type" (if it is a primitive) or // "type_name" (if it is not) with the type parsed. @@ -417,75 +269,39 @@ class LIBPROTOBUF_EXPORT Parser { // Parses field options, i.e. the stuff in square brackets at the end // of a field definition. Also parses default value. - bool ParseFieldOptions(FieldDescriptorProto* field, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file); + bool ParseFieldOptions(FieldDescriptorProto* field); // Parse the "default" option. This needs special handling because its // type is the field's type. - bool ParseDefaultAssignment(FieldDescriptorProto* field, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file); - - enum OptionStyle { - OPTION_ASSIGNMENT, // just "name = value" - OPTION_STATEMENT // "option name = value;" - }; + bool ParseDefaultAssignment(FieldDescriptorProto* field); // Parse a single option name/value pair, e.g. "ctype = CORD". The name // identifies a field of the given Message, and the value of that field // is set to the parsed value. - bool ParseOption(Message* options, - const LocationRecorder& options_location, - const FileDescriptorProto* containing_file, - OptionStyle style); + bool ParseOptionAssignment(Message* options); // Parses a single part of a multipart option name. A multipart name consists // of names separated by dots. Each name is either an identifier or a series // of identifiers separated by dots and enclosed in parentheses. E.g., // "foo.(bar.baz).qux". - bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, - const LocationRecorder& part_location, - const FileDescriptorProto* containing_file); - - // Parses a string surrounded by balanced braces. Strips off the outer - // braces and stores the enclosed string in *value. - // E.g., - // { foo } *value gets 'foo' - // { foo { bar: box } } *value gets 'foo { bar: box }' - // {} *value gets '' - // - // REQUIRES: LookingAt("{") - // When finished successfully, we are looking at the first token past - // the ending brace. - bool ParseUninterpretedBlock(string* value); + bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option); // ================================================================= io::Tokenizer* input_; io::ErrorCollector* error_collector_; - SourceCodeInfo* source_code_info_; - SourceLocationTable* source_location_table_; // legacy + SourceLocationTable* source_location_table_; bool had_errors_; bool require_syntax_identifier_; bool stop_after_syntax_identifier_; string syntax_identifier_; - // Leading doc comments for the next declaration. These are not complete - // yet; use ConsumeEndOfDeclaration() to get the complete comments. - string upcoming_doc_comments_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; // A table mapping (descriptor, ErrorLocation) pairs -- as reported by // DescriptorPool when validating descriptors -- to line and column numbers // within the original source code. -// -// This is semi-obsolete: FileDescriptorProto.source_code_info now contains -// far more complete information about source locations. However, as of this -// writing you still need to use SourceLocationTable when integrating with -// DescriptorPool. class LIBPROTOBUF_EXPORT SourceLocationTable { public: SourceLocationTable(); diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 9ec29a4..e2262b8 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,10 +32,8 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <memory> #include <vector> #include <algorithm> -#include <map> #include <google/protobuf/compiler/parser.h> @@ -45,10 +43,8 @@ #include <google/protobuf/wire_format.h> #include <google/protobuf/text_format.h> #include <google/protobuf/unittest.pb.h> -#include <google/protobuf/unittest_custom_options.pb.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/stubs/map_util.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> @@ -122,9 +118,6 @@ class ParserTest : public testing::Test { EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); ASSERT_EQ("", error_collector_.text_); - // We don't cover SourceCodeInfo in these tests. - actual.clear_source_code_info(); - // Parse the ASCII representation in order to canonicalize it. We could // just compare directly to actual.DebugString(), but that would require // that the caller precisely match the formatting that DebugString() @@ -437,69 +430,6 @@ TEST_F(ParseMessageTest, FieldOptions) { "}"); } -TEST_F(ParseMessageTest, Oneof) { - ExpectParsesTo( - "message TestMessage {\n" - " oneof foo {\n" - " int32 a = 1;\n" - " string b = 2;\n" - " TestMessage c = 3;\n" - " group D = 4 { optional int32 i = 5; }\n" - " }\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " - " oneof_index:0 }" - " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " - " oneof_index:0 }" - " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " - " number:3 oneof_index:0 }" - " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " - " type_name:\"D\" number:4 oneof_index:0 }" - " oneof_decl {" - " name: \"foo\"" - " }" - " nested_type {" - " name: \"D\"" - " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" - " }" - "}"); -} - -TEST_F(ParseMessageTest, MultipleOneofs) { - ExpectParsesTo( - "message TestMessage {\n" - " oneof foo {\n" - " int32 a = 1;\n" - " string b = 2;\n" - " }\n" - " oneof bar {\n" - " int32 c = 3;\n" - " string d = 4;\n" - " }\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " - " oneof_index:0 }" - " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " - " oneof_index:0 }" - " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " - " oneof_index:1 }" - " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " - " oneof_index:1 }" - " oneof_decl {" - " name: \"foo\"" - " }" - " oneof_decl {" - " name: \"bar\"" - " }" - "}"); -} - TEST_F(ParseMessageTest, Group) { ExpectParsesTo( "message TestMessage {\n" @@ -574,31 +504,6 @@ TEST_F(ParseMessageTest, CompoundExtensionRange) { "}"); } -TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) { - // Messages using the message_set_wire_format option can accept larger - // extension numbers, as the numbers are not encoded as int32 field values - // rather than tags. - ExpectParsesTo( - "message TestMessage {\n" - " extensions 4 to max;\n" - " option message_set_wire_format = true;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " extension_range { start:4 end: 0x7fffffff }" - " options {\n" - " uninterpreted_option { \n" - " name {\n" - " name_part: \"message_set_wire_format\"\n" - " is_extension: false\n" - " }\n" - " identifier_value: \"true\"\n" - " }\n" - " }\n" - "}"); -} - TEST_F(ParseMessageTest, Extensions) { ExpectParsesTo( "extend Extendee1 { optional int32 foo = 12; }\n" @@ -639,7 +544,6 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); } - // =================================================================== typedef ParserTest ParseEnumTest; @@ -662,10 +566,6 @@ TEST_F(ParseEnumTest, Values) { " FOO = 13;\n" " BAR = -10;\n" " BAZ = 500;\n" - " HEX_MAX = 0x7FFFFFFF;\n" - " HEX_MIN = -0x80000000;\n" - " INT_MAX = 2147483647;\n" - " INT_MIN = -2147483648;\n" "}\n", "enum_type {" @@ -673,10 +573,6 @@ TEST_F(ParseEnumTest, Values) { " value { name:\"FOO\" number:13 }" " value { name:\"BAR\" number:-10 }" " value { name:\"BAZ\" number:500 }" - " value { name:\"HEX_MAX\" number:2147483647 }" - " value { name:\"HEX_MIN\" number:-2147483648 }" - " value { name:\"INT_MAX\" number:2147483647 }" - " value { name:\"INT_MIN\" number:-2147483648 }" "}"); } @@ -730,7 +626,7 @@ TEST_F(ParseServiceTest, SimpleService) { "}"); } -TEST_F(ParseServiceTest, MethodsAndStreams) { +TEST_F(ParseServiceTest, Methods) { ExpectParsesTo( "service TestService {\n" " rpc Foo(In1) returns (Out1);\n" @@ -746,8 +642,6 @@ TEST_F(ParseServiceTest, MethodsAndStreams) { "}"); } - - // =================================================================== // imports and packages @@ -769,20 +663,6 @@ TEST_F(ParseMiscTest, ParseMultipleImports) { "dependency: \"baz.proto\""); } -TEST_F(ParseMiscTest, ParsePublicImports) { - ExpectParsesTo( - "import \"foo.proto\";\n" - "import public \"bar.proto\";\n" - "import \"baz.proto\";\n" - "import public \"qux.proto\";\n", - "dependency: \"foo.proto\"" - "dependency: \"bar.proto\"" - "dependency: \"baz.proto\"" - "dependency: \"qux.proto\"" - "public_dependency: 1 " - "public_dependency: 3 "); -} - TEST_F(ParseMiscTest, ParsePackage) { ExpectParsesTo( "package foo.bar.baz;\n", @@ -937,7 +817,7 @@ TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { "message TestMessage {\n" " optional uint32 foo = 1 [default=true];\n" "}\n", - "1:35: Expected integer for field default value.\n"); + "1:35: Expected integer.\n"); } TEST_F(ParseErrorTest, DefaultValueNotBoolean) { @@ -953,7 +833,7 @@ TEST_F(ParseErrorTest, DefaultValueNotString) { "message TestMessage {\n" " optional string foo = 1 [default=1];\n" "}\n", - "1:35: Expected string for field default value.\n"); + "1:35: Expected string.\n"); } TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { @@ -982,26 +862,12 @@ TEST_F(ParseErrorTest, DefaultValueTooLarge) { "6:36: Integer out of range.\n"); } -TEST_F(ParseErrorTest, EnumValueOutOfRange) { - ExpectHasErrors( - "enum TestEnum {\n" - " HEX_TOO_BIG = 0x80000000;\n" - " HEX_TOO_SMALL = -0x80000001;\n" - " INT_TOO_BIG = 2147483648;\n" - " INT_TOO_SMALL = -2147483649;\n" - "}\n", - "1:19: Integer out of range.\n" - "2:19: Integer out of range.\n" - "3:19: Integer out of range.\n" - "4:19: Integer out of range.\n"); -} - TEST_F(ParseErrorTest, DefaultValueMissing) { ExpectHasErrors( "message TestMessage {\n" " optional uint32 foo = 1 [default=];\n" "}\n", - "1:35: Expected integer for field default value.\n"); + "1:35: Expected integer.\n"); } TEST_F(ParseErrorTest, DefaultValueForGroup) { @@ -1020,27 +886,6 @@ TEST_F(ParseErrorTest, DuplicateDefaultValue) { "1:37: Already set option \"default\".\n"); } -TEST_F(ParseErrorTest, MissingOneofName) { - ExpectHasErrors( - "message TestMessage {\n" - " oneof {\n" - " int32 bar = 1;\n" - " }\n" - "}\n", - "1:8: Expected oneof name.\n"); -} - -TEST_F(ParseErrorTest, LabelInOneof) { - ExpectHasErrors( - "message TestMessage {\n" - " oneof foo {\n" - " optional int32 bar = 1;\n" - " }\n" - "}\n", - "2:4: Fields in oneofs must not have labels (required / optional " - "/ repeated).\n"); -} - TEST_F(ParseErrorTest, GroupNotCapitalized) { ExpectHasErrors( "message TestMessage {\n" @@ -1085,12 +930,6 @@ TEST_F(ParseErrorTest, MultipleParseErrors) { "3:25: Expected \";\".\n"); } -TEST_F(ParseErrorTest, EofInAggregateValue) { - ExpectHasErrors( - "option (fileopt) = { i:100\n", - "1:0: Unexpected end of stream while parsing aggregate value.\n"); -} - // ------------------------------------------------------------------- // Enum errors @@ -1126,7 +965,6 @@ TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { "1:26: Expected message type.\n"); } - TEST_F(ParseErrorTest, EofInMethodOptions) { ExpectHasErrors( "service TestService {\n" @@ -1135,7 +973,6 @@ TEST_F(ParseErrorTest, EofInMethodOptions) { "1:29: Reached end of input in service definition (missing '}').\n"); } - TEST_F(ParseErrorTest, PrimitiveMethodInput) { ExpectHasErrors( "service TestService {\n" @@ -1144,7 +981,6 @@ TEST_F(ParseErrorTest, PrimitiveMethodInput) { "1:10: Expected message type.\n"); } - TEST_F(ParseErrorTest, MethodOptionTypeError) { // This used to cause an infinite loop. ExpectHasErrors( @@ -1155,7 +991,6 @@ TEST_F(ParseErrorTest, MethodOptionTypeError) { "2:45: Expected \"=\".\n"); } - // ------------------------------------------------------------------- // Import and package errors @@ -1311,7 +1146,6 @@ TEST_F(ParserValidationErrorTest, MethodNameError) { "3:6: \"Bar\" is already defined in \"Foo\".\n"); } - TEST_F(ParserValidationErrorTest, MethodInputTypeError) { ExpectHasValidationErrors( "message Baz {}\n" @@ -1321,7 +1155,6 @@ TEST_F(ParserValidationErrorTest, MethodInputTypeError) { "2:10: \"Qux\" is not defined.\n"); } - TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { ExpectHasValidationErrors( "message Baz {}\n" @@ -1331,94 +1164,17 @@ TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { "2:23: \"Qux\" is not defined.\n"); } - -TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { - // Create another file which defines symbol ".base.bar". - FileDescriptorProto other_file; - other_file.set_name("base.proto"); - other_file.set_package("base"); - other_file.add_message_type()->set_name("bar"); - EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); - - // Define "foo.base" and try "base.bar". - // "base.bar" is resolved to "foo.base.bar" which is not defined. - ExpectHasValidationErrors( - "package foo.base;\n" - "import \"base.proto\";\n" - "message qux {\n" - " optional base.bar baz = 1;\n" - " optional .base.bar quz = 2;\n" - "}\n", - "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," - " which is not defined. The innermost scope is searched first " - "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" - " to start from the outermost scope.\n"); -} - -TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { - // Build descriptor message in test pool - FileDescriptorProto descriptor_proto; - DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto); - ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL); - - // base2.proto: - // package baz - // import google/protobuf/descriptor.proto - // message Bar { optional int32 foo = 1; } - // extend FileOptions { optional Bar bar = 7672757; } - FileDescriptorProto other_file; - other_file.set_name("base2.proto"); - other_file.set_package("baz"); - other_file.add_dependency(); - other_file.set_dependency(0, descriptor_proto.name()); - - DescriptorProto* message(other_file.add_message_type()); - message->set_name("Bar"); - FieldDescriptorProto* field(message->add_field()); - field->set_name("foo"); - field->set_number(1); - field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); - field->set_type(FieldDescriptorProto_Type_TYPE_INT32); - - FieldDescriptorProto* extension(other_file.add_extension()); - extension->set_name("bar"); - extension->set_number(7672757); - extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); - extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE); - extension->set_type_name("Bar"); - extension->set_extendee("google.protobuf.FileOptions"); - - EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); - - // qux.proto: - // package qux.baz - // option (baz.bar).foo = 1; - // - // Although "baz.bar" is already defined, the lookup code will try - // "qux.baz.bar", since it's the match from the innermost scope, - // which will cause a symbol not defined error. - ExpectHasValidationErrors( - "package qux.baz;\n" - "import \"base2.proto\";\n" - "option (baz.bar).foo = 1;\n", - "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\"," - " which is not defined. The innermost scope is searched first " - "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")" - " to start from the outermost scope.\n"); -} - // =================================================================== // Test that the output from FileDescriptor::DebugString() (and all other // descriptor types) is parseable, and results in the same Descriptor -// definitions again afoter parsing (note, however, that the order of messages +// definitions again afoter parsing (not, however, that the order of messages // cannot be guaranteed to be the same) typedef ParserTest ParseDecriptorDebugTest; class CompareDescriptorNames { public: - bool operator()(const DescriptorProto* left, - const DescriptorProto* right) const { + bool operator()(const DescriptorProto* left, const DescriptorProto* right) { return left->name() < right->name(); } }; @@ -1462,19 +1218,13 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { FileDescriptorProto parsed; parser_->Parse(input_.get(), &parsed); EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_) - << "Failed to parse:\n" << debug_string; + ASSERT_EQ("", error_collector_.text_); // We now have a FileDescriptorProto, but to compare with the expected we // need to link to a FileDecriptor, then output back to a proto. We'll // also need to give it the same name as the original. parsed.set_name("google/protobuf/unittest.proto"); // We need the imported dependency before we can build our parsed proto - const FileDescriptor* public_import = - protobuf_unittest_import::PublicImportMessage::descriptor()->file(); - FileDescriptorProto public_import_proto; - public_import->CopyTo(&public_import_proto); - ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); const FileDescriptor* import = protobuf_unittest_import::ImportMessage::descriptor()->file(); FileDescriptorProto import_proto; @@ -1482,8 +1232,6 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); const FileDescriptor* actual = pool_.BuildFile(parsed); parsed.Clear(); - ASSERT_TRUE(actual != NULL) - << "Failed to validate:\n" << debug_string; actual->CopyTo(&parsed); ASSERT_TRUE(actual != NULL); @@ -1499,1110 +1247,6 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { EXPECT_EQ(expected.DebugString(), parsed.DebugString()); } -TEST_F(ParseDecriptorDebugTest, TestCustomOptions) { - const FileDescriptor* original_file = - protobuf_unittest::AggregateMessage::descriptor()->file(); - FileDescriptorProto expected; - original_file->CopyTo(&expected); - - string debug_string = original_file->DebugString(); - - // Parse the debug string - SetupParser(debug_string.c_str()); - FileDescriptorProto parsed; - parser_->Parse(input_.get(), &parsed); - EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_); - - // We now have a FileDescriptorProto, but to compare with the expected we - // need to link to a FileDecriptor, then output back to a proto. We'll - // also need to give it the same name as the original. - parsed.set_name(original_file->name()); - - // unittest_custom_options.proto depends on descriptor.proto. - const FileDescriptor* import = FileDescriptorProto::descriptor()->file(); - FileDescriptorProto import_proto; - import->CopyTo(&import_proto); - ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); - const FileDescriptor* actual = pool_.BuildFile(parsed); - ASSERT_TRUE(actual != NULL); - parsed.Clear(); - actual->CopyTo(&parsed); - - // The messages might be in different orders, making them hard to compare. - // So, sort the messages in the descriptor protos (including nested messages, - // recursively). - SortMessages(&expected); - SortMessages(&parsed); - - EXPECT_EQ(expected.DebugString(), parsed.DebugString()); -} - -// =================================================================== -// SourceCodeInfo tests. - -// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a -// message to a particular sub-field. -// * If the target is itself a message, sets *output_message to point at it, -// *output_field to NULL, and *output_index to -1. -// * Otherwise, if the target is an element of a repeated field, sets -// *output_message to the containing message, *output_field to the descriptor -// of the field, and *output_index to the index of the element. -// * Otherwise, the target is a field (possibly a repeated field, but not any -// one element). Sets *output_message to the containing message, -// *output_field to the descriptor of the field, and *output_index to -1. -// Returns true if the path was valid, false otherwise. A gTest failure is -// recorded before returning false. -bool FollowPath(const Message& root, - const int* path_begin, const int* path_end, - const Message** output_message, - const FieldDescriptor** output_field, - int* output_index) { - if (path_begin == path_end) { - // Path refers to this whole message. - *output_message = &root; - *output_field = NULL; - *output_index = -1; - return true; - } - - const Descriptor* descriptor = root.GetDescriptor(); - const Reflection* reflection = root.GetReflection(); - - const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin); - - if (field == NULL) { - ADD_FAILURE() << descriptor->name() << " has no field number: " - << *path_begin; - return false; - } - - ++path_begin; - - if (field->is_repeated()) { - if (path_begin == path_end) { - // Path refers to the whole repeated field. - *output_message = &root; - *output_field = field; - *output_index = -1; - return true; - } - - int index = *path_begin++; - int size = reflection->FieldSize(root, field); - - if (index >= size) { - ADD_FAILURE() << descriptor->name() << "." << field->name() - << " has size " << size << ", but path contained index: " - << index; - return false; - } - - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Descend into child message. - const Message& child = reflection->GetRepeatedMessage(root, field, index); - return FollowPath(child, path_begin, path_end, - output_message, output_field, output_index); - } else if (path_begin == path_end) { - // Path refers to this element. - *output_message = &root; - *output_field = field; - *output_index = index; - return true; - } else { - ADD_FAILURE() << descriptor->name() << "." << field->name() - << " is not a message; cannot descend into it."; - return false; - } - } else { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - const Message& child = reflection->GetMessage(root, field); - return FollowPath(child, path_begin, path_end, - output_message, output_field, output_index); - } else if (path_begin == path_end) { - // Path refers to this field. - *output_message = &root; - *output_field = field; - *output_index = -1; - return true; - } else { - ADD_FAILURE() << descriptor->name() << "." << field->name() - << " is not a message; cannot descend into it."; - return false; - } - } -} - -// Check if two spans are equal. -bool CompareSpans(const RepeatedField<int>& span1, - const RepeatedField<int>& span2) { - if (span1.size() != span2.size()) return false; - for (int i = 0; i < span1.size(); i++) { - if (span1.Get(i) != span2.Get(i)) return false; - } - return true; -} - -// Test fixture for source info tests, which check that source locations are -// recorded correctly in FileDescriptorProto.source_code_info.location. -class SourceInfoTest : public ParserTest { - protected: - // The parsed file (initialized by Parse()). - FileDescriptorProto file_; - - // Parse the given text as a .proto file and populate the spans_ map with - // all the source location spans in its SourceCodeInfo table. - bool Parse(const char* text) { - ExtractMarkers(text); - SetupParser(text_without_markers_.c_str()); - if (!parser_->Parse(input_.get(), &file_)) { - return false; - } - - const SourceCodeInfo& source_info = file_.source_code_info(); - for (int i = 0; i < source_info.location_size(); i++) { - const SourceCodeInfo::Location& location = source_info.location(i); - const Message* descriptor_proto = NULL; - const FieldDescriptor* field = NULL; - int index = 0; - if (!FollowPath(file_, location.path().begin(), location.path().end(), - &descriptor_proto, &field, &index)) { - return false; - } - - spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), - &location)); - } - - return true; - } - - virtual void TearDown() { - EXPECT_TRUE(spans_.empty()) - << "Forgot to call HasSpan() for:\n" - << spans_.begin()->second->DebugString(); - } - - // ----------------------------------------------------------------- - // HasSpan() checks that the span of source code delimited by the given - // tags (comments) correspond via the SourceCodeInfo table to the given - // part of the FileDescriptorProto. (If unclear, look at the actual tests; - // it should quickly become obvious.) - - bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto) { - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); - } - - bool HasSpanWithComment(char start_marker, char end_marker, - const Message& descriptor_proto, - const char* expected_leading_comments, - const char* expected_trailing_comments) { - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, - expected_leading_comments, expected_trailing_comments); - } - - bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, const string& field_name) { - return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); - } - - bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, const string& field_name, - int index) { - return HasSpan(start_marker, end_marker, descriptor_proto, - field_name, index, NULL, NULL); - } - - bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, - const string& field_name, int index, - const char* expected_leading_comments, - const char* expected_trailing_comments) { - const FieldDescriptor* field = - descriptor_proto.GetDescriptor()->FindFieldByName(field_name); - if (field == NULL) { - ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() - << " has no such field: " << field_name; - return false; - } - - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, field, index, - expected_leading_comments, expected_trailing_comments); - } - - bool HasSpan(const Message& descriptor_proto) { - return HasSpanWithComment( - '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); - } - - bool HasSpan(const Message& descriptor_proto, const string& field_name) { - return HasSpan('\0', '\0', descriptor_proto, field_name, -1); - } - - bool HasSpan(const Message& descriptor_proto, const string& field_name, - int index) { - return HasSpan('\0', '\0', descriptor_proto, field_name, index); - } - - bool HasSpanWithComment(char start_marker, char end_marker, - const Message& descriptor_proto, - const FieldDescriptor* field, int index, - const char* expected_leading_comments, - const char* expected_trailing_comments) { - pair<SpanMap::iterator, SpanMap::iterator> range = - spans_.equal_range(SpanKey(descriptor_proto, field, index)); - - if (start_marker == '\0') { - if (range.first == range.second) { - return false; - } else { - spans_.erase(range.first); - return true; - } - } else { - pair<int, int> start_pos = FindOrDie(markers_, start_marker); - pair<int, int> end_pos = FindOrDie(markers_, end_marker); - - RepeatedField<int> expected_span; - expected_span.Add(start_pos.first); - expected_span.Add(start_pos.second); - if (end_pos.first != start_pos.first) { - expected_span.Add(end_pos.first); - } - expected_span.Add(end_pos.second); - - for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) { - if (CompareSpans(expected_span, iter->second->span())) { - if (expected_leading_comments == NULL) { - EXPECT_FALSE(iter->second->has_leading_comments()); - } else { - EXPECT_TRUE(iter->second->has_leading_comments()); - EXPECT_EQ(expected_leading_comments, - iter->second->leading_comments()); - } - if (expected_trailing_comments == NULL) { - EXPECT_FALSE(iter->second->has_trailing_comments()); - } else { - EXPECT_TRUE(iter->second->has_trailing_comments()); - EXPECT_EQ(expected_trailing_comments, - iter->second->trailing_comments()); - } - - spans_.erase(iter); - return true; - } - } - - return false; - } - } - - private: - struct SpanKey { - const Message* descriptor_proto; - const FieldDescriptor* field; - int index; - - inline SpanKey() {} - inline SpanKey(const Message& descriptor_proto_param, - const FieldDescriptor* field_param, - int index_param) - : descriptor_proto(&descriptor_proto_param), field(field_param), - index(index_param) {} - - inline bool operator<(const SpanKey& other) const { - if (descriptor_proto < other.descriptor_proto) return true; - if (descriptor_proto > other.descriptor_proto) return false; - if (field < other.field) return true; - if (field > other.field) return false; - return index < other.index; - } - }; - - typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap; - SpanMap spans_; - map<char, pair<int, int> > markers_; - string text_without_markers_; - - void ExtractMarkers(const char* text) { - markers_.clear(); - text_without_markers_.clear(); - int line = 0; - int column = 0; - while (*text != '\0') { - if (*text == '$') { - ++text; - GOOGLE_CHECK_NE('\0', *text); - if (*text == '$') { - text_without_markers_ += '$'; - ++column; - } else { - markers_[*text] = make_pair(line, column); - ++text; - GOOGLE_CHECK_EQ('$', *text); - } - } else if (*text == '\n') { - ++line; - column = 0; - text_without_markers_ += *text; - } else { - text_without_markers_ += *text; - ++column; - } - ++text; - } - } -}; - -TEST_F(SourceInfoTest, BasicFileDecls) { - EXPECT_TRUE(Parse( - "$a$syntax = \"proto2\";\n" - "package $b$foo.bar$c$;\n" - "import $d$\"baz.proto\"$e$;\n" - "import $f$\"qux.proto\"$g$;$h$\n" - "\n" - "// comment ignored\n")); - - EXPECT_TRUE(HasSpan('a', 'h', file_)); - EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); - EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); - EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); -} - -TEST_F(SourceInfoTest, Messages) { - EXPECT_TRUE(Parse( - "$a$message $b$Foo$c$ {}$d$\n" - "$e$message $f$Bar$g$ {}$h$\n")); - - EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); - EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1))); - EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); -} - -TEST_F(SourceInfoTest, Fields) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n" - " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n" - "}\n")); - - const FieldDescriptorProto& field1 = file_.message_type(0).field(0); - const FieldDescriptorProto& field2 = file_.message_type(0).field(1); - - EXPECT_TRUE(HasSpan('a', 'i', field1)); - EXPECT_TRUE(HasSpan('a', 'b', field1, "label")); - EXPECT_TRUE(HasSpan('c', 'd', field1, "type")); - EXPECT_TRUE(HasSpan('e', 'f', field1, "name")); - EXPECT_TRUE(HasSpan('g', 'h', field1, "number")); - - EXPECT_TRUE(HasSpan('j', 'r', field2)); - EXPECT_TRUE(HasSpan('j', 'k', field2, "label")); - EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name")); - EXPECT_TRUE(HasSpan('n', 'o', field2, "name")); - EXPECT_TRUE(HasSpan('p', 'q', field2, "number")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); -} - -TEST_F(SourceInfoTest, Extensions) { - EXPECT_TRUE(Parse( - "$a$extend $b$Foo$c$ {\n" - " $d$optional$e$ int32 bar = 1;$f$\n" - " $g$repeated$h$ X.Y baz = 2;$i$\n" - "}$j$\n" - "$k$extend $l$Bar$m$ {\n" - " $n$optional int32 qux = 1;$o$\n" - "}$p$\n")); - - const FieldDescriptorProto& field1 = file_.extension(0); - const FieldDescriptorProto& field2 = file_.extension(1); - const FieldDescriptorProto& field3 = file_.extension(2); - - EXPECT_TRUE(HasSpan('a', 'j', file_, "extension")); - EXPECT_TRUE(HasSpan('k', 'p', file_, "extension")); - - EXPECT_TRUE(HasSpan('d', 'f', field1)); - EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); - EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); - - EXPECT_TRUE(HasSpan('g', 'i', field2)); - EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); - EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); - - EXPECT_TRUE(HasSpan('n', 'o', field3)); - EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(field1, "type")); - EXPECT_TRUE(HasSpan(field1, "name")); - EXPECT_TRUE(HasSpan(field1, "number")); - EXPECT_TRUE(HasSpan(field2, "type_name")); - EXPECT_TRUE(HasSpan(field2, "name")); - EXPECT_TRUE(HasSpan(field2, "number")); - EXPECT_TRUE(HasSpan(field3, "label")); - EXPECT_TRUE(HasSpan(field3, "type")); - EXPECT_TRUE(HasSpan(field3, "name")); - EXPECT_TRUE(HasSpan(field3, "number")); -} - -TEST_F(SourceInfoTest, NestedExtensions) { - EXPECT_TRUE(Parse( - "message Message {\n" - " $a$extend $b$Foo$c$ {\n" - " $d$optional$e$ int32 bar = 1;$f$\n" - " $g$repeated$h$ X.Y baz = 2;$i$\n" - " }$j$\n" - " $k$extend $l$Bar$m$ {\n" - " $n$optional int32 qux = 1;$o$\n" - " }$p$\n" - "}\n")); - - const FieldDescriptorProto& field1 = file_.message_type(0).extension(0); - const FieldDescriptorProto& field2 = file_.message_type(0).extension(1); - const FieldDescriptorProto& field3 = file_.message_type(0).extension(2); - - EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension")); - EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension")); - - EXPECT_TRUE(HasSpan('d', 'f', field1)); - EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); - EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); - - EXPECT_TRUE(HasSpan('g', 'i', field2)); - EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); - EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); - - EXPECT_TRUE(HasSpan('n', 'o', field3)); - EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan(field1, "type")); - EXPECT_TRUE(HasSpan(field1, "name")); - EXPECT_TRUE(HasSpan(field1, "number")); - EXPECT_TRUE(HasSpan(field2, "type_name")); - EXPECT_TRUE(HasSpan(field2, "name")); - EXPECT_TRUE(HasSpan(field2, "number")); - EXPECT_TRUE(HasSpan(field3, "label")); - EXPECT_TRUE(HasSpan(field3, "type")); - EXPECT_TRUE(HasSpan(field3, "name")); - EXPECT_TRUE(HasSpan(field3, "number")); -} - -TEST_F(SourceInfoTest, ExtensionRanges) { - EXPECT_TRUE(Parse( - "message Message {\n" - " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" - " $i$extensions $j$8$k$ to $l$max$m$;$n$\n" - "}\n")); - - const DescriptorProto::ExtensionRange& range1 = - file_.message_type(0).extension_range(0); - const DescriptorProto::ExtensionRange& range2 = - file_.message_type(0).extension_range(1); - const DescriptorProto::ExtensionRange& range3 = - file_.message_type(0).extension_range(2); - - EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range")); - EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range")); - - EXPECT_TRUE(HasSpan('b', 'e', range1)); - EXPECT_TRUE(HasSpan('b', 'c', range1, "start")); - EXPECT_TRUE(HasSpan('d', 'e', range1, "end")); - - EXPECT_TRUE(HasSpan('f', 'g', range2)); - EXPECT_TRUE(HasSpan('f', 'g', range2, "start")); - EXPECT_TRUE(HasSpan('f', 'g', range2, "end")); - - EXPECT_TRUE(HasSpan('j', 'm', range3)); - EXPECT_TRUE(HasSpan('j', 'k', range3, "start")); - EXPECT_TRUE(HasSpan('l', 'm', range3, "end")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); -} - -TEST_F(SourceInfoTest, Oneofs) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$oneof $c$foo$d$ {\n" - " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" - " }$r$\n" - "}\n")); - - const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0); - const FieldDescriptorProto& field = file_.message_type(0).field(0); - - EXPECT_TRUE(HasSpan('a', 'r', oneof_decl)); - EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name")); - - EXPECT_TRUE(HasSpan('e', 'k', field)); - EXPECT_TRUE(HasSpan('e', 'f', field, "type")); - EXPECT_TRUE(HasSpan('g', 'h', field, "name")); - EXPECT_TRUE(HasSpan('i', 'j', field, "number")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); -} - -TEST_F(SourceInfoTest, NestedMessages) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$message $b$Bar$c$ {\n" - " $d$message $e$Baz$f$ {}$g$\n" - " }$h$\n" - " $i$message $j$Qux$k$ {}$l$\n" - "}\n")); - - const DescriptorProto& bar = file_.message_type(0).nested_type(0); - const DescriptorProto& baz = bar.nested_type(0); - const DescriptorProto& qux = file_.message_type(0).nested_type(1); - - EXPECT_TRUE(HasSpan('a', 'h', bar)); - EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); - EXPECT_TRUE(HasSpan('d', 'g', baz)); - EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); - EXPECT_TRUE(HasSpan('i', 'l', qux)); - EXPECT_TRUE(HasSpan('j', 'k', qux, "name")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); -} - -TEST_F(SourceInfoTest, Groups) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " message Bar {}\n" - " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n" - " $i$message Qux {}$j$\n" - " }$k$\n" - "}\n")); - - const DescriptorProto& bar = file_.message_type(0).nested_type(0); - const DescriptorProto& baz = file_.message_type(0).nested_type(1); - const DescriptorProto& qux = baz.nested_type(0); - const FieldDescriptorProto& field = file_.message_type(0).field(0); - - EXPECT_TRUE(HasSpan('a', 'k', field)); - EXPECT_TRUE(HasSpan('a', 'b', field, "label")); - EXPECT_TRUE(HasSpan('c', 'd', field, "type")); - EXPECT_TRUE(HasSpan('e', 'f', field, "name")); - EXPECT_TRUE(HasSpan('e', 'f', field, "type_name")); - EXPECT_TRUE(HasSpan('g', 'h', field, "number")); - - EXPECT_TRUE(HasSpan('a', 'k', baz)); - EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); - EXPECT_TRUE(HasSpan('i', 'j', qux)); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan(bar)); - EXPECT_TRUE(HasSpan(bar, "name")); - EXPECT_TRUE(HasSpan(qux, "name")); -} - -TEST_F(SourceInfoTest, Enums) { - EXPECT_TRUE(Parse( - "$a$enum $b$Foo$c$ {}$d$\n" - "$e$enum $f$Bar$g$ {}$h$\n")); - - EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0))); - EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name")); - EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1))); - EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); -} - -TEST_F(SourceInfoTest, EnumValues) { - EXPECT_TRUE(Parse( - "enum Foo {\n" - " $a$BAR$b$ = $c$1$d$;$e$\n" - " $f$BAZ$g$ = $h$2$i$;$j$\n" - "}")); - - const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0); - const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1); - - EXPECT_TRUE(HasSpan('a', 'e', bar)); - EXPECT_TRUE(HasSpan('a', 'b', bar, "name")); - EXPECT_TRUE(HasSpan('c', 'd', bar, "number")); - EXPECT_TRUE(HasSpan('f', 'j', baz)); - EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); - EXPECT_TRUE(HasSpan('h', 'i', baz, "number")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.enum_type(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); -} - -TEST_F(SourceInfoTest, NestedEnums) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$enum $b$Bar$c$ {}$d$\n" - " $e$enum $f$Baz$g$ {}$h$\n" - "}\n")); - - const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0); - const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1); - - EXPECT_TRUE(HasSpan('a', 'd', bar)); - EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); - EXPECT_TRUE(HasSpan('e', 'h', baz)); - EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); -} - -TEST_F(SourceInfoTest, Services) { - EXPECT_TRUE(Parse( - "$a$service $b$Foo$c$ {}$d$\n" - "$e$service $f$Bar$g$ {}$h$\n")); - - EXPECT_TRUE(HasSpan('a', 'd', file_.service(0))); - EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name")); - EXPECT_TRUE(HasSpan('e', 'h', file_.service(1))); - EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); -} - -TEST_F(SourceInfoTest, MethodsAndStreams) { - EXPECT_TRUE(Parse( - "service Foo {\n" - " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$" - " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$" - "}")); - - const MethodDescriptorProto& bar = file_.service(0).method(0); - const MethodDescriptorProto& baz = file_.service(0).method(1); - - EXPECT_TRUE(HasSpan('a', 'h', bar)); - EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); - EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type")); - EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type")); - - EXPECT_TRUE(HasSpan('i', 'p', baz)); - EXPECT_TRUE(HasSpan('j', 'k', baz, "name")); - EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type")); - EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.service(0))); - EXPECT_TRUE(HasSpan(file_.service(0), "name")); -} - - -TEST_F(SourceInfoTest, Options) { - EXPECT_TRUE(Parse( - "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " - "$h$123$i$;$j$\n" - "$k$option qux = $l$-123$m$;$n$\n" - "$o$option corge = $p$abc$q$;$r$\n" - "$s$option grault = $t$'blah'$u$;$v$\n" - "$w$option garply = $x${ yadda yadda }$y$;$z$\n" - "$0$option waldo = $1$123.0$2$;$3$\n" - )); - - const UninterpretedOption& option1 = file_.options().uninterpreted_option(0); - const UninterpretedOption& option2 = file_.options().uninterpreted_option(1); - const UninterpretedOption& option3 = file_.options().uninterpreted_option(2); - const UninterpretedOption& option4 = file_.options().uninterpreted_option(3); - const UninterpretedOption& option5 = file_.options().uninterpreted_option(4); - const UninterpretedOption& option6 = file_.options().uninterpreted_option(5); - - EXPECT_TRUE(HasSpan('a', 'j', file_.options())); - EXPECT_TRUE(HasSpan('a', 'j', option1)); - EXPECT_TRUE(HasSpan('b', 'g', option1, "name")); - EXPECT_TRUE(HasSpan('b', 'c', option1.name(0))); - EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part")); - EXPECT_TRUE(HasSpan('d', 'g', option1.name(1))); - EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part")); - EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value")); - - EXPECT_TRUE(HasSpan('k', 'n', file_.options())); - EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value")); - - EXPECT_TRUE(HasSpan('o', 'r', file_.options())); - EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value")); - - EXPECT_TRUE(HasSpan('s', 'v', file_.options())); - EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value")); - - EXPECT_TRUE(HasSpan('w', 'z', file_.options())); - EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value")); - - EXPECT_TRUE(HasSpan('0', '3', file_.options())); - EXPECT_TRUE(HasSpan('1', '2', option6, "double_value")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(option2)); - EXPECT_TRUE(HasSpan(option3)); - EXPECT_TRUE(HasSpan(option4)); - EXPECT_TRUE(HasSpan(option5)); - EXPECT_TRUE(HasSpan(option6)); - EXPECT_TRUE(HasSpan(option2, "name")); - EXPECT_TRUE(HasSpan(option3, "name")); - EXPECT_TRUE(HasSpan(option4, "name")); - EXPECT_TRUE(HasSpan(option5, "name")); - EXPECT_TRUE(HasSpan(option6, "name")); - EXPECT_TRUE(HasSpan(option2.name(0))); - EXPECT_TRUE(HasSpan(option3.name(0))); - EXPECT_TRUE(HasSpan(option4.name(0))); - EXPECT_TRUE(HasSpan(option5.name(0))); - EXPECT_TRUE(HasSpan(option6.name(0))); - EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option3.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option4.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option5.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option6.name(0), "name_part")); -} - -TEST_F(SourceInfoTest, ScopedOptions) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$option mopt = 1;$b$\n" - "}\n" - "enum Bar {\n" - " $c$option eopt = 1;$d$\n" - "}\n" - "service Baz {\n" - " $e$option sopt = 1;$f$\n" - " rpc M(X) returns(Y) {\n" - " $g$option mopt = 1;$h$\n" - " }\n" - "}\n")); - - EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); - EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); - EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options())); - EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options())); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0), "positive_int_value")); - EXPECT_TRUE(HasSpan(file_.enum_type(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0), "positive_int_value")); - EXPECT_TRUE(HasSpan(file_.service(0))); - EXPECT_TRUE(HasSpan(file_.service(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0), "positive_int_value")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0), "positive_int_value")); -} - -TEST_F(SourceInfoTest, FieldOptions) { - // The actual "name = value" pairs are parsed by the same code as for - // top-level options so we won't re-test that -- just make sure that the - // syntax used for field options is understood. - EXPECT_TRUE(Parse( - "message Foo {" - " optional int32 bar = 1 " - "$a$[default=$b$123$c$,$d$opt1=123$e$," - "$f$opt2='hi'$g$]$h$;" - "}\n" - )); - - const FieldDescriptorProto& field = file_.message_type(0).field(0); - const UninterpretedOption& option1 = field.options().uninterpreted_option(0); - const UninterpretedOption& option2 = field.options().uninterpreted_option(1); - - EXPECT_TRUE(HasSpan('a', 'h', field.options())); - EXPECT_TRUE(HasSpan('b', 'c', field, "default_value")); - EXPECT_TRUE(HasSpan('d', 'e', option1)); - EXPECT_TRUE(HasSpan('f', 'g', option2)); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.message_type(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan(field)); - EXPECT_TRUE(HasSpan(field, "label")); - EXPECT_TRUE(HasSpan(field, "type")); - EXPECT_TRUE(HasSpan(field, "name")); - EXPECT_TRUE(HasSpan(field, "number")); - EXPECT_TRUE(HasSpan(option1, "name")); - EXPECT_TRUE(HasSpan(option2, "name")); - EXPECT_TRUE(HasSpan(option1.name(0))); - EXPECT_TRUE(HasSpan(option2.name(0))); - EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option1, "positive_int_value")); - EXPECT_TRUE(HasSpan(option2, "string_value")); -} - -TEST_F(SourceInfoTest, EnumValueOptions) { - // The actual "name = value" pairs are parsed by the same code as for - // top-level options so we won't re-test that -- just make sure that the - // syntax used for enum options is understood. - EXPECT_TRUE(Parse( - "enum Foo {" - " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;" - "}\n" - )); - - const EnumValueDescriptorProto& value = file_.enum_type(0).value(0); - const UninterpretedOption& option1 = value.options().uninterpreted_option(0); - const UninterpretedOption& option2 = value.options().uninterpreted_option(1); - - EXPECT_TRUE(HasSpan('a', 'f', value.options())); - EXPECT_TRUE(HasSpan('b', 'c', option1)); - EXPECT_TRUE(HasSpan('d', 'e', option2)); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(file_.enum_type(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); - EXPECT_TRUE(HasSpan(value)); - EXPECT_TRUE(HasSpan(value, "name")); - EXPECT_TRUE(HasSpan(value, "number")); - EXPECT_TRUE(HasSpan(option1, "name")); - EXPECT_TRUE(HasSpan(option2, "name")); - EXPECT_TRUE(HasSpan(option1.name(0))); - EXPECT_TRUE(HasSpan(option2.name(0))); - EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); - EXPECT_TRUE(HasSpan(option1, "positive_int_value")); - EXPECT_TRUE(HasSpan(option2, "string_value")); -} - -TEST_F(SourceInfoTest, DocComments) { - EXPECT_TRUE(Parse( - "// Foo leading\n" - "// line 2\n" - "$a$message Foo {\n" - " // Foo trailing\n" - " // line 2\n" - "\n" - " // ignored\n" - "\n" - " // bar leading\n" - " $b$optional int32 bar = 1;$c$\n" - " // bar trailing\n" - "}$d$\n" - "// ignored\n" - )); - - const DescriptorProto& foo = file_.message_type(0); - const FieldDescriptorProto& bar = foo.field(0); - - EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, - " Foo leading\n line 2\n", - " Foo trailing\n line 2\n")); - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(foo, "name")); - EXPECT_TRUE(HasSpan(bar, "label")); - EXPECT_TRUE(HasSpan(bar, "type")); - EXPECT_TRUE(HasSpan(bar, "name")); - EXPECT_TRUE(HasSpan(bar, "number")); -} - -TEST_F(SourceInfoTest, DocComments2) { - EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" - "// Foo leading\n" - "// line 2\n" - "$a$message Foo {\n" - " /* Foo trailing\n" - " * line 2 */\n" - " // ignored\n" - " /* bar leading\n" - " */" - " $b$optional int32 bar = 1;$c$ // bar trailing\n" - " // ignored\n" - "}$d$\n" - "// ignored\n" - "\n" - "// option leading\n" - "$e$option baz = 123;$f$\n" - "// option trailing\n" - )); - - const DescriptorProto& foo = file_.message_type(0); - const FieldDescriptorProto& bar = foo.field(0); - const UninterpretedOption& baz = file_.options().uninterpreted_option(0); - - EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, - " Foo leading\n line 2\n", - " Foo trailing\n line 2 ")); - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n")); - EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, - " option leading\n", - " option trailing\n")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(foo, "name")); - EXPECT_TRUE(HasSpan(bar, "label")); - EXPECT_TRUE(HasSpan(bar, "type")); - EXPECT_TRUE(HasSpan(bar, "name")); - EXPECT_TRUE(HasSpan(bar, "number")); - EXPECT_TRUE(HasSpan(file_.options())); - EXPECT_TRUE(HasSpan(baz, "name")); - EXPECT_TRUE(HasSpan(baz.name(0))); - EXPECT_TRUE(HasSpan(baz.name(0), "name_part")); - EXPECT_TRUE(HasSpan(baz, "positive_int_value")); -} - -TEST_F(SourceInfoTest, DocComments3) { - EXPECT_TRUE(Parse( - "$a$message Foo {\n" - " // bar leading\n" - " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n" - " // bar trailing\n" - "}$d$\n" - "// ignored\n" - )); - - const DescriptorProto& foo = file_.message_type(0); - const FieldDescriptorProto& bar = foo.field(0); - - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(foo)); - EXPECT_TRUE(HasSpan(foo, "name")); - EXPECT_TRUE(HasSpan(bar, "label")); - EXPECT_TRUE(HasSpan(bar, "type")); - EXPECT_TRUE(HasSpan(bar, "name")); - EXPECT_TRUE(HasSpan(bar, "number")); - EXPECT_TRUE(HasSpan(bar.options())); - EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan( - bar.options().uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan( - bar.options().uninterpreted_option(0), "aggregate_value")); -} - -TEST_F(SourceInfoTest, DocCommentsOneof) { - EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" - "// Foo leading\n" - "$a$message Foo {\n" - " /* Foo trailing\n" - " */\n" - " // ignored\n" - " /* bar leading\n" - " * line 2 */\n" - " $b$oneof bar {\n" - " /* bar trailing\n" - " * line 2 */\n" - " // ignored\n" - " /* bar_int leading\n" - " */\n" - " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" - " // ignored\n" - " }$e$\n" - "}$f$\n")); - - const DescriptorProto& foo = file_.message_type(0); - const OneofDescriptorProto& bar = foo.oneof_decl(0); - const FieldDescriptorProto& bar_int = foo.field(0); - - EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, - " Foo leading\n", - " Foo trailing\n")); - EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, - " bar leading\n line 2 ", - " bar trailing\n line 2 ")); - EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, - " bar_int leading\n", - " bar_int trailing\n")); - - // Ignore these. - EXPECT_TRUE(HasSpan(file_)); - EXPECT_TRUE(HasSpan(foo, "name")); - EXPECT_TRUE(HasSpan(bar, "name")); - EXPECT_TRUE(HasSpan(bar_int, "type")); - EXPECT_TRUE(HasSpan(bar_int, "name")); - EXPECT_TRUE(HasSpan(bar_int, "number")); -} - // =================================================================== } // anonymous namespace diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 9011a6b..a4aedaf 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -59,15 +59,13 @@ namespace google { namespace protobuf { namespace compiler { -class GeneratorResponseContext : public GeneratorContext { +class GeneratorResponseOutputDirectory : public OutputDirectory { public: - GeneratorResponseContext(CodeGeneratorResponse* response, - const vector<const FileDescriptor*>& parsed_files) - : response_(response), - parsed_files_(parsed_files) {} - virtual ~GeneratorResponseContext() {} + GeneratorResponseOutputDirectory(CodeGeneratorResponse* response) + : response_(response) {} + virtual ~GeneratorResponseOutputDirectory() {} - // implements GeneratorContext -------------------------------------- + // implements OutputDirectory -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { CodeGeneratorResponse::File* file = response_->add_file(); @@ -83,13 +81,8 @@ class GeneratorResponseContext : public GeneratorContext { return new io::StringOutputStream(file->mutable_content()); } - void ListParsedFiles(vector<const FileDescriptor*>* output) { - *output = parsed_files_; - } - private: CodeGeneratorResponse* response_; - const vector<const FileDescriptor*>& parsed_files_; }; int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { @@ -119,26 +112,22 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { } } - vector<const FileDescriptor*> parsed_files; + CodeGeneratorResponse response; + GeneratorResponseOutputDirectory output_directory(&response); + for (int i = 0; i < request.file_to_generate_size(); i++) { - parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); - if (parsed_files.back() == NULL) { + const FileDescriptor* file = + pool.FindFileByName(request.file_to_generate(i)); + if (file == NULL) { cerr << argv[0] << ": protoc asked plugin to generate a file but " "did not provide a descriptor for the file: " << request.file_to_generate(i) << endl; return 1; } - } - - CodeGeneratorResponse response; - GeneratorResponseContext context(&response, parsed_files); - - for (int i = 0; i < parsed_files.size(); i++) { - const FileDescriptor* file = parsed_files[i]; string error; bool succeeded = generator->Generate( - file, request.parameter(), &context, &error); + file, request.parameter(), &output_directory, &error); if (!succeeded && error.empty()) { error = "Code generator returned false but provided no error " diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h index 679f9bd..7c40333 100644 --- a/src/google/protobuf/compiler/plugin.h +++ b/src/google/protobuf/compiler/plugin.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -56,6 +56,7 @@ #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ #include <google/protobuf/stubs/common.h> + namespace google { namespace protobuf { namespace compiler { diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index b5cd01b..6b0dd55 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -1,17 +1,11 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/compiler/plugin.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include "google/protobuf/compiler/plugin.pb.h" - -#include <algorithm> - -#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/once.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/wire_format_lite_inl.h> #include <google/protobuf/descriptor.h> -#include <google/protobuf/generated_message_reflection.h> #include <google/protobuf/reflection_ops.h> #include <google/protobuf/wire_format.h> // @@protoc_insertion_point(includes) @@ -139,9 +133,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003(" "\01324.google.protobuf.compiler.CodeGenerat" "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n" - "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB" - ",\n\034com.google.protobuf.compilerB\014PluginP" - "rotos", 445); + "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t", 399); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest(); @@ -160,8 +152,10 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto } } static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_; + // =================================================================== +const ::std::string CodeGeneratorRequest::_default_parameter_; #ifndef _MSC_VER const int CodeGeneratorRequest::kFileToGenerateFieldNumber; const int CodeGeneratorRequest::kParameterFieldNumber; @@ -171,7 +165,6 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber; CodeGeneratorRequest::CodeGeneratorRequest() : ::google::protobuf::Message() { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::InitAsDefaultInstance() { @@ -181,23 +174,20 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); - // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::SharedCtor() { - ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + parameter_ = const_cast< ::std::string*>(&_default_parameter_); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorRequest::~CodeGeneratorRequest() { - // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest) SharedDtor(); } void CodeGeneratorRequest::SharedDtor() { - if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (parameter_ != &_default_parameter_) { delete parameter_; } if (this != default_instance_) { @@ -215,8 +205,7 @@ const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() { } const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; } CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL; @@ -226,9 +215,11 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const { } void CodeGeneratorRequest::Clear() { - if (has_parameter()) { - if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - parameter_->clear(); + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { + if (_has_bit(1)) { + if (parameter_ != &_default_parameter_) { + parameter_->clear(); + } } } file_to_generate_.Clear(); @@ -239,70 +230,65 @@ void CodeGeneratorRequest::Clear() { bool CodeGeneratorRequest::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); - tag = p.first; - if (!p.second) goto handle_unusual; + while ((tag = input->ReadTag()) != 0) { switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated string file_to_generate = 1; case 1: { - if (tag == 10) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_file_to_generate: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_file_to_generate())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->file_to_generate(this->file_to_generate_size() - 1).data(), - this->file_to_generate(this->file_to_generate_size() - 1).length(), - ::google::protobuf::internal::WireFormat::PARSE, - "file_to_generate"); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->file_to_generate(0).data(), this->file_to_generate(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(10)) goto parse_file_to_generate; if (input->ExpectTag(18)) goto parse_parameter; break; } - + // optional string parameter = 2; case 2: { - if (tag == 18) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_parameter: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_parameter())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "parameter"); + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(122)) goto parse_proto_file; break; } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; case 15: { - if (tag == 122) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_proto_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_proto_file())); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(122)) goto parse_proto_file; - if (input->ExpectAtEnd()) goto success; + if (input->ExpectAtEnd()) return true; break; } - + default: { - handle_unusual: - if (tag == 0 || - ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - goto success; + return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -310,93 +296,80 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( } } } -success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest) return true; -failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest) - return false; #undef DO_ } void CodeGeneratorRequest::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "file_to_generate"); + ::google::protobuf::internal::WireFormat::SERIALIZE); ::google::protobuf::internal::WireFormatLite::WriteString( 1, this->file_to_generate(i), output); } - + // optional string parameter = 2; - if (has_parameter()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(1)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "parameter"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( 2, this->parameter(), output); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (int i = 0; i < this->proto_file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 15, this->proto_file(i), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest) } ::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "file_to_generate"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite:: WriteStringToArray(1, this->file_to_generate(i), target); } - + // optional string parameter = 2; - if (has_parameter()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(1)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "parameter"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->parameter(), target); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (int i = 0; i < this->proto_file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 15, this->proto_file(i), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) return target; } int CodeGeneratorRequest::ByteSize() const { int total_size = 0; - + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { // optional string parameter = 2; if (has_parameter()) { @@ -404,7 +377,7 @@ int CodeGeneratorRequest::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->parameter()); } - + } // repeated string file_to_generate = 1; total_size += 1 * this->file_to_generate_size(); @@ -412,7 +385,7 @@ int CodeGeneratorRequest::ByteSize() const { total_size += ::google::protobuf::internal::WireFormatLite::StringSize( this->file_to_generate(i)); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; total_size += 1 * this->proto_file_size(); for (int i = 0; i < this->proto_file_size(); i++) { @@ -420,7 +393,7 @@ int CodeGeneratorRequest::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->proto_file(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -449,7 +422,7 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (from.has_parameter()) { + if (from._has_bit(1)) { set_parameter(from.parameter()); } } @@ -469,8 +442,10 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { } bool CodeGeneratorRequest::IsInitialized() const { - - if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false; + + for (int i = 0; i < proto_file_size(); i++) { + if (!this->proto_file(i).IsInitialized()) return false; + } return true; } @@ -496,6 +471,9 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { // =================================================================== +const ::std::string CodeGeneratorResponse_File::_default_name_; +const ::std::string CodeGeneratorResponse_File::_default_insertion_point_; +const ::std::string CodeGeneratorResponse_File::_default_content_; #ifndef _MSC_VER const int CodeGeneratorResponse_File::kNameFieldNumber; const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; @@ -505,7 +483,6 @@ const int CodeGeneratorResponse_File::kContentFieldNumber; CodeGeneratorResponse_File::CodeGeneratorResponse_File() : ::google::protobuf::Message() { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::InitAsDefaultInstance() { @@ -515,31 +492,28 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); - // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::SharedCtor() { - ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + name_ = const_cast< ::std::string*>(&_default_name_); + insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_); + content_ = const_cast< ::std::string*>(&_default_content_); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { - // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File) SharedDtor(); } void CodeGeneratorResponse_File::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (name_ != &_default_name_) { delete name_; } - if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (insertion_point_ != &_default_insertion_point_) { delete insertion_point_; } - if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (content_ != &_default_content_) { delete content_; } if (this != default_instance_) { @@ -557,8 +531,7 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() { } const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; } CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL; @@ -568,19 +541,19 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const { } void CodeGeneratorResponse_File::Clear() { - if (_has_bits_[0 / 32] & 7) { - if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bit(0)) { + if (name_ != &_default_name_) { name_->clear(); } } - if (has_insertion_point()) { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (_has_bit(1)) { + if (insertion_point_ != &_default_insertion_point_) { insertion_point_->clear(); } } - if (has_content()) { - if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (_has_bit(2)) { + if (content_ != &_default_content_) { content_->clear(); } } @@ -591,70 +564,65 @@ void CodeGeneratorResponse_File::Clear() { bool CodeGeneratorResponse_File::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); - tag = p.first; - if (!p.second) goto handle_unusual; + while ((tag = input->ReadTag()) != 0) { switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (tag == 10) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "name"); + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(18)) goto parse_insertion_point; break; } - + // optional string insertion_point = 2; case 2: { - if (tag == 18) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_insertion_point: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_insertion_point())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "insertion_point"); + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(122)) goto parse_content; break; } - + // optional string content = 15; case 15: { - if (tag == 122) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_content: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_content())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "content"); + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } - if (input->ExpectAtEnd()) goto success; + if (input->ExpectAtEnd()) return true; break; } - + default: { - handle_unusual: - if (tag == 0 || - ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - goto success; + return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -662,102 +630,87 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( } } } -success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File) return true; -failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File) - return false; #undef DO_ } void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; - if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(0)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( 1, this->name(), output); } - + // optional string insertion_point = 2; - if (has_insertion_point()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(1)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "insertion_point"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( 2, this->insertion_point(), output); } - + // optional string content = 15; - if (has_content()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(2)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "content"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( 15, this->content(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File) } ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; - if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(0)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "name"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional string insertion_point = 2; - if (has_insertion_point()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(1)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "insertion_point"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->insertion_point(), target); } - + // optional string content = 15; - if (has_content()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(2)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "content"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 15, this->content(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) return target; } int CodeGeneratorResponse_File::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -765,21 +718,21 @@ int CodeGeneratorResponse_File::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional string insertion_point = 2; if (has_insertion_point()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->insertion_point()); } - + // optional string content = 15; if (has_content()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->content()); } - + } if (!unknown_fields().empty()) { total_size += @@ -807,13 +760,13 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from.has_name()) { + if (from._has_bit(0)) { set_name(from.name()); } - if (from.has_insertion_point()) { + if (from._has_bit(1)) { set_insertion_point(from.insertion_point()); } - if (from.has_content()) { + if (from._has_bit(2)) { set_content(from.content()); } } @@ -833,7 +786,7 @@ void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from } bool CodeGeneratorResponse_File::IsInitialized() const { - + return true; } @@ -859,6 +812,7 @@ void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { // ------------------------------------------------------------------- +const ::std::string CodeGeneratorResponse::_default_error_; #ifndef _MSC_VER const int CodeGeneratorResponse::kErrorFieldNumber; const int CodeGeneratorResponse::kFileFieldNumber; @@ -867,7 +821,6 @@ const int CodeGeneratorResponse::kFileFieldNumber; CodeGeneratorResponse::CodeGeneratorResponse() : ::google::protobuf::Message() { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::InitAsDefaultInstance() { @@ -877,23 +830,20 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); - // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::SharedCtor() { - ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + error_ = const_cast< ::std::string*>(&_default_error_); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse::~CodeGeneratorResponse() { - // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse) SharedDtor(); } void CodeGeneratorResponse::SharedDtor() { - if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (error_ != &_default_error_) { delete error_; } if (this != default_instance_) { @@ -911,8 +861,7 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() { } const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; } CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL; @@ -922,9 +871,11 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const { } void CodeGeneratorResponse::Clear() { - if (has_error()) { - if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - error_->clear(); + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bit(0)) { + if (error_ != &_default_error_) { + error_->clear(); + } } } file_.Clear(); @@ -934,50 +885,46 @@ void CodeGeneratorResponse::Clear() { bool CodeGeneratorResponse::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); - tag = p.first; - if (!p.second) goto handle_unusual; + while ((tag = input->ReadTag()) != 0) { switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string error = 1; case 1: { - if (tag == 10) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_error())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "error"); + ::google::protobuf::internal::WireFormat::PARSE); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(122)) goto parse_file; break; } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; case 15: { - if (tag == 122) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_file())); } else { - goto handle_unusual; + goto handle_uninterpreted; } if (input->ExpectTag(122)) goto parse_file; - if (input->ExpectAtEnd()) goto success; + if (input->ExpectAtEnd()) return true; break; } - + default: { - handle_unusual: - if (tag == 0 || - ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - goto success; + return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -985,73 +932,62 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( } } } -success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse) return true; -failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse) - return false; #undef DO_ } void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; - if (has_error()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(0)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "error"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( 1, this->error(), output); } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; for (int i = 0; i < this->file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 15, this->file(i), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse) } ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; - if (has_error()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + if (_has_bit(0)) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "error"); + ::google::protobuf::internal::WireFormat::SERIALIZE); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->error(), target); } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; for (int i = 0; i < this->file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 15, this->file(i), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) return target; } int CodeGeneratorResponse::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string error = 1; if (has_error()) { @@ -1059,7 +995,7 @@ int CodeGeneratorResponse::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->error()); } - + } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; total_size += 1 * this->file_size(); @@ -1068,7 +1004,7 @@ int CodeGeneratorResponse::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->file(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -1096,7 +1032,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { GOOGLE_CHECK_NE(&from, this); file_.MergeFrom(from.file_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from.has_error()) { + if (from._has_bit(0)) { set_error(from.error()); } } @@ -1116,7 +1052,7 @@ void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) { } bool CodeGeneratorResponse::IsInitialized() const { - + return true; } diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 65634da..f8f8053 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -8,22 +8,21 @@ #include <google/protobuf/stubs/common.h> -#if GOOGLE_PROTOBUF_VERSION < 2006000 +#if GOOGLE_PROTOBUF_VERSION < 2003000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif #include <google/protobuf/generated_message_util.h> -#include <google/protobuf/message.h> #include <google/protobuf/repeated_field.h> #include <google/protobuf/extension_set.h> -#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/generated_message_reflection.h> #include "google/protobuf/descriptor.pb.h" // @@protoc_insertion_point(includes) @@ -46,29 +45,29 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message public: CodeGeneratorRequest(); virtual ~CodeGeneratorRequest(); - + CodeGeneratorRequest(const CodeGeneratorRequest& from); - + inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorRequest& default_instance(); - + void Swap(CodeGeneratorRequest* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorRequest* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -76,7 +75,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message void MergeFrom(const CodeGeneratorRequest& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -89,12 +88,13 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message void SharedDtor(); void SetCachedSize(int size) const; public: + ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // repeated string file_to_generate = 1; inline int file_to_generate_size() const; inline void clear_file_to_generate(); @@ -110,7 +110,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message inline void add_file_to_generate(const char* value, size_t size); inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); - + // optional string parameter = 2; inline bool has_parameter() const; inline void clear_parameter(); @@ -120,9 +120,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message inline void set_parameter(const char* value); inline void set_parameter(const char* value, size_t size); inline ::std::string* mutable_parameter(); - inline ::std::string* release_parameter(); - inline void set_allocated_parameter(::std::string* parameter); - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int proto_file_size() const; inline void clear_proto_file(); @@ -134,23 +132,33 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message proto_file() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); - + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: - inline void set_has_parameter(); - inline void clear_has_parameter(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - - ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; + ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; ::std::string* parameter_; + static const ::std::string _default_parameter_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - + + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? + inline bool _has_bit(int index) const { + return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + } + inline void _set_bit(int index) { + _has_bits_[index / 32] |= (1u << (index % 32)); + } + inline void _clear_bit(int index) { + _has_bits_[index / 32] &= ~(1u << (index % 32)); + } + void InitAsDefaultInstance(); static CodeGeneratorRequest* default_instance_; }; @@ -160,29 +168,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M public: CodeGeneratorResponse_File(); virtual ~CodeGeneratorResponse_File(); - + CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from); - + inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorResponse_File& default_instance(); - + void Swap(CodeGeneratorResponse_File* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorResponse_File* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -190,7 +198,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M void MergeFrom(const CodeGeneratorResponse_File& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -203,12 +211,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M void SharedDtor(); void SetCachedSize(int size) const; public: + ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -218,9 +227,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); - + // optional string insertion_point = 2; inline bool has_insertion_point() const; inline void clear_insertion_point(); @@ -230,9 +237,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_insertion_point(const char* value); inline void set_insertion_point(const char* value, size_t size); inline ::std::string* mutable_insertion_point(); - inline ::std::string* release_insertion_point(); - inline void set_allocated_insertion_point(::std::string* insertion_point); - + // optional string content = 15; inline bool has_content() const; inline void clear_content(); @@ -242,29 +247,35 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_content(const char* value); inline void set_content(const char* value, size_t size); inline ::std::string* mutable_content(); - inline ::std::string* release_content(); - inline void set_allocated_content(::std::string* content); - + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: - inline void set_has_name(); - inline void clear_has_name(); - inline void set_has_insertion_point(); - inline void clear_has_insertion_point(); - inline void set_has_content(); - inline void clear_has_content(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - - ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; + ::std::string* name_; + static const ::std::string _default_name_; ::std::string* insertion_point_; + static const ::std::string _default_insertion_point_; ::std::string* content_; + static const ::std::string _default_content_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - + + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? + inline bool _has_bit(int index) const { + return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + } + inline void _set_bit(int index) { + _has_bits_[index / 32] |= (1u << (index % 32)); + } + inline void _clear_bit(int index) { + _has_bits_[index / 32] &= ~(1u << (index % 32)); + } + void InitAsDefaultInstance(); static CodeGeneratorResponse_File* default_instance_; }; @@ -274,29 +285,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag public: CodeGeneratorResponse(); virtual ~CodeGeneratorResponse(); - + CodeGeneratorResponse(const CodeGeneratorResponse& from); - + inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorResponse& default_instance(); - + void Swap(CodeGeneratorResponse* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorResponse* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -304,7 +315,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag void MergeFrom(const CodeGeneratorResponse& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -317,14 +328,15 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: + ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef CodeGeneratorResponse_File File; - + // accessors ------------------------------------------------------- - + // optional string error = 1; inline bool has_error() const; inline void clear_error(); @@ -334,9 +346,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag inline void set_error(const char* value); inline void set_error(const char* value, size_t size); inline ::std::string* mutable_error(); - inline ::std::string* release_error(); - inline void set_allocated_error(::std::string* error); - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int file_size() const; inline void clear_file(); @@ -348,22 +358,32 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag file() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); - + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: - inline void set_has_error(); - inline void clear_has_error(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - - ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; + ::std::string* error_; + static const ::std::string _default_error_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - + + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? + inline bool _has_bit(int index) const { + return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + } + inline void _set_bit(int index) { + _has_bits_[index / 32] |= (1u << (index % 32)); + } + inline void _clear_bit(int index) { + _has_bits_[index / 32] &= ~(1u << (index % 32)); + } + void InitAsDefaultInstance(); static CodeGeneratorResponse* default_instance_; }; @@ -382,127 +402,83 @@ inline void CodeGeneratorRequest::clear_file_to_generate() { file_to_generate_.Clear(); } inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Get(index); } inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Mutable(index); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) file_to_generate_.Mutable(index)->assign(value); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { file_to_generate_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { file_to_generate_.Mutable(index)->assign( reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline ::std::string* CodeGeneratorRequest::add_file_to_generate() { return file_to_generate_.Add(); } inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { file_to_generate_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { file_to_generate_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline const ::google::protobuf::RepeatedPtrField< ::std::string>& CodeGeneratorRequest::file_to_generate() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_; } inline ::google::protobuf::RepeatedPtrField< ::std::string>* CodeGeneratorRequest::mutable_file_to_generate() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &file_to_generate_; } // optional string parameter = 2; inline bool CodeGeneratorRequest::has_parameter() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void CodeGeneratorRequest::set_has_parameter() { - _has_bits_[0] |= 0x00000002u; -} -inline void CodeGeneratorRequest::clear_has_parameter() { - _has_bits_[0] &= ~0x00000002u; + return _has_bit(1); } inline void CodeGeneratorRequest::clear_parameter() { - if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (parameter_ != &_default_parameter_) { parameter_->clear(); } - clear_has_parameter(); + _clear_bit(1); } inline const ::std::string& CodeGeneratorRequest::parameter() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) return *parameter_; } inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (parameter_ == &_default_parameter_) { parameter_ = new ::std::string; } parameter_->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value) { - set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (parameter_ == &_default_parameter_) { parameter_ = new ::std::string; } parameter_->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (parameter_ == &_default_parameter_) { parameter_ = new ::std::string; } parameter_->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline ::std::string* CodeGeneratorRequest::mutable_parameter() { - set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (parameter_ == &_default_parameter_) { parameter_ = new ::std::string; } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) return parameter_; } -inline ::std::string* CodeGeneratorRequest::release_parameter() { - clear_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - return NULL; - } else { - ::std::string* temp = parameter_; - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - return temp; - } -} -inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { - if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - delete parameter_; - } - if (parameter) { - set_has_parameter(); - parameter_ = parameter; - } else { - clear_has_parameter(); - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int CodeGeneratorRequest::proto_file_size() const { @@ -512,25 +488,20 @@ inline void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Get(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Mutable(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& CodeGeneratorRequest::proto_file() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* CodeGeneratorRequest::mutable_proto_file() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return &proto_file_; } @@ -540,231 +511,129 @@ CodeGeneratorRequest::mutable_proto_file() { // optional string name = 1; inline bool CodeGeneratorResponse_File::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void CodeGeneratorResponse_File::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -inline void CodeGeneratorResponse_File::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; + return _has_bit(0); } inline void CodeGeneratorResponse_File::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (name_ != &_default_name_) { name_->clear(); } - clear_has_name(); + _clear_bit(0); } inline const ::std::string& CodeGeneratorResponse_File::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) return *name_; } inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (name_ == &_default_name_) { name_ = new ::std::string; } name_->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value) { - set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (name_ == &_default_name_) { name_ = new ::std::string; } name_->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (name_ == &_default_name_) { name_ = new ::std::string; } name_->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline ::std::string* CodeGeneratorResponse_File::mutable_name() { - set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (name_ == &_default_name_) { name_ = new ::std::string; } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) return name_; } -inline ::std::string* CodeGeneratorResponse_File::release_name() { - clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - return NULL; - } else { - ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - return temp; - } -} -inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - delete name_; - } - if (name) { - set_has_name(); - name_ = name; - } else { - clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} // optional string insertion_point = 2; inline bool CodeGeneratorResponse_File::has_insertion_point() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void CodeGeneratorResponse_File::set_has_insertion_point() { - _has_bits_[0] |= 0x00000002u; -} -inline void CodeGeneratorResponse_File::clear_has_insertion_point() { - _has_bits_[0] &= ~0x00000002u; + return _has_bit(1); } inline void CodeGeneratorResponse_File::clear_insertion_point() { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (insertion_point_ != &_default_insertion_point_) { insertion_point_->clear(); } - clear_has_insertion_point(); + _clear_bit(1); } inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return *insertion_point_; } inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (insertion_point_ == &_default_insertion_point_) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { - set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (insertion_point_ == &_default_insertion_point_) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (insertion_point_ == &_default_insertion_point_) { insertion_point_ = new ::std::string; } insertion_point_->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(1); + if (insertion_point_ == &_default_insertion_point_) { insertion_point_ = new ::std::string; } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return insertion_point_; } -inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { - clear_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - return NULL; - } else { - ::std::string* temp = insertion_point_; - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - return temp; - } -} -inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - delete insertion_point_; - } - if (insertion_point) { - set_has_insertion_point(); - insertion_point_ = insertion_point; - } else { - clear_has_insertion_point(); - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} // optional string content = 15; inline bool CodeGeneratorResponse_File::has_content() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void CodeGeneratorResponse_File::set_has_content() { - _has_bits_[0] |= 0x00000004u; -} -inline void CodeGeneratorResponse_File::clear_has_content() { - _has_bits_[0] &= ~0x00000004u; + return _has_bit(2); } inline void CodeGeneratorResponse_File::clear_content() { - if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (content_ != &_default_content_) { content_->clear(); } - clear_has_content(); + _clear_bit(2); } inline const ::std::string& CodeGeneratorResponse_File::content() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) return *content_; } inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(2); + if (content_ == &_default_content_) { content_ = new ::std::string; } content_->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value) { - set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(2); + if (content_ == &_default_content_) { content_ = new ::std::string; } content_->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(2); + if (content_ == &_default_content_) { content_ = new ::std::string; } content_->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline ::std::string* CodeGeneratorResponse_File::mutable_content() { - set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(2); + if (content_ == &_default_content_) { content_ = new ::std::string; } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) return content_; } -inline ::std::string* CodeGeneratorResponse_File::release_content() { - clear_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - return NULL; - } else { - ::std::string* temp = content_; - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - return temp; - } -} -inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { - if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - delete content_; - } - if (content) { - set_has_content(); - content_ = content; - } else { - clear_has_content(); - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) -} // ------------------------------------------------------------------- @@ -772,79 +641,45 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con // optional string error = 1; inline bool CodeGeneratorResponse::has_error() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void CodeGeneratorResponse::set_has_error() { - _has_bits_[0] |= 0x00000001u; -} -inline void CodeGeneratorResponse::clear_has_error() { - _has_bits_[0] &= ~0x00000001u; + return _has_bit(0); } inline void CodeGeneratorResponse::clear_error() { - if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + if (error_ != &_default_error_) { error_->clear(); } - clear_has_error(); + _clear_bit(0); } inline const ::std::string& CodeGeneratorResponse::error() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) return *error_; } inline void CodeGeneratorResponse::set_error(const ::std::string& value) { - set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (error_ == &_default_error_) { error_ = new ::std::string; } error_->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value) { - set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (error_ == &_default_error_) { error_ = new ::std::string; } error_->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { - set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (error_ == &_default_error_) { error_ = new ::std::string; } error_->assign(reinterpret_cast<const char*>(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } inline ::std::string* CodeGeneratorResponse::mutable_error() { - set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + _set_bit(0); + if (error_ == &_default_error_) { error_ = new ::std::string; } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) return error_; } -inline ::std::string* CodeGeneratorResponse::release_error() { - clear_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - return NULL; - } else { - ::std::string* temp = error_; - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - return temp; - } -} -inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { - if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { - delete error_; - } - if (error) { - set_has_error(); - error_ = error; - } else { - clear_has_error(); - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) -} // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int CodeGeneratorResponse::file_size() const { @@ -854,25 +689,20 @@ inline void CodeGeneratorResponse::clear_file() { file_.Clear(); } inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Get(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Mutable(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& CodeGeneratorResponse::file() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) return file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index b65379d..4e928b0 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -45,8 +45,6 @@ // flag "--${NAME}_out" is passed to protoc. package google.protobuf.compiler; -option java_package = "com.google.protobuf.compiler"; -option java_outer_classname = "PluginProtos"; import "google/protobuf/descriptor.proto"; @@ -133,7 +131,7 @@ message CodeGeneratorResponse { // in order to work correctly in that context. // // The code generator that generates the initial file and the one which - // inserts into it must both run as part of a single invocation of protoc. + // inserts into it must both run as part of a single invocatino of protoc. // Code generators are executed in the order in which they appear on the // command line. // diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 15e05da..fae83a3 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -28,8 +28,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -//#PY25 compatible generated code for GAE. -// Copyright 2007 Google Inc. All Rights Reserved. // Author: robinson@google.com (Will Robinson) // // This module outputs pure-Python protocol message classes that will @@ -47,7 +45,6 @@ #include <limits> #include <map> #include <utility> -#include <memory> #include <string> #include <vector> @@ -55,7 +52,6 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -110,12 +106,6 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, const char kDescriptorKey[] = "DESCRIPTOR"; -// Does the file have top-level enums? -inline bool HasTopLevelEnums(const FileDescriptor *file) { - return file->enum_type_count() > 0; -} - - // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -130,23 +120,13 @@ void PrintTopBoilerplate( // TODO(robinson): Allow parameterization of Python version? printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "# source: $filename$\n" - "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 - "\n", - "filename", file->name()); - if (HasTopLevelEnums(file)) { - printer->Print( - "from google.protobuf.internal import enum_type_wrapper\n"); - } - printer->Print( - "from google.protobuf import descriptor as _descriptor\n" - "from google.protobuf import message as _message\n" - "from google.protobuf import reflection as _reflection\n" - "from google.protobuf import symbol_database as " - "_symbol_database\n"); + "\n" + "from google.protobuf import descriptor\n" + "from google.protobuf import message\n" + "from google.protobuf import reflection\n"); if (HasGenericServices(file)) { printer->Print( - "from google.protobuf import service as _service\n" + "from google.protobuf import service\n" "from google.protobuf import service_reflection\n"); } @@ -156,8 +136,7 @@ void PrintTopBoilerplate( "from google.protobuf import descriptor_pb2\n"); } printer->Print( - "# @@protoc_insertion_point(imports)\n\n" - "_sym_db = _symbol_database.Default()\n"); + "# @@protoc_insertion_point(imports)\n"); printer->Print("\n\n"); } @@ -223,12 +202,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_ENUM: return SimpleItoa(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: -//##!PY25 return "b\"" + CEscape(field.default_value_string()) + -//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : -//##!PY25 "\".decode('utf-8')"); - return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 - (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 - "\").decode('utf-8')"); //##PY25 + if (field.type() == FieldDescriptor::TYPE_STRING) { + return "unicode(\"" + CEscape(field.default_value_string()) + + "\", \"utf-8\")"; + } else { + return "\"" + CEscape(field.default_value_string()) + "\""; + } case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } @@ -251,7 +230,7 @@ Generator::~Generator() { bool Generator::Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { // Completely serialize all Generate() calls on this instance. The @@ -273,29 +252,26 @@ bool Generator::Generate(const FileDescriptor* file, fdp.SerializeToString(&file_descriptor_serialized_); - scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); + scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); - PrintImports(); PrintFileDescriptor(); PrintTopLevelEnums(); PrintTopLevelExtensions(); PrintAllNestedEnumsInFile(); PrintMessageDescriptors(); + // We have to print the imports after the descriptors, so that mutually + // recursive protos in separate files can successfully reference each other. + PrintImports(); FixForeignFieldsInDescriptors(); PrintMessages(); // We have to fix up the extensions after the message classes themselves, // since they need to call static RegisterExtension() methods on these // classes. FixForeignFieldsInExtensions(); - // Descriptor options may have custom extensions. These custom options - // can only be successfully parsed after we register corresponding - // extensions. Therefore we parse all options again here to recognize - // custom options that may be unknown when we define the descriptors. - FixAllDescriptorOptions(); if (HasGenericServices(file)) { PrintServices(); } @@ -314,13 +290,6 @@ void Generator::PrintImports() const { module_name); } printer_->Print("\n"); - - // Print public imports. - for (int i = 0; i < file_->public_dependency_count(); ++i) { - string module_name = ModuleName(file_->public_dependency(i)->name()); - printer_->Print("from $module$ import *\n", "module", module_name); - } - printer_->Print("\n"); } // Prints the single file descriptor for this file. @@ -330,31 +299,20 @@ void Generator::PrintFileDescriptor() const { m["name"] = file_->name(); m["package"] = file_->package(); const char file_descriptor_template[] = - "$descriptor_name$ = _descriptor.FileDescriptor(\n" + "$descriptor_name$ = descriptor.FileDescriptor(\n" " name='$name$',\n" " package='$package$',\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( -//##!PY25 "serialized_pb=b'$value$'\n", - "serialized_pb=_b('$value$')\n", //##PY25 + "serialized_pb='$value$'", "value", strings::CHexEscape(file_descriptor_serialized_)); - if (file_->dependency_count() != 0) { - printer_->Print(",\ndependencies=["); - for (int i = 0; i < file_->dependency_count(); ++i) { - string module_name = ModuleName(file_->dependency(i)->name()); - printer_->Print("$module_name$.DESCRIPTOR,", "module_name", module_name); - } - printer_->Print("]"); - } // TODO(falk): Also print options and fix the message_type, enum_type, // service and extension later in the generation. printer_->Outdent(); printer_->Print(")\n"); - printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", - kDescriptorKey); printer_->Print("\n"); } @@ -365,11 +323,6 @@ void Generator::PrintTopLevelEnums() const { for (int i = 0; i < file_->enum_type_count(); ++i) { const EnumDescriptor& enum_descriptor = *file_->enum_type(i); PrintEnum(enum_descriptor); - printer_->Print("$name$ = " - "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", - "name", enum_descriptor.name(), - "descriptor_name", - ModuleLevelDescriptorName(enum_descriptor)); printer_->Print("\n"); for (int j = 0; j < enum_descriptor.value_count(); ++j) { @@ -399,14 +352,12 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { map<string, string> m; - string module_level_descriptor_name = - ModuleLevelDescriptorName(enum_descriptor); - m["descriptor_name"] = module_level_descriptor_name; + m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); m["name"] = enum_descriptor.name(); m["full_name"] = enum_descriptor.full_name(); m["file"] = kDescriptorKey; const char enum_descriptor_template[] = - "$descriptor_name$ = _descriptor.EnumDescriptor(\n" + "$descriptor_name$ = descriptor.EnumDescriptor(\n" " name='$name$',\n" " full_name='$full_name$',\n" " filename=None,\n" @@ -426,13 +377,11 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Print("containing_type=None,\n"); printer_->Print("options=$options_value$,\n", "options_value", - OptionsValue("EnumOptions", options_string)); + OptionsValue("EnumOptions", CEscape(options_string))); EnumDescriptorProto edp; PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); printer_->Print(")\n"); - printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", - module_level_descriptor_name); printer_->Print("\n"); } @@ -489,7 +438,7 @@ void Generator::PrintServiceDescriptor( descriptor.options().SerializeToString(&options_string); printer_->Print( - "$service_name$ = _descriptor.ServiceDescriptor(\n", + "$service_name$ = descriptor.ServiceDescriptor(\n", "service_name", service_name); printer_->Indent(); map<string, string> m; @@ -512,6 +461,7 @@ void Generator::PrintServiceDescriptor( printer_->Print("methods=[\n"); for (int i = 0; i < descriptor.method_count(); ++i) { const MethodDescriptor* method = descriptor.method(i); + string options_string; method->options().SerializeToString(&options_string); m.clear(); @@ -522,7 +472,7 @@ void Generator::PrintServiceDescriptor( m["input_type"] = ModuleLevelDescriptorName(*(method->input_type())); m["output_type"] = ModuleLevelDescriptorName(*(method->output_type())); m["options_value"] = OptionsValue("MethodOptions", options_string); - printer_->Print("_descriptor.MethodDescriptor(\n"); + printer_->Print("descriptor.MethodDescriptor(\n"); printer_->Indent(); printer_->Print( m, @@ -543,36 +493,27 @@ void Generator::PrintServiceDescriptor( void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { // Print the service. - printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" - "'$class_name$', (_service.Service,), dict(\n", + printer_->Print("class $class_name$(service.Service):\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "$descriptor_key$ = $descriptor_name$,\n", + "__metaclass__ = service_reflection.GeneratedServiceType\n" + "$descriptor_key$ = $descriptor_name$\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); - printer_->Print( - "__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); - printer_->Print("))\n\n"); printer_->Outdent(); } void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // Print the service stub. - printer_->Print("$class_name$_Stub = " - "service_reflection.GeneratedServiceStubType(" - "'$class_name$_Stub', ($class_name$,), dict(\n", + printer_->Print("class $class_name$_Stub($class_name$):\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "$descriptor_key$ = $descriptor_name$,\n", + "__metaclass__ = service_reflection.GeneratedServiceStubType\n" + "$descriptor_key$ = $descriptor_name$\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); - printer_->Print( - "__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); - printer_->Print("))\n\n"); printer_->Outdent(); } @@ -584,7 +525,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { PrintNestedDescriptors(message_descriptor); printer_->Print("\n"); - printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n", + printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n", "descriptor_name", ModuleLevelDescriptorName(message_descriptor)); printer_->Indent(); @@ -642,22 +583,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "end", SimpleItoa(range->end)); } printer_->Print("],\n"); - printer_->Print("oneofs=[\n"); - printer_->Indent(); - for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { - const OneofDescriptor* desc = message_descriptor.oneof_decl(i); - map<string, string> m; - m["name"] = desc->name(); - m["full_name"] = desc->full_name(); - m["index"] = SimpleItoa(desc->index()); - printer_->Print( - m, - "_descriptor.OneofDescriptor(\n" - " name='$name$', full_name='$full_name$',\n" - " index=$index$, containing_type=None, fields=[]),\n"); - } - printer_->Outdent(); - printer_->Print("],\n"); + // Serialization of proto DescriptorProto edp; PrintSerializedPbInterval(message_descriptor, edp); @@ -680,12 +606,7 @@ void Generator::PrintNestedDescriptors( // Prints all messages in |file|. void Generator::PrintMessages() const { for (int i = 0; i < file_->message_type_count(); ++i) { - vector<string> to_register; - PrintMessage(*file_->message_type(i), "", &to_register); - for (int j = 0; j < to_register.size(); ++j) { - printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", - to_register[j]); - } + PrintMessage(*file_->message_type(i)); printer_->Print("\n"); } } @@ -697,40 +618,33 @@ void Generator::PrintMessages() const { // reflection.py will use to construct the meat of the class itself. // // Mutually recursive with PrintNestedMessages(). -// Collect nested message names to_register for the symbol_database. -void Generator::PrintMessage(const Descriptor& message_descriptor, - const string& prefix, - vector<string>* to_register) const { - string qualified_name(prefix + message_descriptor.name()); - to_register->push_back(qualified_name); - printer_->Print( - "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " - "(_message.Message,), dict(\n", - "name", message_descriptor.name()); +void Generator::PrintMessage( + const Descriptor& message_descriptor) const { + printer_->Print("class $name$(message.Message):\n", "name", + message_descriptor.name()); printer_->Indent(); - - PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); + printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n"); + PrintNestedMessages(message_descriptor); map<string, string> m; m["descriptor_key"] = kDescriptorKey; m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); - printer_->Print("__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); - printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", message_descriptor.full_name()); - printer_->Print("))\n"); + printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); + + printer_->Print( + "\n" + "# @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", message_descriptor.full_name()); + printer_->Outdent(); } // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). -void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, - const string& prefix, - vector<string>* to_register) const { +void Generator::PrintNestedMessages( + const Descriptor& containing_descriptor) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); - PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); - printer_->Print(",\n"); + PrintMessage(*containing_descriptor.nested_type(i)); } } @@ -758,57 +672,6 @@ void Generator::FixForeignFieldsInDescriptor( const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i); FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } - for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { - map<string, string> m; - const OneofDescriptor* oneof = descriptor.oneof_decl(i); - m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); - m["oneof_name"] = oneof->name(); - for (int j = 0; j < oneof->field_count(); ++j) { - m["field_name"] = oneof->field(j)->name(); - printer_->Print( - m, - "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n" - " $descriptor_name$.fields_by_name['$field_name$'])\n"); - printer_->Print( - m, - "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = " - "$descriptor_name$.oneofs_by_name['$oneof_name$']\n"); - } - } -} - -void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { - map<string, string> m; - m["descriptor_name"] = kDescriptorKey; - m["message_name"] = descriptor.name(); - m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); - const char file_descriptor_template[] = - "$descriptor_name$.message_types_by_name['$message_name$'] = " - "$message_descriptor_name$\n"; - printer_->Print(m, file_descriptor_template); -} - -void Generator::AddEnumToFileDescriptor( - const EnumDescriptor& descriptor) const { - map<string, string> m; - m["descriptor_name"] = kDescriptorKey; - m["enum_name"] = descriptor.name(); - m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); - const char file_descriptor_template[] = - "$descriptor_name$.enum_types_by_name['$enum_name$'] = " - "$enum_descriptor_name$\n"; - printer_->Print(m, file_descriptor_template); -} - -void Generator::AddExtensionToFileDescriptor( - const FieldDescriptor& descriptor) const { - map<string, string> m; - m["descriptor_name"] = kDescriptorKey; - m["field_name"] = descriptor.name(); - const char file_descriptor_template[] = - "$descriptor_name$.extensions_by_name['$field_name$'] = " - "$field_name$\n"; - printer_->Print(m, file_descriptor_template); } // Sets any necessary message_type and enum_type attributes @@ -875,7 +738,7 @@ void Generator::FixContainingTypeInDescriptor( const string parent_name = ModuleLevelDescriptorName( *containing_descriptor); printer_->Print( - "$nested_name$.containing_type = $parent_name$\n", + "$nested_name$.containing_type = $parent_name$;\n", "nested_name", nested_name, "parent_name", parent_name); } @@ -889,15 +752,6 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); } - for (int i = 0; i < file_->message_type_count(); ++i) { - AddMessageToFileDescriptor(*file_->message_type(i)); - } - for (int i = 0; i < file_->enum_type_count(); ++i) { - AddEnumToFileDescriptor(*file_->enum_type(i)); - } - for (int i = 0; i < file_->extension_count(); ++i) { - AddExtensionToFileDescriptor(*file_->extension(i)); - } printer_->Print("\n"); } @@ -913,7 +767,6 @@ void Generator::FixForeignFieldsInExtensions() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInNestedExtensions(*file_->message_type(i)); } - printer_->Print("\n"); } void Generator::FixForeignFieldsInExtension( @@ -964,24 +817,20 @@ void Generator::PrintEnumValueDescriptor( m["options"] = OptionsValue("EnumValueOptions", options_string); printer_->Print( m, - "_descriptor.EnumValueDescriptor(\n" + "descriptor.EnumValueDescriptor(\n" " name='$name$', index=$index$, number=$number$,\n" " options=$options$,\n" " type=None)"); } -// Returns a Python expression that calls descriptor._ParseOptions using -// the given descriptor class name and serialized options protobuf string. string Generator::OptionsValue( const string& class_name, const string& serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { string full_class_name = "descriptor_pb2." + class_name; -//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" -//##!PY25 + CEscape(serialized_options)+ "')"; - return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 - + CEscape(serialized_options)+ "'))"; //##PY25 + return "descriptor._ParseOptions(" + full_class_name + "(), '" + + CEscape(serialized_options)+ "')"; } } @@ -1006,7 +855,7 @@ void Generator::PrintFieldDescriptor( // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). const char field_descriptor_decl[] = - "_descriptor.FieldDescriptor(\n" + "descriptor.FieldDescriptor(\n" " name='$name$', full_name='$full_name$', index=$index$,\n" " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" " has_default_value=$has_default_value$, default_value=$default_value$,\n" @@ -1137,125 +986,6 @@ void Generator::PrintSerializedPbInterval( "serialized_end", SimpleItoa(offset + sp.size())); } -namespace { -void PrintDescriptorOptionsFixingCode(const string& descriptor, - const string& options, - io::Printer* printer) { - // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase - // in proto2 python runtime but it couldn't be used here because appengine - // uses a snapshot version of the library in which the new method is not - // yet present. After appengine has synced their runtime library, the code - // below should be cleaned up to use _SetOptions(). - printer->Print( - "$descriptor$.has_options = True\n" - "$descriptor$._options = $options$\n", - "descriptor", descriptor, "options", options); -} -} // namespace - -// Prints expressions that set the options field of all descriptors. -void Generator::FixAllDescriptorOptions() const { - // Prints an expression that sets the file descriptor's options. - string file_options = OptionsValue( - "FileOptions", file_->options().SerializeAsString()); - if (file_options != "None") { - PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); - } - // Prints expressions that set the options for all top level enums. - for (int i = 0; i < file_->enum_type_count(); ++i) { - const EnumDescriptor& enum_descriptor = *file_->enum_type(i); - FixOptionsForEnum(enum_descriptor); - } - // Prints expressions that set the options for all top level extensions. - for (int i = 0; i < file_->extension_count(); ++i) { - const FieldDescriptor& field = *file_->extension(i); - FixOptionsForField(field); - } - // Prints expressions that set the options for all messages, nested enums, - // nested extensions and message fields. - for (int i = 0; i < file_->message_type_count(); ++i) { - FixOptionsForMessage(*file_->message_type(i)); - } -} - -// Prints expressions that set the options for an enum descriptor and its -// value descriptors. -void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { - string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); - string enum_options = OptionsValue( - "EnumOptions", enum_descriptor.options().SerializeAsString()); - if (enum_options != "None") { - PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); - } - for (int i = 0; i < enum_descriptor.value_count(); ++i) { - const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); - string value_options = OptionsValue( - "EnumValueOptions", value_descriptor.options().SerializeAsString()); - if (value_options != "None") { - PrintDescriptorOptionsFixingCode( - StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), - value_descriptor.name().c_str()), - value_options, printer_); - } - } -} - -// Prints expressions that set the options for field descriptors (including -// extensions). -void Generator::FixOptionsForField( - const FieldDescriptor& field) const { - string field_options = OptionsValue( - "FieldOptions", field.options().SerializeAsString()); - if (field_options != "None") { - string field_name; - if (field.is_extension()) { - if (field.extension_scope() == NULL) { - // Top level extensions. - field_name = field.name(); - } else { - field_name = FieldReferencingExpression( - field.extension_scope(), field, "extensions_by_name"); - } - } else { - field_name = FieldReferencingExpression( - field.containing_type(), field, "fields_by_name"); - } - PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); - } -} - -// Prints expressions that set the options for a message and all its inner -// types (nested messages, nested enums, extensions, fields). -void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { - // Nested messages. - for (int i = 0; i < descriptor.nested_type_count(); ++i) { - FixOptionsForMessage(*descriptor.nested_type(i)); - } - // Enums. - for (int i = 0; i < descriptor.enum_type_count(); ++i) { - FixOptionsForEnum(*descriptor.enum_type(i)); - } - // Fields. - for (int i = 0; i < descriptor.field_count(); ++i) { - const FieldDescriptor& field = *descriptor.field(i); - FixOptionsForField(field); - } - // Extensions. - for (int i = 0; i < descriptor.extension_count(); ++i) { - const FieldDescriptor& field = *descriptor.extension(i); - FixOptionsForField(field); - } - // Message option for this message. - string message_options = OptionsValue( - "MessageOptions", descriptor.options().SerializeAsString()); - if (message_options != "None") { - string descriptor_name = ModuleLevelDescriptorName(descriptor); - PrintDescriptorOptionsFixingCode(descriptor_name, - message_options, - printer_); - } -} - } // namespace python } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index f86e9ea..43c2087 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -66,7 +66,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { // CodeGenerator methods. virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* generator_context, + OutputDirectory* output_directory, string* error) const; private: @@ -94,11 +94,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; void PrintMessages() const; - void PrintMessage(const Descriptor& message_descriptor, const string& prefix, - vector<string>* to_register) const; - void PrintNestedMessages(const Descriptor& containing_descriptor, - const string& prefix, - vector<string>* to_register) const; + void PrintMessage(const Descriptor& message_descriptor) const; + void PrintNestedMessages(const Descriptor& containing_descriptor) const; void FixForeignFieldsInDescriptors() const; void FixForeignFieldsInDescriptor( @@ -107,9 +104,6 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; - void AddMessageToFileDescriptor(const Descriptor& descriptor) const; - void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; - void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; string FieldReferencingExpression(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; @@ -143,11 +137,6 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintSerializedPbInterval( const DescriptorT& descriptor, DescriptorProtoT& proto) const; - void FixAllDescriptorOptions() const; - void FixOptionsForField(const FieldDescriptor& field) const; - void FixOptionsForEnum(const EnumDescriptor& descriptor) const; - void FixOptionsForMessage(const Descriptor& descriptor) const; - // Very coarse-grained lock to ensure that Generate() is reentrant. // Guards file_, printer_ and file_descriptor_serialized_. mutable Mutex mutex_; diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index 09dbc65..fde8876 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -34,8 +34,6 @@ // It seemed like parameterizing it would add more complexity than it is // worth. -#include <memory> - #include <google/protobuf/compiler/python/python_generator.h> #include <google/protobuf/compiler/command_line_interface.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -58,19 +56,19 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, + OutputDirectory* output_directory, string* error) const { - TryInsert("test_pb2.py", "imports", context); - TryInsert("test_pb2.py", "module_scope", context); - TryInsert("test_pb2.py", "class_scope:foo.Bar", context); - TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); + TryInsert("test_pb2.py", "imports", output_directory); + TryInsert("test_pb2.py", "module_scope", output_directory); + TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory); + TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory); return true; } void TryInsert(const string& filename, const string& insertion_point, - GeneratorContext* context) const { + OutputDirectory* output_directory) const { scoped_ptr<io::ZeroCopyOutputStream> output( - context->OpenForInsert(filename, insertion_point)); + output_directory->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -80,13 +78,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(PythonPluginTest, PluginTest) { - GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - true)); + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + TestTempDir() + "/test.proto"); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 61ae438..de46a3e 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,16 +32,13 @@ #include <google/protobuf/compiler/subprocess.h> -#include <algorithm> -#include <iostream> - #ifndef _WIN32 #include <errno.h> -#include <sys/select.h> #include <sys/wait.h> #include <signal.h> #endif +#include <algorithm> #include <google/protobuf/stubs/common.h> #include <google/protobuf/message.h> #include <google/protobuf/stubs/substitute.h> @@ -99,7 +96,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { } // Setup STARTUPINFO to redirect handles. - STARTUPINFOA startup_info; + STARTUPINFO startup_info; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; @@ -118,16 +115,16 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { // Create the process. PROCESS_INFORMATION process_info; - if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), - (search_mode == SEARCH_PATH) ? name_copy : NULL, - NULL, // process security attributes - NULL, // thread security attributes - TRUE, // inherit handles? - 0, // obscure creation flags - NULL, // environment (inherit from parent) - NULL, // current directory (inherit from parent) - &startup_info, - &process_info)) { + if (CreateProcess((search_mode == SEARCH_PATH) ? NULL : program.c_str(), + (search_mode == SEARCH_PATH) ? name_copy : NULL, + NULL, // process security attributes + NULL, // thread security attributes + TRUE, // inherit handles? + 0, // obscure creation flags + NULL, // environment (inherit from parent) + NULL, // current directory (inherit from parent) + &startup_info, + &process_info)) { child_handle_ = process_info.hProcess; CloseHandleOrDie(process_info.hThread); child_stdin_ = stdin_pipe_write; @@ -295,8 +292,8 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { int stdin_pipe[2]; int stdout_pipe[2]; - GOOGLE_CHECK(pipe(stdin_pipe) != -1); - GOOGLE_CHECK(pipe(stdout_pipe) != -1); + pipe(stdin_pipe); + pipe(stdout_pipe); char* argv[2] = { strdup(program.c_str()), NULL }; @@ -324,11 +321,9 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { // Write directly to STDERR_FILENO to avoid stdio code paths that may do // stuff that is unsafe here. - int ignored; - ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); + write(STDERR_FILENO, argv[0], strlen(argv[0])); const char* message = ": program not found or is not executable\n"; - ignored = write(STDERR_FILENO, message, strlen(message)); - (void) ignored; + write(STDERR_FILENO, message, strlen(message)); // Must use _exit() rather than exit() to avoid flushing output buffers // that will also be flushed by the parent. @@ -449,7 +444,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, } if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable: " + CEscape(output_data); + *error = "Plugin output is unparseable."; return false; } diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h index 2513863..f9e8ae8 100644 --- a/src/google/protobuf/compiler/subprocess.h +++ b/src/google/protobuf/compiler/subprocess.h @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -40,10 +40,9 @@ #include <sys/types.h> #include <unistd.h> #endif // !_WIN32 -#include <google/protobuf/stubs/common.h> #include <string> - +#include <google/protobuf/stubs/common.h> namespace google { namespace protobuf { @@ -53,7 +52,7 @@ class Message; namespace compiler { // Utility class for launching sub-processes. -class LIBPROTOC_EXPORT Subprocess { +class Subprocess { public: Subprocess(); ~Subprocess(); @@ -77,7 +76,7 @@ class LIBPROTOC_EXPORT Subprocess { #ifdef _WIN32 // Given an error code, returns a human-readable error message. This is // defined here so that CommandLineInterface can share it. - static string Win32ErrorMessage(DWORD error_code); + static string Subprocess::Win32ErrorMessage(DWORD error_code); #endif private: diff --git a/src/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc index 4830fd7..5cbbf3d 100644 --- a/src/google/protobuf/compiler/test_plugin.cc +++ b/src/google/protobuf/compiler/test_plugin.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh index 6fc7136..259d5d2 100755 --- a/src/google/protobuf/compiler/zip_output_unittest.sh +++ b/src/google/protobuf/compiler/zip_output_unittest.sh @@ -2,7 +2,7 @@ # # Protocol Buffers - Google's data interchange format # Copyright 2009 Google Inc. All rights reserved. -# https://developers.google.com/protocol-buffers/ +# http://code.google.com/p/protobuf/ # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -39,51 +39,45 @@ fail() { exit 1 } -TEST_TMPDIR=. -PROTOC=./protoc - echo ' - syntax = "proto2"; option java_multiple_files = true; option java_package = "test.jar"; option java_outer_classname = "Outer"; message Foo {} message Bar {} -' > $TEST_TMPDIR/testzip.proto +' > testzip.proto -$PROTOC \ - --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \ - --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \ - || fail 'protoc failed.' +./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \ + testzip.proto || fail 'protoc failed.' echo "Testing output to zip..." if unzip -h > /dev/null; then - unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.' + unzip -t testzip.zip > testzip.list || fail 'unzip failed.' - grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \ || fail 'testzip.pb.cc not found in output zip.' - grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \ || fail 'testzip.pb.h not found in output zip.' - grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \ || fail 'testzip_pb2.py not found in output zip.' - grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \ + grep -i 'manifest' testzip.list > /dev/null \ && fail 'Zip file contained manifest.' else echo "Warning: 'unzip' command not available. Skipping test." fi echo "Testing output to jar..." -if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then - jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.' +if jar c testzip.proto > /dev/null; then + jar tf testzip.jar > testzip.list || fail 'jar failed.' - grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep '^test/jar/Foo\.java$' testzip.list > /dev/null \ || fail 'Foo.java not found in output jar.' - grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep '^test/jar/Bar\.java$' testzip.list > /dev/null \ || fail 'Bar.java not found in output jar.' - grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + grep '^test/jar/Outer\.java$' testzip.list > /dev/null \ || fail 'Outer.java not found in output jar.' - grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \ - || fail 'Manifest not found in output jar.' + grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \ + || fail 'Manifest not ofund in output jar.' else echo "Warning: 'jar' command not available. Skipping test." fi diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc index 458cced..53c1877 100644 --- a/src/google/protobuf/compiler/zip_writer.cc +++ b/src/google/protobuf/compiler/zip_writer.cc @@ -1,36 +1,6 @@ // 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. - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -213,6 +183,6 @@ bool ZipWriter::WriteDirectory() { return output.HadError(); } -} // namespace compiler -} // namespace protobuf } // namespace google +} // namespace protobuf +} // namespace compiler diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h index 602e508..4289553 100644 --- a/src/google/protobuf/compiler/zip_writer.h +++ b/src/google/protobuf/compiler/zip_writer.h @@ -1,36 +1,6 @@ // 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. - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -88,6 +58,6 @@ class ZipWriter { vector<FileInfo> files_; }; -} // namespace compiler -} // namespace protobuf } // namespace google +} // namespace protobuf +} // namespace compiler |