Merge pull request #9182 from JamesNK/jamesnk/trimming-take3
[C#] Fix trim warnings
This commit is contained in:
commit
b79ac0e6e2
@ -182,10 +182,14 @@ csharp_EXTRA_DIST= \
|
||||
csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs \
|
||||
csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \
|
||||
csharp/src/Google.Protobuf/Collections/RepeatedField.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/DynamicallyAccessedMembersAttribute.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/DynamicallyAccessedMemberTypes.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/RequiresUnreferencedCodeAttribute.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs \
|
||||
csharp/src/Google.Protobuf/Compatibility/UnconditionalSuppressMessageAttribute.cs \
|
||||
csharp/src/Google.Protobuf/Extension.cs \
|
||||
csharp/src/Google.Protobuf/ExtensionRegistry.cs \
|
||||
csharp/src/Google.Protobuf/ExtensionSet.cs \
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!--
|
||||
This TestProtos project is kept separate from the original test project for many reasons.
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -35,6 +35,7 @@ using Google.Protobuf.TestProtos;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using NUnit.Framework;
|
||||
using ProtobufTestMessages.Proto2;
|
||||
using ProtobufTestMessages.Proto3;
|
||||
using System;
|
||||
using UnitTest.Issues.TestProtos;
|
||||
|
||||
@ -918,10 +919,10 @@ namespace Google.Protobuf
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("\"FOREIGN_BAR\"", ForeignEnum.ForeignBar)]
|
||||
[TestCase("5", ForeignEnum.ForeignBar)]
|
||||
[TestCase("100", (ForeignEnum)100)]
|
||||
public void EnumValid(string value, ForeignEnum expectedValue)
|
||||
[TestCase("\"FOREIGN_BAR\"", TestProtos.ForeignEnum.ForeignBar)]
|
||||
[TestCase("5", TestProtos.ForeignEnum.ForeignBar)]
|
||||
[TestCase("100", (TestProtos.ForeignEnum)100)]
|
||||
public void EnumValid(string value, TestProtos.ForeignEnum expectedValue)
|
||||
{
|
||||
string json = "{ \"singleForeignEnum\": " + value + " }";
|
||||
var parsed = TestAllTypes.Parser.ParseJson(json);
|
||||
@ -1021,5 +1022,128 @@ namespace Google.Protobuf
|
||||
{
|
||||
return '"' + text + '"';
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseAllNullValues()
|
||||
{
|
||||
string json = @"{
|
||||
""optionalInt32"": null,
|
||||
""optionalInt64"": null,
|
||||
""optionalUint32"": null,
|
||||
""optionalUint64"": null,
|
||||
""optionalSint32"": null,
|
||||
""optionalSint64"": null,
|
||||
""optionalFixed32"": null,
|
||||
""optionalFixed64"": null,
|
||||
""optionalSfixed32"": null,
|
||||
""optionalSfixed64"": null,
|
||||
""optionalFloat"": null,
|
||||
""optionalDouble"": null,
|
||||
""optionalBool"": null,
|
||||
""optionalString"": null,
|
||||
""optionalBytes"": null,
|
||||
""optionalNestedEnum"": null,
|
||||
""optionalNestedMessage"": null,
|
||||
""repeatedInt32"": null,
|
||||
""repeatedInt64"": null,
|
||||
""repeatedUint32"": null,
|
||||
""repeatedUint64"": null,
|
||||
""repeatedSint32"": null,
|
||||
""repeatedSint64"": null,
|
||||
""repeatedFixed32"": null,
|
||||
""repeatedFixed64"": null,
|
||||
""repeatedSfixed32"": null,
|
||||
""repeatedSfixed64"": null,
|
||||
""repeatedFloat"": null,
|
||||
""repeatedDouble"": null,
|
||||
""repeatedBool"": null,
|
||||
""repeatedString"": null,
|
||||
""repeatedBytes"": null,
|
||||
""repeatedNestedEnum"": null,
|
||||
""repeatedNestedMessage"": null,
|
||||
""mapInt32Int32"": null,
|
||||
""mapBoolBool"": null,
|
||||
""mapStringNestedMessage"": null
|
||||
}";
|
||||
|
||||
TestAllTypesProto3 message = new TestAllTypesProto3();
|
||||
|
||||
message.OptionalInt32 = 1;
|
||||
message.OptionalInt64 = 1;
|
||||
message.OptionalUint32 = 1;
|
||||
message.OptionalUint64 = 1;
|
||||
message.OptionalSint32 = 1;
|
||||
message.OptionalSint64 = 1;
|
||||
message.OptionalFixed32 = 1;
|
||||
message.OptionalFixed64 = 1;
|
||||
message.OptionalSfixed32 = 1;
|
||||
message.OptionalSfixed64 = 1;
|
||||
message.OptionalFloat = 1;
|
||||
message.OptionalDouble = 1;
|
||||
message.OptionalBool = true;
|
||||
message.OptionalString = "1";
|
||||
message.OptionalBytes = ByteString.CopyFrom(new byte[] { 1 });
|
||||
message.OptionalNestedEnum = TestAllTypesProto3.Types.NestedEnum.Bar;
|
||||
message.OptionalNestedMessage = new TestAllTypesProto3.Types.NestedMessage();
|
||||
message.RepeatedInt32.Add(1);
|
||||
message.RepeatedInt64.Add(1);
|
||||
message.RepeatedUint32.Add(1);
|
||||
message.RepeatedUint64.Add(1);
|
||||
message.RepeatedSint32.Add(1);
|
||||
message.RepeatedSint64.Add(1);
|
||||
message.RepeatedFixed32.Add(1);
|
||||
message.RepeatedFixed64.Add(1);
|
||||
message.RepeatedSfixed32.Add(1);
|
||||
message.RepeatedSfixed64.Add(1);
|
||||
message.RepeatedFloat.Add(1);
|
||||
message.RepeatedDouble.Add(1);
|
||||
message.RepeatedBool.Add(true);
|
||||
message.RepeatedString.Add("1");
|
||||
message.RepeatedBytes.Add(ByteString.CopyFrom(new byte[] { 1 }));
|
||||
message.RepeatedNestedEnum.Add(TestAllTypesProto3.Types.NestedEnum.Bar);
|
||||
message.RepeatedNestedMessage.Add(new TestAllTypesProto3.Types.NestedMessage());
|
||||
message.MapInt32Int32.Add(1, 1);
|
||||
message.MapBoolBool.Add(true, true);
|
||||
message.MapStringNestedMessage.Add(" ", new TestAllTypesProto3.Types.NestedMessage());
|
||||
|
||||
JsonParser.Default.Merge(message, json);
|
||||
|
||||
Assert.AreEqual(0, message.OptionalInt32);
|
||||
Assert.AreEqual(0, message.OptionalInt64);
|
||||
Assert.AreEqual(0, message.OptionalUint32);
|
||||
Assert.AreEqual(0, message.OptionalUint64);
|
||||
Assert.AreEqual(0, message.OptionalSint32);
|
||||
Assert.AreEqual(0, message.OptionalSint64);
|
||||
Assert.AreEqual(0, message.OptionalFixed32);
|
||||
Assert.AreEqual(0, message.OptionalFixed64);
|
||||
Assert.AreEqual(0, message.OptionalSfixed32);
|
||||
Assert.AreEqual(0, message.OptionalSfixed64);
|
||||
Assert.AreEqual(0, message.OptionalFloat);
|
||||
Assert.AreEqual(0, message.OptionalDouble);
|
||||
Assert.AreEqual(false, message.OptionalBool);
|
||||
Assert.AreEqual("", message.OptionalString);
|
||||
Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
|
||||
Assert.AreEqual(TestAllTypesProto3.Types.NestedEnum.Foo, message.OptionalNestedEnum);
|
||||
Assert.AreEqual(null, message.OptionalNestedMessage);
|
||||
Assert.AreEqual(0, message.RepeatedInt32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedInt64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedUint32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedUint64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSint32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSint64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFixed32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFixed64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSfixed32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFloat.Count);
|
||||
Assert.AreEqual(0, message.RepeatedDouble.Count);
|
||||
Assert.AreEqual(0, message.RepeatedBool.Count);
|
||||
Assert.AreEqual(0, message.RepeatedString.Count);
|
||||
Assert.AreEqual(0, message.RepeatedBytes.Count);
|
||||
Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
|
||||
Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
|
||||
Assert.AreEqual(0, message.MapInt32Int32.Count);
|
||||
Assert.AreEqual(0, message.MapBoolBool.Count);
|
||||
Assert.AreEqual(0, message.MapStringNestedMessage.Count);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
// Copied with permission from https://github.com/dotnet/runtime/tree/8fbf206d0e518b45ca855832e8bfb391afa85972/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the types of members that are dynamically accessed.
|
||||
///
|
||||
/// This enumeration has a <see cref="FlagsAttribute"/> attribute that allows a
|
||||
/// bitwise combination of its member values.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum DynamicallyAccessedMemberTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies no members.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the default, parameterless public constructor.
|
||||
/// </summary>
|
||||
PublicParameterlessConstructor = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public constructors.
|
||||
/// </summary>
|
||||
PublicConstructors = 0x0002 | PublicParameterlessConstructor,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public constructors.
|
||||
/// </summary>
|
||||
NonPublicConstructors = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public methods.
|
||||
/// </summary>
|
||||
PublicMethods = 0x0008,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public methods.
|
||||
/// </summary>
|
||||
NonPublicMethods = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public fields.
|
||||
/// </summary>
|
||||
PublicFields = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public fields.
|
||||
/// </summary>
|
||||
NonPublicFields = 0x0040,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public nested types.
|
||||
/// </summary>
|
||||
PublicNestedTypes = 0x0080,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public nested types.
|
||||
/// </summary>
|
||||
NonPublicNestedTypes = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public properties.
|
||||
/// </summary>
|
||||
PublicProperties = 0x0200,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public properties.
|
||||
/// </summary>
|
||||
NonPublicProperties = 0x0400,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all public events.
|
||||
/// </summary>
|
||||
PublicEvents = 0x0800,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all non-public events.
|
||||
/// </summary>
|
||||
NonPublicEvents = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all interfaces implemented by the type.
|
||||
/// </summary>
|
||||
Interfaces = 0x2000,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies all members.
|
||||
/// </summary>
|
||||
All = ~None
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,83 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
// Copied with permission from https://github.com/dotnet/runtime/tree/8fbf206d0e518b45ca855832e8bfb391afa85972/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that certain members on a specified <see cref="Type"/> are accessed dynamically,
|
||||
/// for example through <see cref="System.Reflection"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This allows tools to understand which members are being accessed during the execution
|
||||
/// of a program.
|
||||
///
|
||||
/// This attribute is valid on members whose type is <see cref="Type"/> or <see cref="string"/>.
|
||||
///
|
||||
/// When this attribute is applied to a location of type <see cref="string"/>, the assumption is
|
||||
/// that the string represents a fully qualified type name.
|
||||
///
|
||||
/// When this attribute is applied to a class, interface, or struct, the members specified
|
||||
/// can be accessed dynamically on <see cref="Type"/> instances returned from calling
|
||||
/// <see cref="object.GetType"/> on instances of that class, interface, or struct.
|
||||
///
|
||||
/// If the attribute is applied to a method it's treated as a special case and it implies
|
||||
/// the attribute should be applied to the "this" parameter of the method. As such the attribute
|
||||
/// should only be used on instance methods of types assignable to System.Type (or string, but no methods
|
||||
/// will use it there).
|
||||
/// </remarks>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
|
||||
AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
|
||||
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
|
||||
Inherited = false)]
|
||||
internal sealed class DynamicallyAccessedMembersAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicallyAccessedMembersAttribute"/> class
|
||||
/// with the specified member types.
|
||||
/// </summary>
|
||||
/// <param name="memberTypes">The types of members dynamically accessed.</param>
|
||||
public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
|
||||
{
|
||||
MemberTypes = memberTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DynamicallyAccessedMemberTypes"/> which specifies the type
|
||||
/// of members dynamically accessed.
|
||||
/// </summary>
|
||||
public DynamicallyAccessedMemberTypes MemberTypes { get; }
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,72 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
// Copied with permission from https://github.com/dotnet/runtime/tree/8fbf206d0e518b45ca855832e8bfb391afa85972/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the specified method requires dynamic access to code that is not referenced
|
||||
/// statically, for example through <see cref="System.Reflection"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This allows tools to understand which methods are unsafe to call when removing unreferenced
|
||||
/// code from an application.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
|
||||
internal sealed class RequiresUnreferencedCodeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequiresUnreferencedCodeAttribute"/> class
|
||||
/// with the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A message that contains information about the usage of unreferenced code.
|
||||
/// </param>
|
||||
public RequiresUnreferencedCodeAttribute(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a message that contains information about the usage of unreferenced code.
|
||||
/// </summary>
|
||||
public string Message { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional URL that contains more information about the method,
|
||||
/// why it requires unreferenced code, and what options a consumer has to deal with it.
|
||||
/// </summary>
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
@ -31,6 +31,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
|
||||
#if !NET35
|
||||
@ -59,7 +60,11 @@ namespace Google.Protobuf.Compatibility
|
||||
/// including inherited properties or null if there is no such public property.
|
||||
/// Here, "public property" means a property where either the getter, or the setter, or both, is public.
|
||||
/// </summary>
|
||||
internal static PropertyInfo GetProperty(this Type target, string name)
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2072",
|
||||
Justification = "The BaseType of the target will have all properties because of the annotation.")]
|
||||
internal static PropertyInfo GetProperty(
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
|
||||
this Type target, string name)
|
||||
{
|
||||
// GetDeclaredProperty only returns properties declared in the given type, so we need to recurse.
|
||||
while (target != null)
|
||||
@ -86,7 +91,11 @@ namespace Google.Protobuf.Compatibility
|
||||
/// class Child : Base declares public void Foo(long)).
|
||||
/// </remarks>
|
||||
/// <exception cref="AmbiguousMatchException">One type in the hierarchy declared more than one method with the same name</exception>
|
||||
internal static MethodInfo GetMethod(this Type target, string name)
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2072",
|
||||
Justification = "The BaseType of the target will have all properties because of the annotation.")]
|
||||
internal static MethodInfo GetMethod(
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
|
||||
this Type target, string name)
|
||||
{
|
||||
// GetDeclaredMethod only returns methods declared in the given type, so we need to recurse.
|
||||
while (target != null)
|
||||
|
@ -0,0 +1,117 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
// Copied with permission from https://github.com/dotnet/runtime/tree/8fbf206d0e518b45ca855832e8bfb391afa85972/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a
|
||||
/// single code artifact.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="UnconditionalSuppressMessageAttribute"/> is different than
|
||||
/// <see cref="SuppressMessageAttribute"/> in that it doesn't have a
|
||||
/// <see cref="ConditionalAttribute"/>. So it is always preserved in the compiled assembly.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class UnconditionalSuppressMessageAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnconditionalSuppressMessageAttribute"/>
|
||||
/// class, specifying the category of the tool and the identifier for an analysis rule.
|
||||
/// </summary>
|
||||
/// <param name="category">The category for the attribute.</param>
|
||||
/// <param name="checkId">The identifier of the analysis rule the attribute applies to.</param>
|
||||
public UnconditionalSuppressMessageAttribute(string category, string checkId)
|
||||
{
|
||||
Category = category;
|
||||
CheckId = checkId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the category identifying the classification of the attribute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="Category"/> property describes the tool or tool analysis category
|
||||
/// for which a message suppression attribute applies.
|
||||
/// </remarks>
|
||||
public string Category { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifier of the analysis tool rule to be suppressed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Concatenated together, the <see cref="Category"/> and <see cref="CheckId"/>
|
||||
/// properties form a unique check identifier.
|
||||
/// </remarks>
|
||||
public string CheckId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scope of the code that is relevant for the attribute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Scope property is an optional argument that specifies the metadata scope for which
|
||||
/// the attribute is relevant.
|
||||
/// </remarks>
|
||||
public string Scope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a fully qualified path that represents the target of the attribute.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="Target"/> property is an optional argument identifying the analysis target
|
||||
/// of the attribute. An example value is "System.IO.Stream.ctor():System.Void".
|
||||
/// Because it is fully qualified, it can be long, particularly for targets such as parameters.
|
||||
/// The analysis tool user interface should be capable of automatically formatting the parameter.
|
||||
/// </remarks>
|
||||
public string Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional argument expanding on exclusion criteria.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="MessageId "/> property is an optional argument that specifies additional
|
||||
/// exclusion where the literal metadata target is not sufficiently precise. For example,
|
||||
/// the <see cref="UnconditionalSuppressMessageAttribute"/> cannot be applied within a method,
|
||||
/// and it may be desirable to suppress a violation against a statement in the method that will
|
||||
/// give a rule violation, but not against all statements in the method.
|
||||
/// </remarks>
|
||||
public string MessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the justification for suppressing the code analysis message.
|
||||
/// </summary>
|
||||
public string Justification { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
@ -22,6 +22,7 @@
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<!-- Include PDB in the built .nupkg -->
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<IsTrimmable>true</IsTrimmable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
|
@ -40,6 +40,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
@ -879,6 +880,8 @@ namespace Google.Protobuf
|
||||
private static readonly Dictionary<System.Type, Dictionary<object, string>> dictionaries
|
||||
= new Dictionary<System.Type, Dictionary<object, string>>();
|
||||
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2072",
|
||||
Justification = "The field for the value must still be present. It will be returned by reflection, will be in this collection, and its name can be resolved.")]
|
||||
internal static string GetOriginalName(object value)
|
||||
{
|
||||
var enumType = value.GetType();
|
||||
@ -898,21 +901,13 @@ namespace Google.Protobuf
|
||||
return originalName;
|
||||
}
|
||||
|
||||
#if NET35
|
||||
// TODO: Consider adding functionality to TypeExtensions to avoid this difference.
|
||||
private static Dictionary<object, string> GetNameMapping(System.Type enumType) =>
|
||||
enumType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
|
||||
.Where(f => (f.GetCustomAttributes(typeof(OriginalNameAttribute), false)
|
||||
.FirstOrDefault() as OriginalNameAttribute)
|
||||
?.PreferredAlias ?? true)
|
||||
.ToDictionary(f => f.GetValue(null),
|
||||
f => (f.GetCustomAttributes(typeof(OriginalNameAttribute), false)
|
||||
.FirstOrDefault() as OriginalNameAttribute)
|
||||
// If the attribute hasn't been applied, fall back to the name of the field.
|
||||
?.Name ?? f.Name);
|
||||
#else
|
||||
private static Dictionary<object, string> GetNameMapping(System.Type enumType) =>
|
||||
enumType.GetTypeInfo().DeclaredFields
|
||||
private static Dictionary<object, string> GetNameMapping(
|
||||
[DynamicallyAccessedMembers(
|
||||
DynamicallyAccessedMemberTypes.PublicFields |
|
||||
DynamicallyAccessedMemberTypes.NonPublicFields)]
|
||||
System.Type enumType)
|
||||
{
|
||||
return enumType.GetTypeInfo().DeclaredFields
|
||||
.Where(f => f.IsStatic)
|
||||
.Where(f => f.GetCustomAttributes<OriginalNameAttribute>()
|
||||
.FirstOrDefault()?.PreferredAlias ?? true)
|
||||
@ -921,7 +916,7 @@ namespace Google.Protobuf
|
||||
.FirstOrDefault()
|
||||
// If the attribute hasn't been applied, fall back to the name of the field.
|
||||
?.Name ?? f.Name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ using Google.Protobuf.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
@ -63,6 +64,8 @@ namespace Google.Protobuf.Reflection
|
||||
/// </remarks>
|
||||
public sealed class CustomOptions
|
||||
{
|
||||
private const string UnreferencedCodeMessage = "CustomOptions is incompatible with trimming.";
|
||||
|
||||
private static readonly object[] EmptyParameters = new object[0];
|
||||
private readonly IDictionary<int, IExtensionValue> values;
|
||||
|
||||
@ -77,6 +80,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetBool(int field, out bool value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -85,6 +89,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetInt32(int field, out int value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -93,6 +98,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetInt64(int field, out long value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -102,6 +108,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetFixed32(int field, out uint value) => TryGetUInt32(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -111,6 +118,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetFixed64(int field, out ulong value) => TryGetUInt64(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -120,6 +128,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetSFixed32(int field, out int value) => TryGetInt32(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -129,6 +138,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetSFixed64(int field, out long value) => TryGetInt64(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -138,6 +148,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetSInt32(int field, out int value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -147,6 +158,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetSInt64(int field, out long value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -155,6 +167,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetUInt32(int field, out uint value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -163,6 +176,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetUInt64(int field, out ulong value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -171,6 +185,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetFloat(int field, out float value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -179,6 +194,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetDouble(int field, out double value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -187,6 +203,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetString(int field, out string value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -195,6 +212,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetBytes(int field, out ByteString value) => TryGetPrimitiveValue(field, out value);
|
||||
|
||||
/// <summary>
|
||||
@ -203,6 +221,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// <param name="field">The field to fetch the value for.</param>
|
||||
/// <param name="value">The output variable to populate.</param>
|
||||
/// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns>
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
public bool TryGetMessage<T>(int field, out T value) where T : class, IMessage, new()
|
||||
{
|
||||
if (values == null)
|
||||
@ -240,6 +259,7 @@ namespace Google.Protobuf.Reflection
|
||||
return false;
|
||||
}
|
||||
|
||||
[RequiresUnreferencedCode(UnreferencedCodeMessage)]
|
||||
private bool TryGetPrimitiveValue<T>(int field, out T value)
|
||||
{
|
||||
if (values == null)
|
||||
|
@ -452,7 +452,7 @@ namespace Google.Protobuf.Reflection
|
||||
}
|
||||
return IsMap ? new MapFieldAccessor(property, this)
|
||||
: IsRepeated ? new RepeatedFieldAccessor(property, this)
|
||||
: (IFieldAccessor) new SingleFieldAccessor(property, this);
|
||||
: (IFieldAccessor) new SingleFieldAccessor(ContainingType.ClrType, property, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Google.Protobuf.Reflection
|
||||
{
|
||||
@ -43,10 +44,19 @@ namespace Google.Protobuf.Reflection
|
||||
private static readonly string[] EmptyNames = new string[0];
|
||||
private static readonly GeneratedClrTypeInfo[] EmptyCodeInfo = new GeneratedClrTypeInfo[0];
|
||||
private static readonly Extension[] EmptyExtensions = new Extension[0];
|
||||
internal const DynamicallyAccessedMemberTypes MessageAccessibility =
|
||||
// Creating types
|
||||
DynamicallyAccessedMemberTypes.PublicConstructors |
|
||||
// Getting and setting properties
|
||||
DynamicallyAccessedMemberTypes.PublicProperties |
|
||||
DynamicallyAccessedMemberTypes.NonPublicProperties |
|
||||
// Calling presence methods
|
||||
DynamicallyAccessedMemberTypes.PublicMethods;
|
||||
|
||||
/// <summary>
|
||||
/// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
|
||||
/// </summary>
|
||||
[DynamicallyAccessedMembers(MessageAccessibility)]
|
||||
public Type ClrType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@ -88,7 +98,11 @@ namespace Google.Protobuf.Reflection
|
||||
/// Each array parameter may be null, to indicate a lack of values.
|
||||
/// The parameter order is designed to make it feasible to format the generated code readably.
|
||||
/// </summary>
|
||||
public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, Extension[] extensions, GeneratedClrTypeInfo[] nestedTypes)
|
||||
public GeneratedClrTypeInfo(
|
||||
// Preserve all public members on message types when trimming is enabled.
|
||||
// This ensures that members used by reflection, e.g. JSON serialization, are preserved.
|
||||
[DynamicallyAccessedMembers(MessageAccessibility)]
|
||||
Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, Extension[] extensions, GeneratedClrTypeInfo[] nestedTypes)
|
||||
{
|
||||
NestedTypes = nestedTypes ?? EmptyCodeInfo;
|
||||
NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes;
|
||||
@ -104,7 +118,11 @@ namespace Google.Protobuf.Reflection
|
||||
/// Each array parameter may be null, to indicate a lack of values.
|
||||
/// The parameter order is designed to make it feasible to format the generated code readably.
|
||||
/// </summary>
|
||||
public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes)
|
||||
public GeneratedClrTypeInfo(
|
||||
// Preserve all public members on message types when trimming is enabled.
|
||||
// This ensures that members used by reflection, e.g. JSON serialization, are preserved.
|
||||
[DynamicallyAccessedMembers(MessageAccessibility)]
|
||||
Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes)
|
||||
: this(clrType, parser, propertyNames, oneofNames, nestedEnums, null, nestedTypes)
|
||||
{
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
#if NET35
|
||||
@ -182,6 +183,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// a wrapper type, and handle the result appropriately.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[DynamicallyAccessedMembers(GeneratedClrTypeInfo.MessageAccessibility)]
|
||||
public Type ClrType { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
using Google.Protobuf.Compatibility;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Protobuf.Reflection
|
||||
@ -115,13 +116,15 @@ namespace Google.Protobuf.Reflection
|
||||
internal static Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method) =>
|
||||
GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageBool(method);
|
||||
|
||||
internal static Func<IMessage, bool> CreateIsInitializedCaller(Type msg) =>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Type parameter members are preserved with DynamicallyAccessedMembers on GeneratedClrTypeInfo.ctor clrType parameter.")]
|
||||
internal static Func<IMessage, bool> CreateIsInitializedCaller([DynamicallyAccessedMembers(GeneratedClrTypeInfo.MessageAccessibility)]Type msg) =>
|
||||
((IExtensionSetReflector)Activator.CreateInstance(typeof(ExtensionSetReflector<>).MakeGenericType(msg))).CreateIsInitializedCaller();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a delegate which will execute the given method after casting the first argument to
|
||||
/// the type that declares the method, and the second argument to the first parameter type of the method.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Type parameter members are preserved with DynamicallyAccessedMembers on GeneratedClrTypeInfo.ctor clrType parameter.")]
|
||||
internal static IExtensionReflectionHelper CreateExtensionHelper(Extension extension) =>
|
||||
(IExtensionReflectionHelper)Activator.CreateInstance(typeof(ExtensionReflectionHelper<,>).MakeGenericType(extension.TargetType, extension.GetType().GenericTypeArguments[1]), extension);
|
||||
|
||||
@ -131,6 +134,7 @@ namespace Google.Protobuf.Reflection
|
||||
/// they can be garbage collected. We could cache them by type if that proves to be important, but creating
|
||||
/// an object is pretty cheap.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Type parameter members are preserved with DynamicallyAccessedMembers on GeneratedClrTypeInfo.ctor clrType parameter.")]
|
||||
private static IReflectionHelper GetReflectionHelper(Type t1, Type t2) =>
|
||||
(IReflectionHelper) Activator.CreateInstance(typeof(ReflectionHelper<,>).MakeGenericType(t1, t2));
|
||||
|
||||
@ -308,16 +312,14 @@ namespace Google.Protobuf.Reflection
|
||||
}
|
||||
}
|
||||
|
||||
private class ExtensionSetReflector<T1> : IExtensionSetReflector where T1 : IExtendableMessage<T1>
|
||||
private class ExtensionSetReflector<
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
|
||||
T1> : IExtensionSetReflector where T1 : IExtendableMessage<T1>
|
||||
{
|
||||
public Func<IMessage, bool> CreateIsInitializedCaller()
|
||||
{
|
||||
var prop = typeof(T1).GetTypeInfo().GetDeclaredProperty("_Extensions");
|
||||
#if NET35
|
||||
var getFunc = (Func<T1, ExtensionSet<T1>>)prop.GetGetMethod(true).CreateDelegate(typeof(Func<T1, ExtensionSet<T1>>));
|
||||
#else
|
||||
var getFunc = (Func<T1, ExtensionSet<T1>>)prop.GetMethod.CreateDelegate(typeof(Func<T1, ExtensionSet<T1>>));
|
||||
#endif
|
||||
var initializedFunc = (Func<ExtensionSet<T1>, bool>)
|
||||
typeof(ExtensionSet<T1>)
|
||||
.GetTypeInfo()
|
||||
|
@ -31,6 +31,8 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using Google.Protobuf.Compatibility;
|
||||
|
||||
@ -50,7 +52,9 @@ namespace Google.Protobuf.Reflection
|
||||
private readonly Action<IMessage> clearDelegate;
|
||||
private readonly Func<IMessage, bool> hasDelegate;
|
||||
|
||||
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
|
||||
internal SingleFieldAccessor(
|
||||
[DynamicallyAccessedMembers(GeneratedClrTypeInfo.MessageAccessibility)]
|
||||
Type messageType, PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
|
||||
{
|
||||
if (!property.CanWrite)
|
||||
{
|
||||
@ -87,13 +91,13 @@ namespace Google.Protobuf.Reflection
|
||||
// Primitive fields always support presence in proto2, and support presence in proto3 for optional fields.
|
||||
else if (descriptor.File.Syntax == Syntax.Proto2 || descriptor.Proto.Proto3Optional)
|
||||
{
|
||||
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
|
||||
MethodInfo hasMethod = messageType.GetRuntimeProperty("Has" + property.Name).GetMethod;
|
||||
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);
|
||||
MethodInfo clearMethod = messageType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
|
||||
if (clearMethod == null)
|
||||
{
|
||||
throw new ArgumentException("Not all required properties/methods are available");
|
||||
@ -107,16 +111,48 @@ namespace Google.Protobuf.Reflection
|
||||
hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); };
|
||||
|
||||
// While presence isn't supported, clearing still is; it's just setting to a default value.
|
||||
var clrType = property.PropertyType;
|
||||
|
||||
object defaultValue =
|
||||
clrType == typeof(string) ? ""
|
||||
: clrType == typeof(ByteString) ? ByteString.Empty
|
||||
: Activator.CreateInstance(clrType);
|
||||
object defaultValue = GetDefaultValue(descriptor);
|
||||
clearDelegate = message => SetValue(message, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static object GetDefaultValue(FieldDescriptor descriptor)
|
||||
{
|
||||
switch (descriptor.FieldType)
|
||||
{
|
||||
case FieldType.Bool:
|
||||
return false;
|
||||
case FieldType.Bytes:
|
||||
return ByteString.Empty;
|
||||
case FieldType.String:
|
||||
return "";
|
||||
case FieldType.Double:
|
||||
return 0.0;
|
||||
case FieldType.SInt32:
|
||||
case FieldType.Int32:
|
||||
case FieldType.SFixed32:
|
||||
case FieldType.Enum:
|
||||
return 0;
|
||||
case FieldType.Fixed32:
|
||||
case FieldType.UInt32:
|
||||
return (uint)0;
|
||||
case FieldType.Fixed64:
|
||||
case FieldType.UInt64:
|
||||
return 0UL;
|
||||
case FieldType.SFixed64:
|
||||
case FieldType.Int64:
|
||||
case FieldType.SInt64:
|
||||
return 0L;
|
||||
case FieldType.Float:
|
||||
return 0f;
|
||||
case FieldType.Message:
|
||||
case FieldType.Group: // Never expect to get this, but...
|
||||
return null;
|
||||
default:
|
||||
throw new ArgumentException("Invalid field type");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Clear(IMessage message) => clearDelegate(message);
|
||||
public override bool HasValue(IMessage message) => hasDelegate(message);
|
||||
public override void SetValue(IMessage message, object value) => setValueDelegate(message, value);
|
||||
|
@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Google.Protobuf.Reflection;
|
||||
@ -115,7 +116,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Parses from a string to a FieldMask and validates all field paths.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static FieldMask FromString<T>(string value) where T : IMessage
|
||||
public static FieldMask FromString<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(string value) where T : IMessage
|
||||
{
|
||||
return FromStringEnumerable<T>(new List<string>(value.Split(FIELD_PATH_SEPARATOR)));
|
||||
}
|
||||
@ -124,7 +125,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Constructs a FieldMask for a list of field paths in a certain type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static FieldMask FromStringEnumerable<T>(IEnumerable<string> paths) where T : IMessage
|
||||
public static FieldMask FromStringEnumerable<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(IEnumerable<string> paths) where T : IMessage
|
||||
{
|
||||
var mask = new FieldMask();
|
||||
foreach (var path in paths)
|
||||
@ -151,7 +152,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Constructs a FieldMask from the passed field numbers.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static FieldMask FromFieldNumbers<T>(params int[] fieldNumbers) where T : IMessage
|
||||
public static FieldMask FromFieldNumbers<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(params int[] fieldNumbers) where T : IMessage
|
||||
{
|
||||
return FromFieldNumbers<T>((IEnumerable<int>)fieldNumbers);
|
||||
}
|
||||
@ -160,7 +161,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Constructs a FieldMask from the passed field numbers.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static FieldMask FromFieldNumbers<T>(IEnumerable<int> fieldNumbers) where T : IMessage
|
||||
public static FieldMask FromFieldNumbers<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(IEnumerable<int> fieldNumbers) where T : IMessage
|
||||
{
|
||||
var descriptor = Activator.CreateInstance<T>().Descriptor;
|
||||
|
||||
@ -208,7 +209,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Checks whether paths in a given fields mask are valid.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static bool IsValid<T>(FieldMask fieldMask) where T : IMessage
|
||||
public static bool IsValid<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(FieldMask fieldMask) where T : IMessage
|
||||
{
|
||||
var descriptor = Activator.CreateInstance<T>().Descriptor;
|
||||
|
||||
@ -235,7 +236,7 @@ namespace Google.Protobuf.WellKnownTypes
|
||||
/// Checks whether a given field path is valid.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to validate the field paths against.</typeparam>
|
||||
public static bool IsValid<T>(string path) where T : IMessage
|
||||
public static bool IsValid<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>(string path) where T : IMessage
|
||||
{
|
||||
var descriptor = Activator.CreateInstance<T>().Descriptor;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user