Enabled Nullable Reference Types (#136)
This commit is contained in:
parent
42b64441a1
commit
d3195acac0
@ -1,10 +1,14 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0' and !$(TargetFramework.StartsWith('netcoreapp2')) and !$(TargetFramework.StartsWith('net4'))">
|
<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0' and !$(TargetFramework.StartsWith('netcoreapp2')) and !$(TargetFramework.StartsWith('net4'))">
|
||||||
<DefineConstants>$(DefineConstants);HAS_ASYNC_ENUMERATOR</DefineConstants>
|
<DefineConstants>$(DefineConstants);HAS_ASYNC_ENUMERATOR</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
|
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
|
||||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
<IncludeSource>true</IncludeSource>
|
<IncludeSource>true</IncludeSource>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@ -7,9 +7,9 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
public class EnhancedStackFrame : StackFrame
|
public class EnhancedStackFrame : StackFrame
|
||||||
{
|
{
|
||||||
private string _fileName;
|
private readonly string? _fileName;
|
||||||
private int _lineNumber;
|
private readonly int _lineNumber;
|
||||||
private int _colNumber;
|
private readonly int _colNumber;
|
||||||
|
|
||||||
public StackFrame StackFrame { get; }
|
public StackFrame StackFrame { get; }
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
public ResolvedMethod MethodInfo { get; }
|
public ResolvedMethod MethodInfo { get; }
|
||||||
|
|
||||||
internal EnhancedStackFrame(StackFrame stackFrame, ResolvedMethod methodInfo, string fileName, int lineNumber, int colNumber)
|
internal EnhancedStackFrame(StackFrame stackFrame, ResolvedMethod methodInfo, string? fileName, int lineNumber, int colNumber)
|
||||||
: base(fileName, lineNumber, colNumber)
|
: base(fileName, lineNumber, colNumber)
|
||||||
{
|
{
|
||||||
StackFrame = stackFrame;
|
StackFrame = stackFrame;
|
||||||
@ -32,7 +32,7 @@ namespace System.Diagnostics
|
|||||||
_colNumber = colNumber;
|
_colNumber = colNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool IsEquivalent(ResolvedMethod methodInfo, string fileName, int lineNumber, int colNumber)
|
internal bool IsEquivalent(ResolvedMethod methodInfo, string? fileName, int lineNumber, int colNumber)
|
||||||
{
|
{
|
||||||
return _lineNumber == lineNumber &&
|
return _lineNumber == lineNumber &&
|
||||||
_colNumber == colNumber &&
|
_colNumber == colNumber &&
|
||||||
@ -59,7 +59,7 @@ namespace System.Diagnostics
|
|||||||
/// This information is typically extracted from the debugging symbols for the executable.
|
/// This information is typically extracted from the debugging symbols for the executable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The file name, or null if the file name cannot be determined.</returns>
|
/// <returns>The file name, or null if the file name cannot be determined.</returns>
|
||||||
public override string GetFileName() => _fileName;
|
public override string? GetFileName() => _fileName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the offset from the start of the Microsoft intermediate language (MSIL)
|
/// Gets the offset from the start of the Microsoft intermediate language (MSIL)
|
||||||
|
|||||||
@ -44,8 +44,8 @@ namespace System.Diagnostics
|
|||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnhancedStackFrame lastFrame = null;
|
EnhancedStackFrame? lastFrame = null;
|
||||||
PortablePdbReader portablePdbReader = null;
|
PortablePdbReader? portablePdbReader = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (var i = 0; i < stackFrames.Length; i++)
|
for (var i = 0; i < stackFrames.Length; i++)
|
||||||
@ -70,6 +70,12 @@ namespace System.Diagnostics
|
|||||||
(portablePdbReader ??= new PortablePdbReader()).PopulateStackFrame(frame, method, frame.GetILOffset(), out fileName, out row, out column);
|
(portablePdbReader ??= new PortablePdbReader()).PopulateStackFrame(frame, method, frame.GetILOffset(), out fileName, out row, out column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method is null)
|
||||||
|
{
|
||||||
|
// Method can't be null
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var resolvedMethod = GetMethodDisplayString(method);
|
var resolvedMethod = GetMethodDisplayString(method);
|
||||||
if (lastFrame?.IsEquivalent(resolvedMethod, fileName, row, column) ?? false)
|
if (lastFrame?.IsEquivalent(resolvedMethod, fileName, row, column) ?? false)
|
||||||
{
|
{
|
||||||
@ -85,11 +91,7 @@ namespace System.Diagnostics
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (portablePdbReader is not null)
|
portablePdbReader?.Dispose();
|
||||||
{
|
|
||||||
portablePdbReader.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
@ -97,12 +99,6 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
public static ResolvedMethod GetMethodDisplayString(MethodBase originMethod)
|
public static ResolvedMethod GetMethodDisplayString(MethodBase originMethod)
|
||||||
{
|
{
|
||||||
// Special case: no method available
|
|
||||||
if (originMethod == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var method = originMethod;
|
var method = originMethod;
|
||||||
|
|
||||||
var methodDisplayInfo = new ResolvedMethod
|
var methodDisplayInfo = new ResolvedMethod
|
||||||
@ -174,7 +170,7 @@ namespace System.Diagnostics
|
|||||||
if (value is Delegate d)
|
if (value is Delegate d)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(d.Method, originMethod) &&
|
if (ReferenceEquals(d.Method, originMethod) &&
|
||||||
d.Target.ToString() == originMethod.DeclaringType.ToString())
|
d.Target.ToString() == originMethod.DeclaringType?.ToString())
|
||||||
{
|
{
|
||||||
methodDisplayInfo.Name = field.Name;
|
methodDisplayInfo.Name = field.Name;
|
||||||
methodDisplayInfo.IsLambda = false;
|
methodDisplayInfo.IsLambda = false;
|
||||||
@ -208,11 +204,10 @@ namespace System.Diagnostics
|
|||||||
}
|
}
|
||||||
else if (mi.ReturnType != null)
|
else if (mi.ReturnType != null)
|
||||||
{
|
{
|
||||||
methodDisplayInfo.ReturnParameter = new ResolvedParameter
|
methodDisplayInfo.ReturnParameter = new ResolvedParameter(mi.ReturnType)
|
||||||
{
|
{
|
||||||
Prefix = "",
|
Prefix = "",
|
||||||
Name = "",
|
Name = "",
|
||||||
ResolvedType = mi.ReturnType,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,7 +273,7 @@ namespace System.Diagnostics
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryResolveGeneratedName(ref MethodBase method, out Type type, out string methodName, out string subMethodName, out GeneratedNameKind kind, out int? ordinal)
|
private static bool TryResolveGeneratedName(ref MethodBase method, out Type? type, out string methodName, out string? subMethodName, out GeneratedNameKind kind, out int? ordinal)
|
||||||
{
|
{
|
||||||
kind = GeneratedNameKind.None;
|
kind = GeneratedNameKind.None;
|
||||||
type = method.DeclaringType;
|
type = method.DeclaringType;
|
||||||
@ -364,15 +359,18 @@ namespace System.Diagnostics
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryResolveSourceMethod(IEnumerable<MethodBase> candidateMethods, GeneratedNameKind kind, string matchHint, ref MethodBase method, ref Type type, out int? ordinal)
|
private static bool TryResolveSourceMethod(IEnumerable<MethodBase> candidateMethods, GeneratedNameKind kind, string? matchHint, ref MethodBase method, ref Type type, out int? ordinal)
|
||||||
{
|
{
|
||||||
ordinal = null;
|
ordinal = null;
|
||||||
foreach (var candidateMethod in candidateMethods)
|
foreach (var candidateMethod in candidateMethods)
|
||||||
{
|
{
|
||||||
var methodBody = candidateMethod.GetMethodBody();
|
if (candidateMethod.GetMethodBody() is not { } methodBody)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (kind == GeneratedNameKind.LambdaMethod)
|
if (kind == GeneratedNameKind.LambdaMethod)
|
||||||
{
|
{
|
||||||
foreach (var v in EnumerableIList.Create(methodBody?.LocalVariables))
|
foreach (var v in EnumerableIList.Create(methodBody.LocalVariables))
|
||||||
{
|
{
|
||||||
if (v.LocalType == type)
|
if (v.LocalType == type)
|
||||||
{
|
{
|
||||||
@ -387,14 +385,13 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var rawIL = methodBody?.GetILAsByteArray();
|
var rawIl = methodBody.GetILAsByteArray();
|
||||||
if (rawIL == null) continue;
|
var reader = new ILReader(rawIl);
|
||||||
var reader = new ILReader(rawIL);
|
|
||||||
while (reader.Read(candidateMethod))
|
while (reader.Read(candidateMethod))
|
||||||
{
|
{
|
||||||
if (reader.Operand is MethodBase mb)
|
if (reader.Operand is MethodBase mb)
|
||||||
{
|
{
|
||||||
if (method == mb || (matchHint != null && method.Name.Contains(matchHint)))
|
if (method == mb || matchHint != null && method.Name.Contains(matchHint))
|
||||||
{
|
{
|
||||||
if (kind == GeneratedNameKind.LambdaMethod)
|
if (kind == GeneratedNameKind.LambdaMethod)
|
||||||
{
|
{
|
||||||
@ -462,7 +459,7 @@ namespace System.Diagnostics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static string GetMatchHint(GeneratedNameKind kind, MethodBase method)
|
static string? GetMatchHint(GeneratedNameKind kind, MethodBase method)
|
||||||
{
|
{
|
||||||
var methodName = method.Name;
|
var methodName = method.Name;
|
||||||
|
|
||||||
@ -590,28 +587,25 @@ namespace System.Diagnostics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameterType.IsByRef)
|
if (parameterType.IsByRef && parameterType.GetElementType() is {} elementType)
|
||||||
{
|
{
|
||||||
parameterType = parameterType.GetElementType();
|
parameterType = elementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResolvedParameter
|
return new ResolvedParameter(parameterType)
|
||||||
{
|
{
|
||||||
Prefix = prefix,
|
Prefix = prefix,
|
||||||
Name = parameter.Name,
|
Name = parameter.Name,
|
||||||
ResolvedType = parameterType,
|
|
||||||
IsDynamicType = parameter.IsDefined(typeof(DynamicAttribute), false)
|
IsDynamicType = parameter.IsDefined(typeof(DynamicAttribute), false)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResolvedParameter GetValueTupleParameter(IList<string> tupleNames, string prefix, string name, Type parameterType)
|
private static ResolvedParameter GetValueTupleParameter(IList<string> tupleNames, string prefix, string name, Type parameterType)
|
||||||
{
|
{
|
||||||
return new ValueTupleResolvedParameter
|
return new ValueTupleResolvedParameter(parameterType, tupleNames)
|
||||||
{
|
{
|
||||||
TupleNames = tupleNames,
|
|
||||||
Prefix = prefix,
|
Prefix = prefix,
|
||||||
Name = name,
|
Name = name,
|
||||||
ResolvedType = parameterType
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,8 +644,6 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
private static bool ShowInStackTrace(MethodBase method)
|
private static bool ShowInStackTrace(MethodBase method)
|
||||||
{
|
{
|
||||||
Debug.Assert(method != null);
|
|
||||||
|
|
||||||
// Since .NET 5:
|
// Since .NET 5:
|
||||||
// https://github.com/dotnet/runtime/blob/7c18d4d6488dab82124d475d1199def01d1d252c/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs#L348-L361
|
// https://github.com/dotnet/runtime/blob/7c18d4d6488dab82124d475d1199def01d1d252c/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs#L348-L361
|
||||||
if ((method.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining) != 0)
|
if ((method.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining) != 0)
|
||||||
|
|||||||
@ -102,11 +102,12 @@ namespace System.Diagnostics
|
|||||||
sb.Append(" at ");
|
sb.Append(" at ");
|
||||||
frame.MethodInfo.Append(sb);
|
frame.MethodInfo.Append(sb);
|
||||||
|
|
||||||
var filePath = frame.GetFileName();
|
if (frame.GetFileName() is {} fileName
|
||||||
if (!string.IsNullOrEmpty(filePath))
|
// IsNullOrEmpty alone wasn't enough to disable the null warning
|
||||||
|
&& !string.IsNullOrEmpty(fileName))
|
||||||
{
|
{
|
||||||
sb.Append(" in ");
|
sb.Append(" in ");
|
||||||
sb.Append(TryGetFullPath(filePath));
|
sb.Append(TryGetFullPath(fileName));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace System.Collections.Generic.Enumerable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
object IEnumerator.Current => Current;
|
object? IEnumerator.Current => Current;
|
||||||
public void Reset() => _index = -1;
|
public void Reset() => _index = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace System.Diagnostics.Internal
|
|||||||
|
|
||||||
public OpCode OpCode { get; private set; }
|
public OpCode OpCode { get; private set; }
|
||||||
public int MetadataToken { get; private set; }
|
public int MetadataToken { get; private set; }
|
||||||
public MemberInfo Operand { get; private set; }
|
public MemberInfo? Operand { get; private set; }
|
||||||
|
|
||||||
public bool Read(MethodBase methodInfo)
|
public bool Read(MethodBase methodInfo)
|
||||||
{
|
{
|
||||||
@ -38,7 +38,7 @@ namespace System.Diagnostics.Internal
|
|||||||
return doubleByteOpCode[ReadByte()];
|
return doubleByteOpCode[ReadByte()];
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberInfo ReadOperand(OpCode code, MethodBase methodInfo)
|
MemberInfo? ReadOperand(OpCode code, MethodBase methodInfo)
|
||||||
{
|
{
|
||||||
MetadataToken = 0;
|
MetadataToken = 0;
|
||||||
int inlineLength;
|
int inlineLength;
|
||||||
@ -46,12 +46,12 @@ namespace System.Diagnostics.Internal
|
|||||||
{
|
{
|
||||||
case OperandType.InlineMethod:
|
case OperandType.InlineMethod:
|
||||||
MetadataToken = ReadInt();
|
MetadataToken = ReadInt();
|
||||||
Type[] methodArgs = null;
|
Type[]? methodArgs = null;
|
||||||
if (methodInfo.GetType() != typeof(ConstructorInfo) && !methodInfo.GetType().IsSubclassOf(typeof(ConstructorInfo)))
|
if (methodInfo.GetType() != typeof(ConstructorInfo) && !methodInfo.GetType().IsSubclassOf(typeof(ConstructorInfo)))
|
||||||
{
|
{
|
||||||
methodArgs = methodInfo.GetGenericArguments();
|
methodArgs = methodInfo.GetGenericArguments();
|
||||||
}
|
}
|
||||||
Type[] typeArgs = null;
|
Type[]? typeArgs = null;
|
||||||
if (methodInfo.DeclaringType != null)
|
if (methodInfo.DeclaringType != null)
|
||||||
{
|
{
|
||||||
typeArgs = methodInfo.DeclaringType.GetGenericArguments();
|
typeArgs = methodInfo.DeclaringType.GetGenericArguments();
|
||||||
|
|||||||
@ -68,13 +68,13 @@ namespace System.Diagnostics.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MetadataReader GetMetadataReader(string assemblyPath)
|
private MetadataReader? GetMetadataReader(string assemblyPath)
|
||||||
{
|
{
|
||||||
if (!_cache.TryGetValue(assemblyPath, out var provider))
|
if (!_cache.TryGetValue(assemblyPath, out var provider))
|
||||||
{
|
{
|
||||||
var pdbPath = GetPdbPath(assemblyPath);
|
var pdbPath = GetPdbPath(assemblyPath);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(pdbPath) && File.Exists(pdbPath) && IsPortable(pdbPath))
|
if (!string.IsNullOrEmpty(pdbPath) && File.Exists(pdbPath) && IsPortable(pdbPath!))
|
||||||
{
|
{
|
||||||
var pdbStream = File.OpenRead(pdbPath);
|
var pdbStream = File.OpenRead(pdbPath);
|
||||||
provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
||||||
@ -86,7 +86,7 @@ namespace System.Diagnostics.Internal
|
|||||||
return provider?.GetMetadataReader();
|
return provider?.GetMetadataReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetPdbPath(string assemblyPath)
|
private static string? GetPdbPath(string assemblyPath)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(assemblyPath))
|
if (string.IsNullOrEmpty(assemblyPath))
|
||||||
{
|
{
|
||||||
@ -97,16 +97,16 @@ namespace System.Diagnostics.Internal
|
|||||||
{
|
{
|
||||||
var peStream = File.OpenRead(assemblyPath);
|
var peStream = File.OpenRead(assemblyPath);
|
||||||
|
|
||||||
using (var peReader = new PEReader(peStream))
|
using var peReader = new PEReader(peStream);
|
||||||
|
foreach (var entry in peReader.ReadDebugDirectory())
|
||||||
{
|
{
|
||||||
foreach (var entry in peReader.ReadDebugDirectory())
|
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
||||||
{
|
{
|
||||||
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
||||||
{
|
var peDirectory = Path.GetDirectoryName(assemblyPath);
|
||||||
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
return peDirectory is null
|
||||||
var peDirectory = Path.GetDirectoryName(assemblyPath);
|
? null
|
||||||
return Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path));
|
: Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,13 +116,11 @@ namespace System.Diagnostics.Internal
|
|||||||
|
|
||||||
private static bool IsPortable(string pdbPath)
|
private static bool IsPortable(string pdbPath)
|
||||||
{
|
{
|
||||||
using (var pdbStream = File.OpenRead(pdbPath))
|
using var pdbStream = File.OpenRead(pdbPath);
|
||||||
{
|
return pdbStream.ReadByte() == 'B' &&
|
||||||
return pdbStream.ReadByte() == 'B' &&
|
pdbStream.ReadByte() == 'S' &&
|
||||||
pdbStream.ReadByte() == 'S' &&
|
pdbStream.ReadByte() == 'J' &&
|
||||||
pdbStream.ReadByte() == 'J' &&
|
pdbStream.ReadByte() == 'B';
|
||||||
pdbStream.ReadByte() == 'B';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace System.Diagnostics.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ReflectionHelper
|
public static class ReflectionHelper
|
||||||
{
|
{
|
||||||
private static PropertyInfo tranformerNamesLazyPropertyInfo;
|
private static PropertyInfo? tranformerNamesLazyPropertyInfo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the <paramref name="type"/> is a value tuple type.
|
/// Returns true if the <paramref name="type"/> is a value tuple type.
|
||||||
@ -43,15 +43,15 @@ namespace System.Diagnostics.Internal
|
|||||||
/// To avoid compile-time depencency hell with System.ValueTuple, this method uses reflection
|
/// To avoid compile-time depencency hell with System.ValueTuple, this method uses reflection
|
||||||
/// instead of casting the attribute to a specific type.
|
/// instead of casting the attribute to a specific type.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static IList<string> GetTransformerNames(this Attribute attribute)
|
public static IList<string>? GetTransformerNames(this Attribute attribute)
|
||||||
{
|
{
|
||||||
Debug.Assert(attribute.IsTupleElementNameAttribue());
|
Debug.Assert(attribute.IsTupleElementNameAttribue());
|
||||||
|
|
||||||
var propertyInfo = GetTransformNamesPropertyInfo(attribute.GetType());
|
var propertyInfo = GetTransformNamesPropertyInfo(attribute.GetType());
|
||||||
return (IList<string>)propertyInfo.GetValue(attribute);
|
return propertyInfo?.GetValue(attribute) as IList<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyInfo GetTransformNamesPropertyInfo(Type attributeType)
|
private static PropertyInfo? GetTransformNamesPropertyInfo(Type attributeType)
|
||||||
{
|
{
|
||||||
return LazyInitializer.EnsureInitialized(ref tranformerNamesLazyPropertyInfo,
|
return LazyInitializer.EnsureInitialized(ref tranformerNamesLazyPropertyInfo,
|
||||||
() => attributeType.GetProperty("TransformNames", BindingFlags.Instance | BindingFlags.Public));
|
() => attributeType.GetProperty("TransformNames", BindingFlags.Instance | BindingFlags.Public));
|
||||||
|
|||||||
@ -9,27 +9,27 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
public class ResolvedMethod
|
public class ResolvedMethod
|
||||||
{
|
{
|
||||||
public MethodBase MethodBase { get; set; }
|
public MethodBase? MethodBase { get; set; }
|
||||||
|
|
||||||
public Type DeclaringType { get; set; }
|
public Type? DeclaringType { get; set; }
|
||||||
|
|
||||||
public bool IsAsync { get; set; }
|
public bool IsAsync { get; set; }
|
||||||
|
|
||||||
public bool IsLambda { get; set; }
|
public bool IsLambda { get; set; }
|
||||||
|
|
||||||
public ResolvedParameter ReturnParameter { get; set; }
|
public ResolvedParameter? ReturnParameter { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
public int? Ordinal { get; set; }
|
public int? Ordinal { get; set; }
|
||||||
|
|
||||||
public string GenericArguments { get; set; }
|
public string? GenericArguments { get; set; }
|
||||||
|
|
||||||
public Type[] ResolvedGenericArguments { get; set; }
|
public Type[]? ResolvedGenericArguments { get; set; }
|
||||||
|
|
||||||
public MethodBase SubMethodBase { get; set; }
|
public MethodBase? SubMethodBase { get; set; }
|
||||||
|
|
||||||
public string SubMethod { get; set; }
|
public string? SubMethod { get; set; }
|
||||||
|
|
||||||
public EnumerableIList<ResolvedParameter> Parameters { get; set; }
|
public EnumerableIList<ResolvedParameter> Parameters { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,15 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
public class ResolvedParameter
|
public class ResolvedParameter
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
public Type ResolvedType { get; set; }
|
public Type ResolvedType { get; set; }
|
||||||
|
|
||||||
public string Prefix { get; set; }
|
public string? Prefix { get; set; }
|
||||||
public bool IsDynamicType { get; set; }
|
public bool IsDynamicType { get; set; }
|
||||||
|
|
||||||
|
public ResolvedParameter(Type resolvedType) => ResolvedType = resolvedType;
|
||||||
|
|
||||||
public override string ToString() => Append(new StringBuilder()).ToString();
|
public override string ToString() => Append(new StringBuilder()).ToString();
|
||||||
|
|
||||||
public StringBuilder Append(StringBuilder sb)
|
public StringBuilder Append(StringBuilder sb)
|
||||||
|
|||||||
@ -9,25 +9,31 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
public class ValueTupleResolvedParameter : ResolvedParameter
|
public class ValueTupleResolvedParameter : ResolvedParameter
|
||||||
{
|
{
|
||||||
public IList<string> TupleNames { get; set; }
|
public IList<string> TupleNames { get; }
|
||||||
|
|
||||||
|
public ValueTupleResolvedParameter(Type resolvedType, IList<string> tupleNames)
|
||||||
|
: base(resolvedType)
|
||||||
|
=> TupleNames = tupleNames;
|
||||||
|
|
||||||
protected override void AppendTypeName(StringBuilder sb)
|
protected override void AppendTypeName(StringBuilder sb)
|
||||||
{
|
{
|
||||||
if (ResolvedType.IsValueTuple())
|
if (ResolvedType is not null)
|
||||||
{
|
{
|
||||||
AppendValueTupleParameterName(sb, ResolvedType);
|
if (ResolvedType.IsValueTuple())
|
||||||
}
|
{
|
||||||
else
|
AppendValueTupleParameterName(sb, ResolvedType);
|
||||||
{
|
}
|
||||||
// Need to unwrap the first generic argument first.
|
else
|
||||||
sb.Append(TypeNameHelper.GetTypeNameForGenericType(ResolvedType));
|
{
|
||||||
sb.Append("<");
|
// Need to unwrap the first generic argument first.
|
||||||
AppendValueTupleParameterName(sb, ResolvedType.GetGenericArguments()[0]);
|
sb.Append(TypeNameHelper.GetTypeNameForGenericType(ResolvedType));
|
||||||
sb.Append(">");
|
sb.Append("<");
|
||||||
|
AppendValueTupleParameterName(sb, ResolvedType.GetGenericArguments()[0]);
|
||||||
|
sb.Append(">");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void AppendValueTupleParameterName(StringBuilder sb, Type parameterType)
|
private void AppendValueTupleParameterName(StringBuilder sb, Type parameterType)
|
||||||
{
|
{
|
||||||
sb.Append("(");
|
sb.Append("(");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user