Skip to content

Commit

Permalink
Merge pull request #5445 from haon4/master
Browse files Browse the repository at this point in the history
Make Protobuf compatible with C# 6
  • Loading branch information
Hao Nguyen authored Dec 11, 2018
2 parents 1d90079 + db0a9e0 commit 52fee0e
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 52 deletions.
5 changes: 3 additions & 2 deletions csharp/src/Google.Protobuf/FieldMaskTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ public FieldMaskTree AddFieldPath(string path)
return this;
}

if (!node.Children.TryGetValue(part, out var childNode))
Node childNode;
if (!node.Children.TryGetValue(part, out childNode))
{
createNewBranch = true;
childNode = new Node();
Expand Down Expand Up @@ -361,4 +362,4 @@ private void Merge(
}
}
}
}
}
1 change: 1 addition & 0 deletions csharp/src/Google.Protobuf/Google.Protobuf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.6.1</VersionPrefix>
<LangVersion>6</LangVersion>
<Authors>Google Inc.</Authors>
<TargetFrameworks>netstandard1.0;net45</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down
95 changes: 49 additions & 46 deletions csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,64 +98,65 @@ private Dictionary<IDescriptor, DescriptorDeclaration> CreateDeclarationMap()
}
}
return dictionary;
}

IDescriptor FindDescriptorForPath(IList<int> path)
private IDescriptor FindDescriptorForPath(IList<int> path)
{
// All complete declarations have an even, non-empty path length
// (There can be an empty path for a descriptor declaration, but that can't have any comments,
// so we currently ignore it.)
if (path.Count == 0 || (path.Count & 1) != 0)
{
// All complete declarations have an even, non-empty path length
// (There can be an empty path for a descriptor declaration, but that can't have any comments,
// so we currently ignore it.)
if (path.Count == 0 || (path.Count & 1) != 0)
{
return null;
}
IReadOnlyList<DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);
return null;
}
IReadOnlyList<DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);

for (int i = 2; current != null && i < path.Count; i += 2)
{
var list = current.GetNestedDescriptorListForField(path[i]);
current = GetDescriptorFromList(list, path[i + 1]);
}
return current;
for (int i = 2; current != null && i < path.Count; i += 2)
{
var list = current.GetNestedDescriptorListForField(path[i]);
current = GetDescriptorFromList(list, path[i + 1]);
}
return current;
}

DescriptorBase GetDescriptorFromList(IReadOnlyList<DescriptorBase> list, int index)
private DescriptorBase GetDescriptorFromList(IReadOnlyList<DescriptorBase> list, int index)
{
// This is fine: it may be a newer version of protobuf than we understand, with a new descriptor
// field.
if (list == null)
{
// This is fine: it may be a newer version of protobuf than we understand, with a new descriptor
// field.
if (list == null)
{
return null;
}
// We *could* return null to silently continue, but this is basically data corruption.
if (index < 0 || index >= list.Count)
{
// We don't have much extra information to give at this point unfortunately. If this becomes a problem,
// we can pass in the complete path and report that and the file name.
throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range");
}
return list[index];
return null;
}
// We *could* return null to silently continue, but this is basically data corruption.
if (index < 0 || index >= list.Count)
{
// We don't have much extra information to give at this point unfortunately. If this becomes a problem,
// we can pass in the complete path and report that and the file name.
throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range");
}
return list[index];
}

IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{
switch (fieldNumber)
{
case FileDescriptorProto.ServiceFieldNumber:
return (IReadOnlyList<DescriptorBase>) Services;
case FileDescriptorProto.MessageTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) MessageTypes;
case FileDescriptorProto.EnumTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) EnumTypes;
default:
return null;
}
case FileDescriptorProto.ServiceFieldNumber:
return (IReadOnlyList<DescriptorBase>) Services;
case FileDescriptorProto.MessageTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) MessageTypes;
case FileDescriptorProto.EnumTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) EnumTypes;
default:
return null;
}
}

internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor)
{
declarations.Value.TryGetValue(descriptor, out var declaration);
DescriptorDeclaration declaration;
declarations.Value.TryGetValue(descriptor, out declaration);
return declaration;
}

Expand Down Expand Up @@ -191,7 +192,8 @@ private static IList<FileDescriptor> DeterminePublicDependencies(FileDescriptor
throw new DescriptorValidationException(@this, "Invalid public dependency index.");
}
string name = proto.Dependency[index];
if (!nameToFileMap.TryGetValue(name, out var file))
FileDescriptor file;
if (!nameToFileMap.TryGetValue(name, out file))
{
if (!allowUnknownDependencies)
{
Expand Down Expand Up @@ -414,7 +416,8 @@ public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<Byt
var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency)
{
if (!descriptorsByName.TryGetValue(dependencyName, out var dependency))
FileDescriptor dependency;
if (!descriptorsByName.TryGetValue(dependencyName, out dependency))
{
throw new ArgumentException($"Dependency missing: {dependencyName}");
}
Expand Down
15 changes: 12 additions & 3 deletions csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,22 @@ internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor)
if (descriptor.File.Proto.Syntax == "proto2")
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
if (hasMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
if (clearMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
else
{
hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType;
hasDelegate = message => {
throw new InvalidOperationException("HasValue is not implemented for proto3 fields");
};
var clrType = property.PropertyType;

// TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
object defaultValue =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public int CompareTo(Timestamp other)
/// <returns>true if the two timestamps refer to the same nanosecond</returns>
public static bool operator ==(Timestamp a, Timestamp b)
{
return ReferenceEquals(a, b) || (a is null ? (b is null ? true : false) : a.Equals(b));
return ReferenceEquals(a, b) || (ReferenceEquals(a, null) ? (ReferenceEquals(b, null) ? true : false) : a.Equals(b));
}

/// <summary>
Expand Down

0 comments on commit 52fee0e

Please sign in to comment.