Enabled Nullable Reference Types (#136)

This commit is contained in:
Bruno Garcia 2021-01-03 20:14:24 -05:00 committed by GitHub
parent 42b64441a1
commit d3195acac0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 97 additions and 93 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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));
} }

View File

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

View File

@ -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();

View File

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

View File

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

View File

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

View File

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

View File

@ -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("(");