aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Jon Skeet <jonskeet@google.com>2015-07-20 19:24:31 +0100
committerGravatar Jon Skeet <jonskeet@google.com>2015-07-21 12:59:40 +0100
commit53c399a1d65df65e9f83a70b55041a01cf8d7489 (patch)
treebf3f738dd30295dc8ceb65478b9071d6d654e144 /src
parent2ee4b5665520fe3245eb5e15df8bd35e0c539a07 (diff)
Revamp to reflection.
Changes in brief: 1. Descriptor is now the entry point for all reflection. 2. IReflectedMessage has gone; there's now a Descriptor property in IMessage, which is explicitly implemented (due to the static property). 3. FieldAccessorTable has gone away 4. IFieldAccessor and OneofFieldAccessor still exist; we *could* put the functionality straight into FieldDescriptor and OneofDescriptor... I'm unsure about that. 5. There's a temporary property MessageDescriptor.FieldAccessorsByFieldNumber to make the test changes small - we probably want this to go away 6. Discovery for delegates is now via attributes applied to properties and the Clear method of a oneof I'm happy with 1-3. 4 I'm unsure about - feedback welcome. 5 will go away 6 I'm unsure about, both in design and implementation. Should we have a ProtobufMessageAttribute too? Should we find all the relevant attributes in MessageDescriptor and pass them down, to avoid an O(N^2) scenario? Generated code changes coming in the next commit.
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.cc1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc84
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc3
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc37
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc2
13 files changed, 45 insertions, 99 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 89d4eb18..d327e267 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -74,6 +74,7 @@ void FieldGeneratorBase::SetCommonFieldVariables(
(*variables)["property_name"] = property_name();
(*variables)["type_name"] = type_name();
+ (*variables)["original_name"] = descriptor_->name();
(*variables)["name"] = name();
(*variables)["descriptor_name"] = descriptor_->name();
(*variables)["default_value"] = default_value();
@@ -85,7 +86,6 @@ void FieldGeneratorBase::SetCommonFieldVariables(
}
(*variables)["capitalized_type_name"] = capitalized_type_name();
(*variables)["number"] = number();
- (*variables)["field_ordinal"] = field_ordinal();
(*variables)["has_property_check"] =
(*variables)["property_name"] + " != " + (*variables)["default_value"];
(*variables)["other_has_property_check"] = "other." +
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 653ff992..7737ffe2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -77,6 +77,8 @@ std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor);
std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor);
+std::string GetClassName(const Descriptor* descriptor);
+
std::string GetClassName(const EnumDescriptor* descriptor);
std::string GetFieldName(const FieldDescriptor* descriptor);
@@ -119,10 +121,6 @@ inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
return descriptor->name() == "google/protobuf/descriptor_proto_file.proto";
}
-inline bool IsMapEntry(const Descriptor* descriptor) {
- return descriptor->options().map_entry();
-}
-
inline bool IsWrapperType(const FieldDescriptor* descriptor) {
return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index cba24a59..bdbfd92b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -79,6 +79,7 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 10cf3585..42fd5065 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -96,88 +96,11 @@ const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number()
return fields_by_number_;
}
-/// 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.
-std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) {
- std::string result = descriptor->full_name();
- std::replace(result.begin(), result.end(), '.', '_');
- return "static_" + result;
-}
-
-void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
- // Because descriptor.proto (Google.Protobuf.DescriptorProtos) is
- // used in the construction of descriptors, we have a tricky bootstrapping
- // problem. To help control static initialization order, we make sure all
- // descriptors and other static data that depends on them are members of
- // the proto-descriptor class. This way, they will be initialized in
- // a deterministic order.
-
- std::string identifier = GetUniqueFileScopeIdentifier(descriptor_);
-
- // The descriptor for this type.
- printer->Print(
- "internal static pbr::FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n",
- "identifier", GetUniqueFileScopeIdentifier(descriptor_),
- "full_class_name", full_class_name());
-
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- // Don't generate accessor table fields for maps...
- if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
- MessageGenerator messageGenerator(descriptor_->nested_type(i));
- messageGenerator.GenerateStaticVariables(printer);
- }
- }
-}
-
-void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) {
- map<string, string> vars;
- vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
- vars["full_class_name"] = full_class_name();
-
- // Work out how to get to the message descriptor (which may be multiply nested) from the file
- // descriptor.
- string descriptor_chain;
- const Descriptor* current_descriptor = descriptor_;
- while (current_descriptor->containing_type()) {
- descriptor_chain = ".NestedTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
- current_descriptor = current_descriptor->containing_type();
- }
- descriptor_chain = "descriptor.MessageTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
- vars["descriptor_chain"] = descriptor_chain;
-
- printer->Print(
- vars,
- "internal__$identifier$__FieldAccessorTable = \n"
- " new pbr::FieldAccessorTable(typeof($full_class_name$), $descriptor_chain$,\n");
- printer->Print(" new string[] { ");
- for (int i = 0; i < descriptor_->field_count(); i++) {
- printer->Print("\"$property_name$\", ",
- "property_name", GetPropertyName(descriptor_->field(i)));
- }
- printer->Print("}, new string[] { ");
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print("\"$oneof_name$\", ",
- "oneof_name",
- UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
- }
- printer->Print("});\n");
-
- // Generate static member initializers for all non-map-entry nested types.
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
- MessageGenerator messageGenerator(descriptor_->nested_type(i));
- messageGenerator.GenerateStaticVariableInitializers(printer);
- }
- }
-}
-
void MessageGenerator::Generate(io::Printer* printer) {
map<string, string> vars;
vars["class_name"] = class_name();
vars["access_level"] = class_access_level();
vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file());
- vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
printer->Print(
"[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
@@ -221,8 +144,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
" get { return $descriptor_accessor$; }\n"
"}\n"
"\n"
- "pbr::FieldAccessorTable pb::IReflectedMessage.Fields {\n"
- " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
+ "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+ " get { return Descriptor; }\n"
"}\n"
"\n"
"private bool _frozen = false;\n"
@@ -258,6 +181,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+ vars["original_name"] = descriptor_->oneof_decl(i)->name();
printer->Print(
vars,
"private object $name$_;\n"
@@ -275,9 +199,11 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print(
vars,
"private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
+ "[pbr::ProtobufOneof(\"$original_name$\")]\n"
"public $property_name$OneofCase $property_name$Case {\n"
" get { return $name$Case_; }\n"
"}\n\n"
+ "[pbr::ProtobufOneof(\"$original_name$\")]\n"
"public void Clear$property_name$() {\n"
" pb::Freezable.CheckMutable(this);\n"
" $name$Case_ = $property_name$OneofCase.None;\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index fbe8a3be..f0c49ac9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -53,8 +53,6 @@ class MessageGenerator : public SourceGeneratorBase {
void GenerateCloningCode(io::Printer* printer);
void GenerateFreezingCode(io::Printer* printer);
void GenerateFrameworkMethods(io::Printer* printer);
- void GenerateStaticVariables(io::Printer* printer);
- void GenerateStaticVariableInitializers(io::Printer* printer);
void Generate(io::Printer* printer);
private:
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index d2c3a88b..c2b6ff76 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -64,6 +64,7 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
@@ -158,6 +159,7 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
" set {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index 4454ef02..2c9338bd 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -71,6 +71,7 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
@@ -174,6 +175,7 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
" set {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index d5fc6d98..60d06154 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -59,12 +59,13 @@ void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
- " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);");
+ " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
printer->Print(variables_,
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index d939fc79..921798b0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -78,6 +78,7 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index 5b5d9b3d..bcfb9936 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -65,6 +65,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 57271d17..3f39250e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -63,12 +63,6 @@ UmbrellaClassGenerator::~UmbrellaClassGenerator() {
void UmbrellaClassGenerator::Generate(io::Printer* printer) {
WriteIntroduction(printer);
- printer->Print("#region Static variables\n");
- for (int i = 0; i < file_->message_type_count(); i++) {
- MessageGenerator messageGenerator(file_->message_type(i));
- messageGenerator.GenerateStaticVariables(printer);
- }
- printer->Print("#endregion\n");
WriteDescriptor(printer);
// Close the class declaration.
printer->Outdent();
@@ -183,24 +177,43 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
// Invoke InternalBuildGeneratedFileFrom() to build the file.
printer->Print(
"descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
- printer->Print(" new pbr::FileDescriptor[] {\n");
+ printer->Print(" new pbr::FileDescriptor[] { ");
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
- " $full_umbrella_class_name$.Descriptor, \n",
+ "$full_umbrella_class_name$.Descriptor, ",
"full_umbrella_class_name",
GetFullUmbrellaClassName(file_->dependency(i)));
}
- printer->Print(" });\n");
- // Then invoke any other static variable initializers, e.g. field accessors.
+ // Specify all the generated types (messages and enums), recursively, as an array.
+ printer->Print("},\n"
+ " new global::System.Type[] { ");
for (int i = 0; i < file_->message_type_count(); i++) {
- MessageGenerator messageGenerator(file_->message_type(i));
- messageGenerator.GenerateStaticVariableInitializers(printer);
+ WriteTypeLiterals(file_->message_type(i), printer);
}
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+ }
+ printer->Print("});\n");
+
printer->Outdent();
printer->Print("}\n");
printer->Print("#endregion\n\n");
}
+void UmbrellaClassGenerator::WriteTypeLiterals(const Descriptor* descriptor, io::Printer* printer) {
+ if (IsMapEntryMessage(descriptor)) {
+ printer->Print("null, ");
+ return;
+ }
+ printer->Print("typeof($type_name$), ", "type_name", GetClassName(descriptor));
+ for (int i = 0; i < descriptor->nested_type_count(); i++) {
+ WriteTypeLiterals(descriptor->nested_type(i), printer);
+ }
+ for (int i = 0; i < descriptor->enum_type_count(); i++) {
+ printer->Print("typeof($type_name$), ", "type_name", GetClassName(descriptor->enum_type(i)));
+ }
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
index f7533d2d..db1092a9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
@@ -57,6 +57,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase {
void WriteIntroduction(io::Printer* printer);
void WriteDescriptor(io::Printer* printer);
+ void WriteTypeLiterals(const Descriptor* descriptor, io::Printer* printer);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator);
};
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 75ef5e50..d6cd0a10 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -73,6 +73,7 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n"
@@ -169,6 +170,7 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
+ "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
" set {\n"