aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/csharp/csharp_helpers.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_helpers.cc')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.cc149
1 files changed, 66 insertions, 83 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 76e2c850..46f4fc33 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -46,11 +46,13 @@
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
namespace google {
namespace protobuf {
@@ -112,24 +114,21 @@ std::string GetFileNamespace(const FileDescriptor* descriptor) {
if (descriptor->options().has_csharp_namespace()) {
return descriptor->options().csharp_namespace();
}
- return descriptor->package();
+ return UnderscoresToCamelCase(descriptor->package(), true, true);
}
-std::string GetUmbrellaClassNameInternal(const std::string& proto_file) {
+std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor) {
+ // umbrella_classname can no longer be set using message option.
+ std::string proto_file = descriptor->name();
int lastslash = proto_file.find_last_of("/");
std::string base = proto_file.substr(lastslash + 1);
return UnderscoresToPascalCase(StripDotProto(base));
}
-std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) {
- // umbrella_classname can no longer be set using message option.
- return GetUmbrellaClassNameInternal(descriptor->name());
-}
-
-std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) {
+std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor) {
// TODO(jtattermusch): reintroduce csharp_umbrella_namespace option
bool collision = false;
- std::string umbrella_classname = GetFileUmbrellaClassname(descriptor);
+ std::string umbrella_classname = GetUmbrellaClassUnqualifiedName(descriptor);
for(int i = 0; i < descriptor->message_type_count(); i++) {
if (descriptor->message_type(i)->name() == umbrella_classname) {
collision = true;
@@ -153,7 +152,8 @@ std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) {
// TODO(jtattermusch): can we reuse a utility function?
std::string UnderscoresToCamelCase(const std::string& input,
- bool cap_next_letter) {
+ bool cap_next_letter,
+ bool preserve_period) {
string result;
// Note: I distrust ctype.h due to locales.
for (int i = 0; i < input.size(); i++) {
@@ -179,6 +179,9 @@ std::string UnderscoresToCamelCase(const std::string& input,
cap_next_letter = true;
} else {
cap_next_letter = true;
+ if (input[i] == '.' && preserve_period) {
+ result += '.';
+ }
}
}
// Add a trailing "_" if the name should be altered.
@@ -205,30 +208,21 @@ std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
// the C# namespace.
classname = name.substr(file->package().size() + 1);
}
- result += StringReplace(classname, ".", ".Types.", false);
+ result += StringReplace(classname, ".", ".Types.", true);
return "global::" + result;
}
-
-
-std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor) {
+std::string GetUmbrellaClassName(const FileDescriptor* descriptor) {
std::string result = GetFileNamespace(descriptor);
if (!result.empty()) {
result += '.';
}
- result += GetQualifiedUmbrellaClassName(descriptor);
- return "global::" + result;
-}
-
-std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor) {
- std::string umbrellaNamespace = GetFileUmbrellaNamespace(descriptor);
- std::string umbrellaClassname = GetFileUmbrellaClassname(descriptor);
-
- std::string fullName = umbrellaClassname;
+ std::string umbrellaNamespace = GetUmbrellaClassNestedNamespace(descriptor);
if (!umbrellaNamespace.empty()) {
- fullName = umbrellaNamespace + "." + umbrellaClassname;
+ result += umbrellaNamespace + ".";
}
- return fullName;
+ result += GetUmbrellaClassUnqualifiedName(descriptor);
+ return "global::" + result;
}
std::string GetClassName(const Descriptor* descriptor) {
@@ -257,7 +251,13 @@ std::string GetFieldConstantName(const FieldDescriptor* field) {
std::string GetPropertyName(const FieldDescriptor* descriptor) {
// TODO(jtattermusch): consider introducing csharp_property_name field option
std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
- if (property_name == descriptor->containing_type()->name()) {
+ // Avoid either our own type name or reserved names. Note that not all names
+ // are reserved - a field called to_string, write_to etc would still cause a problem.
+ // There are various ways of ending up with naming collisions, but we try to avoid obvious
+ // ones.
+ if (property_name == descriptor->containing_type()->name()
+ || property_name == "Types"
+ || property_name == "Descriptor") {
property_name += "_";
}
return property_name;
@@ -338,84 +338,67 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
return StringToBase64(fdp_bytes);
}
+// TODO(jonskeet): Remove this when internal::WireFormat::MakeTag works
+// properly...
+// Workaround for issue #493
+uint FixedMakeTag(const FieldDescriptor* field) {
+ internal::WireFormatLite::WireType field_type = field->is_packed()
+ ? internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED
+ : internal::WireFormat::WireTypeForFieldType(field->type());
+
+ return internal::WireFormatLite::MakeTag(field->number(), field_type);
+}
+
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
if (descriptor->is_repeated()) {
- return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+ if (descriptor->is_map()) {
+ return new MapFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+ }
} else {
- if (descriptor->containing_oneof()) {
- return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
- } else {
- return new MessageFieldGenerator(descriptor, fieldOrdinal);
- }
+ if (IsWrapperType(descriptor)) {
+ if (descriptor->containing_oneof()) {
+ return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+ }
+ } else {
+ if (descriptor->containing_oneof()) {
+ return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new MessageFieldGenerator(descriptor, fieldOrdinal);
+ }
+ }
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
} else {
- if (descriptor->containing_oneof()) {
- return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
- } else {
- return new EnumFieldGenerator(descriptor, fieldOrdinal);
- }
+ if (descriptor->containing_oneof()) {
+ return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new EnumFieldGenerator(descriptor, fieldOrdinal);
+ }
}
default:
if (descriptor->is_repeated()) {
return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
} else {
- if (descriptor->containing_oneof()) {
- return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
- } else {
- return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
- }
+ if (descriptor->containing_oneof()) {
+ return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+ } else {
+ return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+ }
}
}
}
-bool HasRequiredFields(const Descriptor* descriptor, std::set<const Descriptor*>* already_seen) {
- if (already_seen->find(descriptor) != already_seen->end()) {
- // 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(descriptor);
-
- // 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 (descriptor->extension_count() > 0) {
- return true;
- }
-
- for (int i = 0; i < descriptor->field_count(); i++) {
- const FieldDescriptor* field = descriptor->field(i);
- if (field->is_required()) {
- return true;
- }
- if (GetCSharpType(field->type()) == CSHARPTYPE_MESSAGE) {
- if (HasRequiredFields(field->message_type(), already_seen)) {
- return true;
- }
- }
- }
- return false;
-}
-
-bool HasRequiredFields(const Descriptor* descriptor) {
- std::set<const Descriptor*> already_seen;
- return HasRequiredFields(descriptor, &already_seen);
-}
-
-} // namespace java
+} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google