diff options
Diffstat (limited to 'src/google/protobuf/compiler/java')
38 files changed, 1463 insertions, 8966 deletions
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__ |