|
|
|
@ -14,9 +14,12 @@ |
|
|
|
|
#include <cstdint> |
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
#include "absl/container/flat_hash_map.h" |
|
|
|
|
#include "absl/functional/function_ref.h" |
|
|
|
|
#include "absl/log/absl_check.h" |
|
|
|
|
#include "absl/log/absl_log.h" |
|
|
|
|
#include "absl/strings/str_cat.h" |
|
|
|
|
#include "absl/strings/string_view.h" |
|
|
|
|
#include "google/protobuf/compiler/java/context.h" |
|
|
|
|
#include "google/protobuf/compiler/java/doc_comment.h" |
|
|
|
|
#include "google/protobuf/compiler/java/field_common.h" |
|
|
|
@ -30,11 +33,29 @@ namespace google { |
|
|
|
|
namespace protobuf { |
|
|
|
|
namespace compiler { |
|
|
|
|
namespace java { |
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
using internal::WireFormat; |
|
|
|
|
using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic; |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
// Adds two variables to (*variables) that operate on a particular field value,
|
|
|
|
|
// both for use locally and on another instance named 'other'. This ensures that
|
|
|
|
|
// we treat these values the same way, whether it's in the current instance or
|
|
|
|
|
// another.
|
|
|
|
|
//
|
|
|
|
|
// `this_variable_name` and `other_variable_name` MUST be string constants.
|
|
|
|
|
//
|
|
|
|
|
// The `create_value` FunctionRef takes the representation of the value and
|
|
|
|
|
// should use it to create and return the code that operates on this value.
|
|
|
|
|
void AddPrimitiveVariableForThisAndOther( |
|
|
|
|
absl::string_view this_variable_name, absl::string_view other_variable_name, |
|
|
|
|
absl::FunctionRef<std::string(absl::string_view)> create_value, |
|
|
|
|
absl::flat_hash_map<absl::string_view, std::string>* variables) { |
|
|
|
|
(*variables)[this_variable_name] = |
|
|
|
|
create_value(absl::StrCat((*variables)["name"], "_")); |
|
|
|
|
(*variables)[other_variable_name] = create_value( |
|
|
|
|
absl::StrCat("other.get", (*variables)["capitalized_name"], "()")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SetPrimitiveVariables( |
|
|
|
|
const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, |
|
|
|
@ -112,25 +133,44 @@ void SetPrimitiveVariables( |
|
|
|
|
(*variables)["set_has_field_bit_to_local"] = |
|
|
|
|
absl::StrCat(GenerateSetBitToLocal(messageBitIndex), ";"); |
|
|
|
|
(*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); |
|
|
|
|
(*variables)["is_other_field_present_message"] = |
|
|
|
|
absl::StrCat("other.has", (*variables)["capitalized_name"], "()"); |
|
|
|
|
} else { |
|
|
|
|
(*variables)["set_has_field_bit_to_local"] = ""; |
|
|
|
|
switch (descriptor->type()) { |
|
|
|
|
case FieldDescriptor::TYPE_BYTES: |
|
|
|
|
(*variables)["is_field_present_message"] = |
|
|
|
|
absl::StrCat("!", name, "_.isEmpty()"); |
|
|
|
|
AddPrimitiveVariableForThisAndOther( |
|
|
|
|
"is_field_present_message", "is_other_field_present_message", |
|
|
|
|
[](absl::string_view value) { |
|
|
|
|
return absl::StrCat("!", value, ".isEmpty()"); |
|
|
|
|
}, |
|
|
|
|
variables); |
|
|
|
|
break; |
|
|
|
|
case FieldDescriptor::TYPE_FLOAT: |
|
|
|
|
(*variables)["is_field_present_message"] = |
|
|
|
|
absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0"); |
|
|
|
|
AddPrimitiveVariableForThisAndOther( |
|
|
|
|
"is_field_present_message", "is_other_field_present_message", |
|
|
|
|
[](absl::string_view value) { |
|
|
|
|
return absl::StrCat("java.lang.Float.floatToRawIntBits(", value, |
|
|
|
|
") != 0"); |
|
|
|
|
}, |
|
|
|
|
variables); |
|
|
|
|
break; |
|
|
|
|
case FieldDescriptor::TYPE_DOUBLE: |
|
|
|
|
(*variables)["is_field_present_message"] = absl::StrCat( |
|
|
|
|
"java.lang.Double.doubleToRawLongBits(", name, "_) != 0"); |
|
|
|
|
AddPrimitiveVariableForThisAndOther( |
|
|
|
|
"is_field_present_message", "is_other_field_present_message", |
|
|
|
|
[](absl::string_view value) { |
|
|
|
|
return absl::StrCat("java.lang.Double.doubleToRawLongBits(", |
|
|
|
|
value, ") != 0"); |
|
|
|
|
}, |
|
|
|
|
variables); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
variables->insert( |
|
|
|
|
{"is_field_present_message", |
|
|
|
|
absl::StrCat(name, "_ != ", (*variables)["default"])}); |
|
|
|
|
AddPrimitiveVariableForThisAndOther( |
|
|
|
|
"is_field_present_message", "is_other_field_present_message", |
|
|
|
|
[variables](absl::string_view value) { |
|
|
|
|
return absl::StrCat(value, " != ", (*variables)["default"]); |
|
|
|
|
}, |
|
|
|
|
variables); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -301,17 +341,10 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( |
|
|
|
|
|
|
|
|
|
void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( |
|
|
|
|
io::Printer* printer) const { |
|
|
|
|
if (descriptor_->has_presence()) { |
|
|
|
|
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"); |
|
|
|
|
} |
|
|
|
|
printer->Print(variables_, |
|
|
|
|
"if ($is_other_field_present_message$) {\n" |
|
|
|
|
" set$capitalized_name$(other.get$capitalized_name$());\n" |
|
|
|
|
"}\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode( |
|
|
|
|