Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Protobuf compatible with C# 6 #5445

Merged
3 commits merged into from Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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