Merge pull request #5445 from haon4/master

Make Protobuf compatible with C# 6
This commit is contained in:
Hao Nguyen 2018-12-11 14:19:38 -08:00 committed by GitHub
commit 52fee0e8f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 53 deletions

View File

@ -120,7 +120,8 @@ namespace Google.Protobuf
return this;
}
if (!node.Children.TryGetValue(part, out var childNode))
Node childNode;
if (!node.Children.TryGetValue(part, out childNode))
{
createNewBranch = true;
childNode = new Node();
@ -361,4 +362,4 @@ namespace Google.Protobuf
}
}
}
}
}

View File

@ -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>

View File

@ -98,64 +98,65 @@ namespace Google.Protobuf.Reflection
}
}
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]);
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;
return null;
}
IReadOnlyList<DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);
DescriptorBase GetDescriptorFromList(IReadOnlyList<DescriptorBase> list, int index)
for (int i = 2; current != null && i < path.Count; i += 2)
{
// 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];
var list = current.GetNestedDescriptorListForField(path[i]);
current = GetDescriptorFromList(list, path[i + 1]);
}
return current;
}
IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
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)
{
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;
}
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];
}
private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int 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;
}
}
internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor)
{
declarations.Value.TryGetValue(descriptor, out var declaration);
DescriptorDeclaration declaration;
declarations.Value.TryGetValue(descriptor, out declaration);
return declaration;
}
@ -191,7 +192,8 @@ namespace Google.Protobuf.Reflection
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)
{
@ -414,7 +416,8 @@ namespace Google.Protobuf.Reflection
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}");
}

View File

@ -60,13 +60,22 @@ namespace Google.Protobuf.Reflection
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 =

View File

@ -308,7 +308,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <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>