Browse Source

Enable nullable reference types across the C# AST consumers

Turn on #nullable enable across the AST consumer layer: the output visitor, the
IL-to-C# builders (statement, call and expression builders, CSharpDecompiler,
TypeSystemAstBuilder), the translation-result wrappers, the sequence-point and
required-namespace collectors, and the annotation helpers. Optional inputs,
fields and returns are typed nullable, detector out-parameters use
[NotNullWhen(true)], and structurally-guaranteed dereferences use the
null-forgiving operator. A few public parameters that already tolerate null are
widened to match their downstream callers. The annotations emit no IL, so the
Pretty suite stays byte-identical.
Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3807/head
Siegfried Pammer 3 months ago committed by Siegfried Pammer
parent
commit
2ea569b005
  1. 10
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  2. 116
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs
  4. 131
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  5. 101
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  6. 4
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs
  7. 30
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  8. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs
  9. 8
      ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs
  10. 6
      ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs
  11. 15
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs
  12. 18
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  13. 4
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs
  14. 14
      ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs
  15. 14
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  16. 14
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  17. 83
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  18. 5
      ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs
  19. 103
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  20. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  21. 13
      ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs
  22. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
  23. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs
  24. 6
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  25. 14
      ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs
  26. 6
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  27. 2
      ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs
  28. 2
      ICSharpCode.Decompiler/CSharp/TranslationContext.cs
  29. 2
      ILSpy/Languages/CSharpHighlightingTokenWriter.cs

10
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.IL; @@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
// Annotations:
@ -134,7 +136,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -134,7 +136,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// Retrieves the <see cref="ISymbol"/> associated with this AstNode, or null if no symbol
/// is associated with the node.
/// </summary>
public static ISymbol GetSymbol(this AstNode node)
public static ISymbol? GetSymbol(this AstNode node)
{
var rr = node.Annotation<ResolveResult>();
if (rr is MethodGroupResolveResult mgrr)
@ -157,7 +159,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -157,7 +159,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// Retrieves the <see cref="ILVariable"/> associated with this <see cref="IdentifierExpression"/>,
/// or <c>null</c> if no variable is associated with this identifier.
/// </summary>
public static ILVariable GetILVariable(this IdentifierExpression expr)
public static ILVariable? GetILVariable(this IdentifierExpression expr)
{
if (expr.Annotation<ResolveResult>() is ILVariableResolveResult rr)
return rr.Variable;
@ -169,7 +171,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -169,7 +171,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// Retrieves the <see cref="ILVariable"/> associated with this <see cref="VariableInitializer"/>,
/// or <c>null</c> if no variable is associated with this initializer.
/// </summary>
public static ILVariable GetILVariable(this VariableInitializer vi)
public static ILVariable? GetILVariable(this VariableInitializer vi)
{
if (vi.Annotation<ResolveResult>() is ILVariableResolveResult rr)
return rr.Variable;
@ -181,7 +183,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -181,7 +183,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// Retrieves the <see cref="ILVariable"/> associated with this <see cref="ForeachStatement"/>,
/// or <c>null</c> if no variable is associated with this foreach statement.
/// </summary>
public static ILVariable GetILVariable(this ForeachStatement loop)
public static ILVariable? GetILVariable(this ForeachStatement loop)
{
if (loop.Annotation<ResolveResult>() is ILVariableResolveResult rr)
return rr.Variable;

116
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
@ -45,6 +46,8 @@ using ICSharpCode.Decompiler.Util; @@ -45,6 +46,8 @@ using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
@ -60,7 +63,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -60,7 +63,7 @@ namespace ICSharpCode.Decompiler.CSharp
readonly MetadataModule module;
readonly MetadataReader metadata;
readonly DecompilerSettings settings;
SyntaxTree syntaxTree;
SyntaxTree? syntaxTree;
List<IILTransform> ilTransforms = GetILTransforms();
@ -210,12 +213,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -210,12 +213,12 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// Gets or sets the optional provider for debug info.
/// </summary>
public IDebugInfoProvider DebugInfoProvider { get; set; }
public IDebugInfoProvider? DebugInfoProvider { get; set; }
/// <summary>
/// Gets or sets the optional provider for XML documentation strings.
/// </summary>
public IDocumentationProvider DocumentationProvider { get; set; }
public IDocumentationProvider? DocumentationProvider { get; set; }
/// <summary>
/// IL transforms.
@ -275,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -275,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// <param name="module">The module containing the member.</param>
/// <param name="member">The metadata token/handle of the member. Can be a TypeDef, MethodDef or FieldDef.</param>
/// <param name="settings">The settings used to determine whether code should be hidden. E.g. if async methods are not transformed, async state machines are included in the decompiled code.</param>
public static bool MemberIsHidden(MetadataFile module, EntityHandle member, DecompilerSettings settings)
public static bool MemberIsHidden(MetadataFile? module, EntityHandle member, DecompilerSettings settings)
{
if (module == null || member.IsNil)
return false;
@ -671,7 +674,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -671,7 +674,7 @@ namespace ICSharpCode.Decompiler.CSharp
return typeSystemAstBuilder;
}
IDocumentationProvider CreateDefaultDocumentationProvider()
IDocumentationProvider? CreateDefaultDocumentationProvider()
{
try
{
@ -783,8 +786,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -783,8 +786,8 @@ namespace ICSharpCode.Decompiler.CSharp
void DoDecompileTypes(IEnumerable<TypeDefinitionHandle> types, DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{
string currentNamespace = null;
AstNode groupNode = null;
string? currentNamespace = null;
AstNode? groupNode = null;
foreach (var typeDefHandle in types)
{
var typeDef = module.GetDefinition(typeDefHandle);
@ -806,7 +809,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -806,7 +809,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
currentNamespace = typeDef.Namespace;
var typeDecl = DoDecompile(typeDef, decompileRun, decompilationContext.WithCurrentTypeDefinition(typeDef));
groupNode.AddChild(typeDecl, SlotKind.Member);
groupNode!.AddChild(typeDecl, SlotKind.Member);
}
}
@ -1189,7 +1192,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1189,7 +1192,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
if (type.ParentModule != typeSystem.MainModule)
throw new NotSupportedException($"Type {fullTypeName} was not found in the module being decompiled, but only in {type.ParentModule.Name}");
throw new NotSupportedException($"Type {fullTypeName} was not found in the module being decompiled, but only in {type.ParentModule!.Name}");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var namespaces = new HashSet<string>();
syntaxTree = new SyntaxTree();
@ -1237,8 +1240,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1237,8 +1240,8 @@ namespace ICSharpCode.Decompiler.CSharp
var decompileRun = CreateDecompileRun(namespaces);
bool first = true;
ITypeDefinition parentTypeDef = null;
ExtensionInfo parentExtensionInfo = null;
ITypeDefinition? parentTypeDef = null;
ExtensionInfo? parentExtensionInfo = null;
foreach (var entity in definitions)
{
@ -1341,7 +1344,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1341,7 +1344,7 @@ namespace ICSharpCode.Decompiler.CSharp
extensionInfo = propDef.ResolveExtensionInfo();
Debug.Assert(extensionInfo != null);
var accessor = propDef.Getter ?? propDef.Setter;
memberInfo = extensionInfo.InfoOfExtensionMember((IMethod)accessor.MemberDefinition).GetValueOrDefault();
memberInfo = extensionInfo.InfoOfExtensionMember((IMethod)accessor!.MemberDefinition).GetValueOrDefault();
subst = new TypeParameterSubstitution(memberInfo.ExtensionGroupingTypeParameters, null);
propDef = (IProperty)propDef.Specialize(subst);
EntityDeclaration prop = DoDecompile(propDef, decompileRun, new SimpleTypeResolveContext(propDef), extensionInfo);
@ -1363,7 +1366,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1363,7 +1366,7 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree;
}
ITypeDefinition FindCommonDeclaringTypeDefinition(ITypeDefinition a, ITypeDefinition b)
ITypeDefinition? FindCommonDeclaringTypeDefinition(ITypeDefinition? a, ITypeDefinition? b)
{
if (a == null || b == null)
return null;
@ -1427,7 +1430,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1427,7 +1430,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (m == null || m.DeclaringType.Kind != TypeKind.Interface)
continue;
var methodDecl = new MethodDeclaration();
methodDecl.ReturnType = memberDecl.ReturnType?.Clone();
// EntityDeclaration.ReturnType is typed non-null but its getter yields null when the Type
// slot is empty; leave the forwarder's (already empty) return-type slot untouched in that case.
if (memberDecl.ReturnType is { } memberReturnType)
methodDecl.ReturnType = memberReturnType.Clone();
methodDecl.PrivateImplementationType = astBuilder.ConvertType(m.DeclaringType);
methodDecl.Name = m.Name;
methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole<TypeParameterDeclaration>(SlotKind.TypeParameter)
@ -1483,7 +1489,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1483,7 +1489,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (member is ExtensionDeclaration)
return;
var entity = (IEntity)member.GetSymbol();
var entity = (IEntity)member.GetSymbol()!;
var lookup = new MemberLookup(entity.DeclaringTypeDefinition, entity.ParentModule);
var baseTypes = entity.DeclaringType.GetNonInterfaceBaseTypes().Where(t => entity.DeclaringType != t).ToList();
@ -1592,8 +1598,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1592,8 +1598,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (entityDecl is ExtensionDeclaration ext && settings.ExtensionMembers)
{
var extensionInfo = typeDef.DeclaringTypeDefinition.ExtensionInfo ?? typeDef.DeclaringTypeDefinition.DeclaringTypeDefinition.ExtensionInfo;
extensionInfo.IsExtensionMarkerType(typeDef, out var group);
var extensionInfo = typeDef.DeclaringTypeDefinition!.ExtensionInfo ?? typeDef.DeclaringTypeDefinition.DeclaringTypeDefinition!.ExtensionInfo;
extensionInfo!.IsExtensionMarkerType(typeDef, out var group);
DoDecompileExtensionMembers(ext, group.Marker, extensionInfo);
}
// e.g. DelegateDeclaration
@ -1604,13 +1610,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1604,13 +1610,13 @@ namespace ICSharpCode.Decompiler.CSharp
TypeKind.Struct => settings.RecordStructs && typeDef.IsRecord,
_ => false,
};
RecordDecompiler recordDecompiler = isRecord ? new RecordDecompiler(typeSystem, typeDef, settings, CancellationToken) : null;
RecordDecompiler? recordDecompiler = isRecord ? new RecordDecompiler(typeSystem, typeDef, settings, CancellationToken) : null;
if (recordDecompiler != null)
decompileRun.RecordDecompilers.Add(typeDef, recordDecompiler);
// With C# 9 records, the relative order of fields and properties matters:
IEnumerable<IMember> fieldsAndProperties = isRecord
? recordDecompiler.FieldsAndProperties
? recordDecompiler!.FieldsAndProperties
: typeDef.Fields.Concat<IMember>(typeDef.Properties);
// For COM interop scenarios, the relative order of virtual functions/properties matters:
@ -1629,7 +1635,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1629,7 +1635,7 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var group in typeDef.ExtensionInfo?.ExtensionGroups ?? [])
{
var ext = (ExtensionDeclaration)typeSystemAstBuilder.ConvertExtension(group);
DoDecompileExtensionMembers(ext, group.Marker, typeDef.ExtensionInfo);
DoDecompileExtensionMembers(ext, group.Marker, typeDef.ExtensionInfo!);
typeDecl.Members.Add(ext);
}
@ -1709,7 +1715,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1709,7 +1715,7 @@ namespace ICSharpCode.Decompiler.CSharp
case EnumValueDisplayMode.AllHex:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>())
{
var constantValue = (enumMember.GetSymbol() as IField).GetConstantValue();
var constantValue = (enumMember.GetSymbol() as IField)!.GetConstantValue();
if (constantValue == null || enumMember.Initializer is not PrimitiveExpression pe)
{
continue;
@ -1744,7 +1750,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1744,7 +1750,7 @@ namespace ICSharpCode.Decompiler.CSharp
Instrumentation.DecompilerEventSource.Log.DoDecompileTypeDefinition(typeDef.FullName, watch.ElapsedMilliseconds);
}
void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler, PartialTypeInfo partialType, ExtensionInfo extensionInfo)
void DoDecompileMember(IEntity entity, RecordDecompiler? recordDecompiler, PartialTypeInfo? partialType, ExtensionInfo? extensionInfo)
{
if (partialType != null && partialType.IsDeclaredMember(entity.MetadataToken))
{
@ -1822,7 +1828,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1822,7 +1828,7 @@ namespace ICSharpCode.Decompiler.CSharp
else if (rr is TypeResolveResult trr
&& trr.Type.GetDefinition()?.DeclaringTypeDefinition == typeDef)
{
workList.Enqueue(trr.Type.GetDefinition());
workList.Enqueue(trr.Type.GetDefinition()!);
}
}
}
@ -1879,7 +1885,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1879,7 +1885,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (MemberIsHidden(module, field.MetadataToken, settings))
continue;
object constantValue = field.GetConstantValue();
object? constantValue = field.GetConstantValue();
if (constantValue == null)
continue;
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false);
@ -1928,7 +1934,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1928,7 +1934,7 @@ namespace ICSharpCode.Decompiler.CSharp
return firstValue == 0 ? EnumValueDisplayMode.None : EnumValueDisplayMode.FirstOnly;
}
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo extensionInfo)
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo? extensionInfo)
{
Debug.Assert(decompilationContext.CurrentMember == method);
var watch = System.Diagnostics.Stopwatch.StartNew();
@ -1943,7 +1949,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1943,7 +1949,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
FixParameterNames(methodDecl);
var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.MetadataFile, (MethodDefinitionHandle)method.MetadataToken))
if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule!.MetadataFile, (MethodDefinitionHandle)method.MetadataToken))
{
// if local functions are not active and we're dealing with a local function,
// reduce the visibility of the method to private,
@ -1970,7 +1976,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1970,7 +1976,7 @@ namespace ICSharpCode.Decompiler.CSharp
&& InheritanceHelper.GetBaseMember(method) == null && IsTypeHierarchyKnown(method.DeclaringType))
{
methodDecl.Modifiers &= ~Modifiers.Override;
if (!method.DeclaringTypeDefinition.IsSealed)
if (!method.DeclaringTypeDefinition!.IsSealed)
{
methodDecl.Modifiers |= Modifiers.Virtual;
}
@ -2020,10 +2026,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2020,10 +2026,10 @@ namespace ICSharpCode.Decompiler.CSharp
internal static bool IsWindowsFormsInitializeComponentMethod(IMethod method)
{
return method.ReturnType.Kind == TypeKind.Void && method.Name == "InitializeComponent" && method.DeclaringTypeDefinition.GetNonInterfaceBaseTypes().Any(t => t.FullName == "System.Windows.Forms.Control");
return method.ReturnType.Kind == TypeKind.Void && method.Name == "InitializeComponent" && method.DeclaringTypeDefinition!.GetNonInterfaceBaseTypes().Any(t => t.FullName == "System.Windows.Forms.Control");
}
void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo extensionInfo)
void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo? extensionInfo)
{
try
{
@ -2037,7 +2043,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2037,7 +2043,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (!method.IsStatic)
parameterOffset = 1; // implementation method has an additional receiver parameter
method = extensionInfo.InfoOfExtensionMember((IMethod)method.MemberDefinition).Value.ImplementationMethod;
method = extensionInfo.InfoOfExtensionMember((IMethod)method.MemberDefinition)!.Value.ImplementationMethod;
}
var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
@ -2126,7 +2132,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2126,7 +2132,7 @@ namespace ICSharpCode.Decompiler.CSharp
internal static void AddAnnotationsToDeclaration(IMethod method, EntityDeclaration entityDecl, ILFunction function, int parameterOffset = 0)
{
int i = parameterOffset;
var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index);
var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index!.Value);
foreach (var parameter in entityDecl.GetChildrenByRole<ParameterDeclaration>(SlotKind.Parameter))
{
if (parameters.TryGetValue(i, out var v))
@ -2136,11 +2142,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2136,11 +2142,11 @@ namespace ICSharpCode.Decompiler.CSharp
entityDecl.AddAnnotation(function);
}
internal static void CleanUpMethodDeclaration(EntityDeclaration entityDecl, BlockStatement body, ILFunction function, bool decompileBody = true)
internal static void CleanUpMethodDeclaration(EntityDeclaration entityDecl, BlockStatement? body, ILFunction function, bool decompileBody = true)
{
if (function.IsIterator)
{
if (decompileBody && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement))
if (decompileBody && !body!.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement))
{
body.Add(new YieldBreakStatement());
}
@ -2243,7 +2249,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2243,7 +2249,7 @@ namespace ICSharpCode.Decompiler.CSharp
return found;
}
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute)
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, [NotNullWhen(true)] out Syntax.Attribute? attribute)
{
attribute = null;
foreach (var section in entityDecl.Attributes)
@ -2269,7 +2275,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2269,7 +2275,7 @@ namespace ICSharpCode.Decompiler.CSharp
var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string;
if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName))
continue;
syntaxTree.AddLeadingTrivia(new PreProcessorDirective(PreProcessorDirectiveType.Define, symbolName));
syntaxTree!.AddLeadingTrivia(new PreProcessorDirective(PreProcessorDirectiveType.Define, symbolName));
}
}
@ -2280,13 +2286,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2280,13 +2286,13 @@ namespace ICSharpCode.Decompiler.CSharp
try
{
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst)
if (decompilationContext.CurrentTypeDefinition!.Kind == TypeKind.Enum && field.IsConst)
{
var enumDec = new EnumMemberDeclaration { Name = field.Name };
object constantValue = field.GetConstantValue();
object? constantValue = field.GetConstantValue();
if (constantValue != null)
{
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, constantValue);
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType!, constantValue);
}
enumDec.Attributes.AddRange(field.GetAttributes().Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a))));
enumDec.AddAnnotation(new MemberResolveResult(null, field));
@ -2343,11 +2349,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2343,11 +2349,11 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal static bool IsFixedField(IField field, out IType type, out int elementCount)
internal static bool IsFixedField(IField field, [NotNullWhen(true)] out IType? type, out int elementCount)
{
type = null;
elementCount = 0;
IAttribute attr = field.GetAttribute(KnownAttribute.FixedBuffer);
IAttribute? attr = field.GetAttribute(KnownAttribute.FixedBuffer);
if (attr != null && attr.FixedArguments.Length == 2)
{
if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length)
@ -2360,7 +2366,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2360,7 +2366,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo extensionInfo)
EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext, ExtensionInfo? extensionInfo)
{
Debug.Assert(decompilationContext.CurrentMember == property);
var watch = System.Diagnostics.Stopwatch.StartNew();
@ -2374,7 +2380,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2374,7 +2380,7 @@ namespace ICSharpCode.Decompiler.CSharp
propertyDecl.Name = property.Name.Substring(lastDot + 1);
}
FixParameterNames(propertyDecl);
Accessor getter, setter;
Accessor? getter, setter;
if (propertyDecl is PropertyDeclaration)
{
getter = ((PropertyDeclaration)propertyDecl).Getter;
@ -2386,29 +2392,29 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2386,29 +2392,29 @@ namespace ICSharpCode.Decompiler.CSharp
setter = ((IndexerDeclaration)propertyDecl).Setter;
}
bool getterHasBody = property.CanGet && property.Getter.HasBody;
bool setterHasBody = property.CanSet && property.Setter.HasBody;
bool getterHasBody = property.CanGet && property.Getter!.HasBody;
bool setterHasBody = property.CanSet && property.Setter!.HasBody;
if (getterHasBody)
{
DecompileBody(property.Getter, getter, decompileRun, decompilationContext, extensionInfo);
DecompileBody(property.Getter!, getter!, decompileRun, decompilationContext, extensionInfo);
}
if (setterHasBody)
{
DecompileBody(property.Setter, setter, decompileRun, decompilationContext, extensionInfo);
DecompileBody(property.Setter!, setter!, decompileRun, decompilationContext, extensionInfo);
}
if (!getterHasBody && !setterHasBody && !property.IsAbstract && property.DeclaringType.Kind != TypeKind.Interface)
{
propertyDecl.Modifiers |= Modifiers.Extern;
}
var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken;
var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter)!.MetadataToken;
var accessor = metadata.GetMethodDefinition(accessorHandle);
if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot))
{
SetNewModifier(propertyDecl);
}
if (property.CanGet && IsCovariantReturnOverride(property.Getter))
if (property.CanGet && IsCovariantReturnOverride(property.Getter!))
{
RemoveAttribute(getter, KnownAttribute.PreserveBaseOverrides);
RemoveAttribute(getter!, KnownAttribute.PreserveBaseOverrides);
propertyDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
propertyDecl.Modifiers |= Modifiers.Override;
}
@ -2435,10 +2441,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2435,10 +2441,10 @@ namespace ICSharpCode.Decompiler.CSharp
var watch = System.Diagnostics.Stopwatch.StartNew();
try
{
bool adderHasBody = ev.CanAdd && ev.AddAccessor.HasBody;
bool removerHasBody = ev.CanRemove && ev.RemoveAccessor.HasBody;
bool adderHasBody = ev.CanAdd && ev.AddAccessor!.HasBody;
bool removerHasBody = ev.CanRemove && ev.RemoveAccessor!.HasBody;
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition.Kind != TypeKind.Interface
typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition!.Kind != TypeKind.Interface
|| ev.IsExplicitInterfaceImplementation
|| adderHasBody
|| removerHasBody;
@ -2450,17 +2456,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2450,17 +2456,17 @@ namespace ICSharpCode.Decompiler.CSharp
}
if (adderHasBody)
{
DecompileBody(ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompileRun, decompilationContext, null);
DecompileBody(ev.AddAccessor!, ((CustomEventDeclaration)eventDecl).AddAccessor!, decompileRun, decompilationContext, null);
}
if (removerHasBody)
{
DecompileBody(ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompileRun, decompilationContext, null);
DecompileBody(ev.RemoveAccessor!, ((CustomEventDeclaration)eventDecl).RemoveAccessor!, decompileRun, decompilationContext, null);
}
if (!adderHasBody && !removerHasBody && !ev.IsAbstract && ev.DeclaringType.Kind != TypeKind.Interface)
{
eventDecl.Modifiers |= Modifiers.Extern;
}
var accessor = metadata.GetMethodDefinition((MethodDefinitionHandle)(ev.AddAccessor ?? ev.RemoveAccessor).MetadataToken);
var accessor = metadata.GetMethodDefinition((MethodDefinitionHandle)(ev.AddAccessor ?? ev.RemoveAccessor)!.MetadataToken);
if (accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot))
{
SetNewModifier(eventDecl);

2
ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
public enum LanguageVersion

131
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
@ -32,6 +33,8 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -32,6 +33,8 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
struct CallBuilder
@ -47,10 +50,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -47,10 +50,10 @@ namespace ICSharpCode.Decompiler.CSharp
public TranslatedExpression[] Arguments;
public IParameter[] ExpectedParameters;
public string[] ParameterNames;
public string[] ArgumentNames;
public string[]? ArgumentNames;
public int FirstOptionalArgumentIndex;
public BitSet IsPrimitiveValue;
public IReadOnlyList<int> ArgumentToParameterMap;
public IReadOnlyList<int>? ArgumentToParameterMap;
public bool AddNamesToPrimitiveValues;
public bool UseImplicitlyTypedOut;
@ -64,9 +67,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -64,9 +67,9 @@ namespace ICSharpCode.Decompiler.CSharp
return FirstOptionalArgumentIndex;
}
public string[] GetArgumentNames(int skipCount = 0)
public string[]? GetArgumentNames(int skipCount = 0)
{
string[] argumentNames = ArgumentNames;
string[]? argumentNames = ArgumentNames;
if (AddNamesToPrimitiveValues && IsPrimitiveValue.Any() && !IsExpandedForm
&& !ParameterNames.Any(string.IsNullOrEmpty))
{
@ -154,7 +157,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -154,7 +157,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
for (int i = 0; i < Arguments.Length; i++)
{
string inferredName;
string? inferredName;
switch (Arguments[i].Expression)
{
case IdentifierExpression identifier:
@ -196,7 +199,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -196,7 +199,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.typeSystem = typeSystem;
}
public TranslatedExpression Build(CallInstruction inst, IType typeHint = null)
public TranslatedExpression Build(CallInstruction inst, IType? typeHint = null)
{
if (inst is NewObj newobj && IL.Transforms.DelegateConstruction.MatchDelegateConstruction(newobj, out _, out _, out _))
{
@ -255,7 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -255,7 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp
return result;
}
static bool IsSpanBasedStringConcat(CallInstruction call, out List<(ILInstruction, KnownTypeCode)> operands)
static bool IsSpanBasedStringConcat(CallInstruction call, [NotNullWhen(true)] out List<(ILInstruction, KnownTypeCode)>? operands)
{
operands = null;
@ -321,8 +324,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -321,8 +324,8 @@ namespace ICSharpCode.Decompiler.CSharp
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method,
IReadOnlyList<ILInstruction> callArguments,
IReadOnlyList<int> argumentToParameterMap = null,
IType constrainedTo = null)
IReadOnlyList<int>? argumentToParameterMap = null,
IType? constrainedTo = null)
{
if (method.IsExplicitInterfaceImplementation && callOpCode == OpCode.Call)
{
@ -340,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -340,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp
var expectedTargetDetails = new ExpectedTargetDetails {
CallOpCode = callOpCode
};
ILFunction localFunction = null;
ILFunction? localFunction = null;
if (method.IsLocalFunction)
{
localFunction = expressionBuilder.ResolveLocalFunction(method);
@ -353,7 +356,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -353,7 +356,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (localFunction != null)
{
var ide = new IdentifierExpression(localFunction.Name);
var ide = new IdentifierExpression(localFunction.Name!);
if (method.TypeArguments.Count > 0)
{
ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
@ -522,13 +525,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -522,13 +525,15 @@ namespace ICSharpCode.Decompiler.CSharp
}
var transform = GetRequiredTransformationsForCall(expectedTargetDetails, method, ref target,
ref argumentList, CallTransformation.All, out IParameterizedMember foundMethod);
ref argumentList, CallTransformation.All, out IParameterizedMember? foundMethod);
// GetRequiredTransformationsForCall always assigns foundMethod (the resolved overload or 'method').
Debug.Assert(foundMethod != null);
// Note: after this, 'method' and 'foundMethod' may differ,
// but as far as allowed by IsAppropriateCallTarget().
// Need to update list of parameter names, because foundMethod is different and thus might use different names.
if (!method.Equals(foundMethod) && argumentList.ParameterNames.Length >= foundMethod.Parameters.Count)
if (!method.Equals(foundMethod) && argumentList.ParameterNames.Length >= foundMethod!.Parameters.Count)
{
for (int i = 0; i < foundMethod.Parameters.Count; i++)
{
@ -582,7 +587,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -582,7 +587,7 @@ namespace ICSharpCode.Decompiler.CSharp
private ExpressionWithResolveResult HandleStringInterpolation(IMethod method, ArgumentList argumentList)
{
if (!TryGetStringInterpolationTokens(argumentList, out string format, out var tokens))
if (!TryGetStringInterpolationTokens(argumentList, out string? format, out var tokens))
return default;
var arguments = argumentList.Arguments;
@ -598,7 +603,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -598,7 +603,7 @@ namespace ICSharpCode.Decompiler.CSharp
return;
var arrayCreation = (ArrayCreateExpression)argumentList.Arguments[1].Expression;
var arrayCreationRR = (ArrayCreateResolveResult)argumentList.Arguments[1].ResolveResult;
var element = arrayCreation.Initializer.Elements.First().Detach();
var element = arrayCreation.Initializer!.Elements.First().Detach();
argument = new TranslatedExpression(element, arrayCreationRR.InitializerElements.First());
}
@ -714,7 +719,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -714,7 +719,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
public ExpressionWithResolveResult BuildDictionaryInitializerExpression(OpCode callOpCode, IMethod method,
InitializedObjectResolveResult target, IReadOnlyList<ILInstruction> indices, ILInstruction value = null)
InitializedObjectResolveResult target, IReadOnlyList<ILInstruction> indices, ILInstruction? value = null)
{
if (method is null)
throw new ArgumentNullException(nameof(method));
@ -755,7 +760,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -755,7 +760,7 @@ namespace ICSharpCode.Decompiler.CSharp
);
}
private bool TryGetStringInterpolationTokens(ArgumentList argumentList, out string format, out List<(TokenKind Kind, int Index, int Alignment, string Format)> tokens)
private bool TryGetStringInterpolationTokens(ArgumentList argumentList, [NotNullWhen(true)] out string? format, [NotNullWhen(true)] out List<(TokenKind Kind, int Index, int Alignment, string? Format)>? tokens)
{
tokens = null;
format = null;
@ -766,9 +771,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -766,9 +771,9 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (!arguments.Skip(1).All(a => !a.Expression.DescendantsAndSelf.OfType<PrimitiveExpression>().Any(p => p.Value is string)))
return false;
tokens = new List<(TokenKind Kind, int Index, int Alignment, string Format)>();
tokens = new List<(TokenKind Kind, int Index, int Alignment, string? Format)>();
int i = 0;
format = (string)crr.ConstantValue;
format = (string)crr.ConstantValue!;
foreach (var (kind, data) in TokenizeFormatString(format))
{
int index;
@ -787,7 +792,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -787,7 +792,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens.Add((kind, index, 0, null));
break;
case TokenKind.ArgumentWithFormat:
arg = data.Split(new[] { ':' }, 2);
arg = data!.Split(new[] { ':' }, 2);
if (arg.Length != 2 || arg[1].Length == 0)
return false;
if (!int.TryParse(arg[0], out index) || index != i)
@ -796,7 +801,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -796,7 +801,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens.Add((kind, index, 0, arg[1]));
break;
case TokenKind.ArgumentWithAlignment:
arg = data.Split(new[] { ',' }, 2);
arg = data!.Split(new[] { ',' }, 2);
if (arg.Length != 2 || arg[1].Length == 0)
return false;
if (!int.TryParse(arg[0], out index) || index != i)
@ -807,7 +812,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -807,7 +812,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens.Add((kind, index, alignment, null));
break;
case TokenKind.ArgumentWithAlignmentAndFormat:
arg = data.Split(new[] { ',', ':' }, 3);
arg = data!.Split(new[] { ',', ':' }, 3);
if (arg.Length != 3 || arg[1].Length == 0 || arg[2].Length == 0)
return false;
if (!int.TryParse(arg[0], out index) || index != i)
@ -834,7 +839,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -834,7 +839,7 @@ namespace ICSharpCode.Decompiler.CSharp
ArgumentWithAlignmentAndFormat,
}
private IEnumerable<(TokenKind, string)> TokenizeFormatString(string value)
private IEnumerable<(TokenKind, string?)> TokenizeFormatString(string value)
{
int pos = -1;
@ -926,14 +931,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -926,14 +931,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
private ArgumentList BuildArgumentList(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method,
int firstParamIndex, IReadOnlyList<ILInstruction> callArguments, IReadOnlyList<int> argumentToParameterMap)
private ArgumentList BuildArgumentList(ExpectedTargetDetails expectedTargetDetails, ResolveResult? target, IMethod method,
int firstParamIndex, IReadOnlyList<ILInstruction> callArguments, IReadOnlyList<int>? argumentToParameterMap)
{
ArgumentList list = new ArgumentList();
// Translate arguments to the expected parameter types
var arguments = new List<TranslatedExpression>(method.Parameters.Count);
string[] argumentNames = null;
string[]? argumentNames = null;
Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count);
var expectedParameters = new List<IParameter>(method.Parameters.Count); // parameters, but in argument order
bool isExpandedForm = false;
@ -1038,12 +1043,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1038,12 +1043,12 @@ namespace ICSharpCode.Decompiler.CSharp
return p.Type.IsKnownType(KnownTypeCode.Boolean);
}
private bool TransformParamsArgument(ExpectedTargetDetails expectedTargetDetails, ResolveResult targetResolveResult,
private bool TransformParamsArgument(ExpectedTargetDetails expectedTargetDetails, ResolveResult? targetResolveResult,
IMethod method, IParameter parameter, TranslatedExpression paramsArgument, ref List<IParameter> expectedParameters,
ref List<TranslatedExpression> arguments)
{
var expressionBuilder = this.expressionBuilder;
if (ExtractArguments(out IType elementType, out var expandedParameters, out var expandedArguments))
if (ExtractArguments(out var elementType, out var expandedParameters, out var expandedArguments))
{
expandedParameters.InsertRange(0, expectedParameters);
expandedArguments.InsertRange(0, arguments);
@ -1059,7 +1064,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1059,7 +1064,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
return false;
bool ExtractArguments(out IType elementType, out List<IParameter> parameters, out List<TranslatedExpression> arguments)
bool ExtractArguments([NotNullWhen(true)] out IType? elementType, [NotNullWhen(true)] out List<IParameter>? parameters, [NotNullWhen(true)] out List<TranslatedExpression>? arguments)
{
elementType = null;
parameters = null;
@ -1138,13 +1143,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1138,13 +1143,13 @@ namespace ICSharpCode.Decompiler.CSharp
}
private CallTransformation GetRequiredTransformationsForCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
ref TranslatedExpression target, ref ArgumentList argumentList, CallTransformation allowedTransforms, out IParameterizedMember foundMethod)
ref TranslatedExpression target, ref ArgumentList argumentList, CallTransformation allowedTransforms, out IParameterizedMember? foundMethod)
{
CallTransformation transform = CallTransformation.None;
// initialize requireTarget flag
bool requireTarget;
ResolveResult targetResolveResult;
ResolveResult? targetResolveResult;
if ((allowedTransforms & CallTransformation.RequireTarget) != 0)
{
if (settings.AlwaysQualifyMemberReferences || expressionBuilder.HidesVariableWithName(method.Name))
@ -1475,9 +1480,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1475,9 +1480,9 @@ namespace ICSharpCode.Decompiler.CSharp
}
OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
ResolveResult target, IType[] typeArguments, ResolveResult[] arguments,
string[] argumentNames, int firstOptionalArgumentIndex,
out IParameterizedMember foundMember, out bool bestCandidateIsExpandedForm)
ResolveResult? target, IType[] typeArguments, ResolveResult[] arguments,
string[]? argumentNames, int firstOptionalArgumentIndex,
out IParameterizedMember? foundMember, out bool bestCandidateIsExpandedForm)
{
foundMember = null;
bestCandidateIsExpandedForm = false;
@ -1585,8 +1590,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1585,8 +1590,8 @@ namespace ICSharpCode.Decompiler.CSharp
return OverloadResolutionErrors.None;
}
bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method,
IList<TranslatedExpression> arguments, string[] argumentNames, out IMember foundMember)
bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult? target, IMethod method,
IList<TranslatedExpression> arguments, string[]? argumentNames, [NotNullWhen(true)] out IMember? foundMember)
{
Log.WriteLine("IsUnambiguousAccess: Performing overload resolution for " + method);
Log.WriteCollection(" Arguments: ", arguments.Select(a => a.ResolveResult));
@ -1594,7 +1599,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1594,7 +1599,7 @@ namespace ICSharpCode.Decompiler.CSharp
foundMember = null;
if (target == null)
{
var result = resolver.ResolveSimpleName(method.AccessorOwner.Name,
var result = resolver.ResolveSimpleName(method.AccessorOwner!.Name,
EmptyList<IType>.Instance,
isInvocationTarget: false) as MemberResolveResult;
if (result == null || result.IsError)
@ -1604,7 +1609,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1604,7 +1609,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
if (method.AccessorOwner.SymbolKind == SymbolKind.Indexer)
if (method.AccessorOwner!.SymbolKind == SymbolKind.Indexer)
{
var or = new OverloadResolution(resolver.Compilation,
arguments.SelectArray(a => a.ResolveResult),
@ -1621,7 +1626,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1621,7 +1626,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
var result = lookup.Lookup(target,
method.AccessorOwner.Name,
method.AccessorOwner!.Name,
EmptyList<IType>.Instance,
isInvocation: false) as MemberResolveResult;
if (result == null || result.IsError)
@ -1633,10 +1638,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1633,10 +1638,10 @@ namespace ICSharpCode.Decompiler.CSharp
}
ExpressionWithResolveResult HandleAccessorCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
TranslatedExpression target, List<TranslatedExpression> arguments, string[] argumentNames)
TranslatedExpression target, List<TranslatedExpression> arguments, string[]? argumentNames)
{
bool requireTarget;
if (settings.AlwaysQualifyMemberReferences || method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expressionBuilder.HidesVariableWithName(method.AccessorOwner.Name))
if (settings.AlwaysQualifyMemberReferences || method.AccessorOwner!.SymbolKind == SymbolKind.Indexer || expressionBuilder.HidesVariableWithName(method.AccessorOwner.Name))
requireTarget = true;
else if (method.IsStatic)
requireTarget = !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition);
@ -1654,7 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1654,7 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp
arguments.Remove(value);
}
IMember foundMember;
IMember? foundMember;
while (!IsUnambiguousAccess(expectedTargetDetails, targetResolveResult, method, arguments, argumentNames, out foundMember))
{
if (!argumentsCasted)
@ -1670,12 +1675,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1670,12 +1675,12 @@ namespace ICSharpCode.Decompiler.CSharp
else if (!targetCasted)
{
targetCasted = true;
target = target.ConvertTo(method.AccessorOwner.DeclaringType, expressionBuilder);
target = target.ConvertTo(method.AccessorOwner!.DeclaringType, expressionBuilder);
targetResolveResult = target.ResolveResult;
}
else
{
foundMember = method.AccessorOwner;
foundMember = method.AccessorOwner!;
break;
}
}
@ -1693,12 +1698,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1693,12 +1698,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (requireTarget)
{
expr = new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name)
expr = new MemberReferenceExpression(target.Expression, method.AccessorOwner!.Name)
.WithoutILInstruction().WithRR(rr);
}
else
{
expr = new IdentifierExpression(method.AccessorOwner.Name)
expr = new IdentifierExpression(method.AccessorOwner!.Name)
.WithoutILInstruction().WithRR(rr);
}
@ -1714,7 +1719,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1714,7 +1719,7 @@ namespace ICSharpCode.Decompiler.CSharp
op = AssignmentOperatorType.Subtract;
}
}
return new AssignmentExpression(expr, op, value.Expression).WithRR(new TypeResolveResult(method.AccessorOwner.ReturnType));
return new AssignmentExpression(expr, op, value.Expression!).WithRR(new TypeResolveResult(method.AccessorOwner!.ReturnType));
}
else
{
@ -1725,12 +1730,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1725,12 +1730,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (requireTarget)
{
return new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name)
return new MemberReferenceExpression(target.Expression, method.AccessorOwner!.Name)
.WithoutILInstruction().WithRR(rr);
}
else
{
return new IdentifierExpression(method.AccessorOwner.Name)
return new IdentifierExpression(method.AccessorOwner!.Name)
.WithoutILInstruction().WithRR(rr);
}
}
@ -1756,7 +1761,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1756,7 +1761,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
ExpressionWithResolveResult HandleConstructorCall(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method, ArgumentList argumentList)
ExpressionWithResolveResult HandleConstructorCall(ExpectedTargetDetails expectedTargetDetails, ResolveResult? target, IMethod method, ArgumentList argumentList)
{
if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType())
{
@ -1802,7 +1807,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1802,7 +1807,7 @@ namespace ICSharpCode.Decompiler.CSharp
CastArguments(argumentList.Arguments, argumentList.ExpectedParameters);
break; // make sure that we don't not end up in an infinite loop
}
IType returnTypeOverride = null;
IType? returnTypeOverride = null;
if (typeSystem.MainModule.TypeSystemOptions.HasFlag(TypeSystemOptions.NativeIntegersWithoutAttribute))
{
// For DeclaringType, we don't use nint/nuint (so that DeclaringType.GetConstructors etc. works),
@ -1908,7 +1913,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1908,7 +1913,7 @@ namespace ICSharpCode.Decompiler.CSharp
return expr.Expression.WithRR(new MemberResolveResult(null, method));
}
ExpressionWithResolveResult BuildDelegateReference(IMethod method, IMethod invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg)
ExpressionWithResolveResult BuildDelegateReference(IMethod method, IMethod? invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction? thisArg)
{
ExpressionBuilder expressionBuilder = this.expressionBuilder;
ExpressionWithResolveResult targetExpression;
@ -1935,13 +1940,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1935,13 +1940,13 @@ namespace ICSharpCode.Decompiler.CSharp
}
(TranslatedExpression target, bool addTypeArguments, string methodName, ResolveResult result) DisambiguateDelegateReference(IMethod method, IMethod invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg)
(TranslatedExpression target, bool addTypeArguments, string methodName, ResolveResult result) DisambiguateDelegateReference(IMethod method, IMethod? invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction? thisArg)
{
if (method.IsLocalFunction)
{
ILFunction localFunction = expressionBuilder.ResolveLocalFunction(method);
ILFunction? localFunction = expressionBuilder.ResolveLocalFunction(method);
Debug.Assert(localFunction != null);
return (default, addTypeArguments: true, localFunction.Name, ToMethodGroup(method, localFunction));
return (default, addTypeArguments: true, localFunction.Name!, ToMethodGroup(method, localFunction));
}
if (method.IsExtensionMethod && method.Parameters.Count - 1 == invokeMethod?.Parameters.Count)
{
@ -1951,21 +1956,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1951,21 +1956,21 @@ namespace ICSharpCode.Decompiler.CSharp
targetType = ((ByReferenceType)targetType).ElementType;
thisArg = thisArgBox.Argument;
}
TranslatedExpression target = expressionBuilder.Translate(thisArg, targetType);
TranslatedExpression target = expressionBuilder.Translate(thisArg!, targetType);
var currentTarget = target;
bool targetCasted = false;
bool addTypeArguments = false;
// Initial inputs for IsUnambiguousMethodReference:
ResolveResult targetResolveResult = target.ResolveResult;
IReadOnlyList<IType> typeArguments = EmptyList<IType>.Instance;
if (thisArg.MatchLdNull())
if (thisArg!.MatchLdNull())
{
targetCasted = true;
currentTarget = currentTarget.ConvertTo(targetType, expressionBuilder);
targetResolveResult = currentTarget.ResolveResult;
}
// Find somewhat minimal solution:
ResolveResult result;
ResolveResult? result;
while (!IsUnambiguousMethodReference(expectedTargetDetails, method, targetResolveResult, typeArguments, true, out result))
{
if (!targetCasted)
@ -1985,7 +1990,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1985,7 +1990,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
break;
}
return (currentTarget, addTypeArguments, method.Name, result);
return (currentTarget, addTypeArguments, method.Name, result!);
}
else
{
@ -2019,10 +2024,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2019,10 +2024,10 @@ namespace ICSharpCode.Decompiler.CSharp
bool targetCasted = false;
bool addTypeArguments = false;
// Initial inputs for IsUnambiguousMethodReference:
ResolveResult targetResolveResult = targetAdded ? target.ResolveResult : null;
ResolveResult? targetResolveResult = targetAdded ? target.ResolveResult : null;
IReadOnlyList<IType> typeArguments = EmptyList<IType>.Instance;
// Find somewhat minimal solution:
ResolveResult result;
ResolveResult? result;
while (!IsUnambiguousMethodReference(expectedTargetDetails, method, targetResolveResult, typeArguments, false, out result))
{
if (!addTypeArguments)
@ -2054,7 +2059,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2054,7 +2059,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
result = mgrr.WithChosenMethod(method);
}
return (currentTarget, addTypeArguments, method.Name, result);
return (currentTarget, addTypeArguments, method.Name, result!);
}
}
@ -2071,7 +2076,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2071,7 +2076,7 @@ namespace ICSharpCode.Decompiler.CSharp
return oce;
}
bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult target, IReadOnlyList<IType> typeArguments, bool isExtensionMethodReference, out ResolveResult result)
bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult? target, IReadOnlyList<IType> typeArguments, bool isExtensionMethodReference, [NotNullWhen(true)] out ResolveResult? result)
{
Log.WriteLine("IsUnambiguousMethodReference: Performing overload resolution for " + method);

101
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -38,6 +38,8 @@ using ICSharpCode.Decompiler.Util; @@ -38,6 +38,8 @@ using ICSharpCode.Decompiler.Util;
using ExpressionType = System.Linq.Expressions.ExpressionType;
using PrimitiveType = ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveType;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
@ -128,7 +130,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -128,7 +130,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (rr.Type.IsCSharpSmallIntegerType())
{
expr = new CastExpression(new PrimitiveType(KnownTypeReference.GetCSharpNameByTypeCode(rr.Type.GetDefinition().KnownTypeCode)), expr);
expr = new CastExpression(new PrimitiveType(KnownTypeReference.GetCSharpNameByTypeCode(rr.Type.GetDefinition()!.KnownTypeCode)), expr);
// Note: no unchecked annotation necessary, because the constant was folded to be in-range
}
else if (rr.Type.IsCSharpNativeIntegerType())
@ -160,7 +162,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -160,7 +162,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
public TranslatedExpression Translate(ILInstruction inst, IType typeHint = null)
public TranslatedExpression Translate(ILInstruction inst, IType? typeHint = null)
{
Debug.Assert(inst != null);
cancellationToken.ThrowIfCancellationRequested();
@ -224,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -224,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (variable.Kind == VariableKind.Parameter && variable.Index < 0)
expr = new ThisReferenceExpression();
else
expr = new IdentifierExpression(variable.Name);
expr = new IdentifierExpression(variable.Name!);
if (variable.Type.Kind == TypeKind.ByReference)
{
// When loading a by-ref parameter, use 'ref paramName'.
@ -272,13 +274,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -272,13 +274,13 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal ILFunction ResolveLocalFunction(IMethod method)
internal ILFunction? ResolveLocalFunction(IMethod method)
{
Debug.Assert(method.IsLocalFunction);
method = (IMethod)((IMethod)method.MemberDefinition).ReducedFrom.MemberDefinition;
method = (IMethod)((IMethod)method.MemberDefinition!).ReducedFrom!.MemberDefinition;
foreach (var parent in currentFunction.Ancestors.OfType<ILFunction>())
{
var definition = parent.LocalFunctions.FirstOrDefault(f => f.Method.MemberDefinition.Equals(method));
var definition = parent.LocalFunctions.FirstOrDefault(f => f.Method!.MemberDefinition.Equals(method));
if (definition != null)
{
return definition;
@ -296,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -296,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp
return !(target.Expression is ThisReferenceExpression || target.Expression is BaseReferenceExpression);
}
ExpressionWithResolveResult ConvertField(IField field, ILInstruction targetInstruction = null)
ExpressionWithResolveResult ConvertField(IField field, ILInstruction? targetInstruction = null)
{
var target = TranslateTarget(targetInstruction,
nonVirtualInvocation: true,
@ -321,7 +323,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -321,7 +323,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool targetCasted = false;
var targetResolveResult = requireTarget ? target.ResolveResult : null;
bool IsAmbiguousAccess(out MemberResolveResult result)
bool IsAmbiguousAccess(out MemberResolveResult? result)
{
if (targetResolveResult == null)
{
@ -335,7 +337,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -335,7 +337,7 @@ namespace ICSharpCode.Decompiler.CSharp
return result == null || result.IsError || !result.Member.Equals(field, NormalizeTypeVisitor.TypeErasure);
}
MemberResolveResult mrr;
MemberResolveResult? mrr;
while (IsAmbiguousAccess(out mrr))
{
if (!requireTarget)
@ -495,11 +497,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -495,11 +497,12 @@ namespace ICSharpCode.Decompiler.CSharp
StackAllocExpression TranslateLocAlloc(LocAlloc inst, IType typeHint, out IType elementType)
{
TranslatedExpression countExpression;
PointerType pointerType;
PointerType? pointerType;
if (inst.Argument.MatchBinaryNumericInstruction(BinaryNumericOperator.Mul, out var left, out var right)
&& right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend).MatchSizeOf(out elementType))
&& right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend).MatchSizeOf(out var sizeOfElementType))
{
// Determine the element type from the sizeof
elementType = sizeOfElementType;
countExpression = Translate(left.UnwrapConv(ConversionKind.ZeroExtend));
pointerType = new PointerType(elementType);
}
@ -634,7 +637,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -634,7 +637,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
Expression expr;
IType constantType;
object constantValue;
object? constantValue;
if (type.IsReferenceType == true)
{
expr = new NullReferenceExpression();
@ -966,7 +969,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -966,7 +969,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst);
}
OperatorResolveResult rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult) as OperatorResolveResult;
OperatorResolveResult? rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult) as OperatorResolveResult;
if (rr == null || rr.IsError || rr.UserDefinedOperatorMethod != null
|| NullableType.GetUnderlyingType(rr.Operands[0].Type).GetStackType() != inst.InputType
|| !rr.Type.IsKnownType(KnownTypeCode.Boolean))
@ -1375,12 +1378,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1375,12 +1378,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
right = Translate(offsetInst);
right = ConvertArrayIndex(right, inst.RightInputType, allowIntPtr: true);
return CallUnsafeIntrinsic(name, new[] { left.Expression, right.Expression }, brt, inst);
return CallUnsafeIntrinsic(name, new[] { left.Expression, right.Expression }, brt!, inst);
}
else
{
right = ConvertArrayIndex(right, inst.RightInputType, allowIntPtr: true);
return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst);
return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt!, inst);
}
}
@ -1428,7 +1431,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1428,7 +1431,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal TranslatedExpression CallUnsafeIntrinsic(string name, Expression[] arguments, IType returnType, ILInstruction inst = null, IEnumerable<IType> typeArguments = null)
internal TranslatedExpression CallUnsafeIntrinsic(string name, Expression[] arguments, IType returnType, ILInstruction? inst = null, IEnumerable<IType>? typeArguments = null)
{
var target = new MemberReferenceExpression {
Target = new TypeReferenceExpression(astBuilder.ConvertType(compilation.FindType(KnownTypeCode.Unsafe))),
@ -1499,7 +1502,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1499,7 +1502,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (sub.CheckForOverflow)
return null;
// First, attempt to parse the 'sizeof' on the RHS
IType elementType;
IType? elementType;
if (inst.Right.MatchLdcI(out long elementSize))
{
elementType = null;
@ -2403,7 +2406,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2403,7 +2406,7 @@ namespace ICSharpCode.Decompiler.CSharp
return expr;
}
internal bool IsCurrentOrContainingType(ITypeDefinition type)
internal bool IsCurrentOrContainingType(ITypeDefinition? type)
{
var currentTypeDefinition = decompilationContext.CurrentTypeDefinition;
while (currentTypeDefinition != null)
@ -2415,7 +2418,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2415,7 +2418,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
internal bool IsBaseTypeOfCurrentType(ITypeDefinition type)
internal bool IsBaseTypeOfCurrentType(ITypeDefinition? type)
{
return decompilationContext.CurrentTypeDefinition.GetAllBaseTypeDefinitions().Any(t => t == type);
}
@ -2506,7 +2509,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2506,7 +2509,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement returnStmt)
{
lambda.Body = returnStmt.Expression.Detach();
inferredReturnType = lambda.Body.GetResolveResult().Type;
inferredReturnType = lambda.Body!.GetResolveResult().Type;
}
else
{
@ -2539,7 +2542,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2539,7 +2542,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitILFunction(ILFunction function, TranslationContext context)
{
return TranslateFunction(function.DelegateType, function)
return TranslateFunction(function.DelegateType!, function)
.WithILInstruction(function);
}
@ -2580,7 +2583,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2580,7 +2583,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (resultType.Kind == TypeKind.Void)
return compilation.FindType(KnownTypeCode.Task);
ITypeDefinition def = compilation.FindType(KnownTypeCode.TaskOfT).GetDefinition();
ITypeDefinition? def = compilation.FindType(KnownTypeCode.TaskOfT).GetDefinition();
if (def != null)
return new ParameterizedType(def, new[] { resultType });
else
@ -2589,7 +2592,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2589,7 +2592,7 @@ namespace ICSharpCode.Decompiler.CSharp
IEnumerable<ParameterDeclaration> MakeParameters(IReadOnlyList<IParameter> parameters, ILFunction function)
{
var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index);
var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index!.Value);
int i = 0;
foreach (var parameter in parameters)
{
@ -2597,7 +2600,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2597,7 +2600,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (variables.TryGetValue(i, out var v))
{
pd.AddAnnotation(new ILVariableResolveResult(v, parameters[i].Type));
pd.Name = v.Name;
pd.Name = v.Name!;
}
if (string.IsNullOrEmpty(pd.Name) && !pd.Type.IsArgList())
{
@ -2661,8 +2664,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2661,8 +2664,8 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal TranslatedExpression TranslateTarget(ILInstruction target, bool nonVirtualInvocation,
bool memberStatic, IType memberDeclaringType, IType constrainedTo = null)
internal TranslatedExpression TranslateTarget(ILInstruction? target, bool nonVirtualInvocation,
bool memberStatic, IType memberDeclaringType, IType? constrainedTo = null)
{
// If references are missing member.IsStatic might not be set correctly.
// Additionally check target for null, in order to avoid a crash.
@ -3036,7 +3039,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3036,7 +3039,7 @@ namespace ICSharpCode.Decompiler.CSharp
memberName = "LongLength";
code = KnownTypeCode.Int64;
}
IProperty member = arrayType.GetProperties(p => p.Name == memberName).FirstOrDefault();
IProperty? member = arrayType.GetProperties(p => p.Name == memberName).FirstOrDefault();
ResolveResult rr = member == null
? new ResolveResult(compilation.FindType(code))
: new MemberResolveResult(arrayExpr.ResolveResult, member);
@ -3365,9 +3368,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3365,9 +3368,9 @@ namespace ICSharpCode.Decompiler.CSharp
{
var call = (Call)block.Instructions[i];
Interpolation BuildInterpolation(int alignment = 0, string suffix = null)
Interpolation BuildInterpolation(int alignment = 0, string? suffix = null)
{
return new Interpolation(Translate(call.Arguments[1]).ConvertTo(call.GetParameter(1).Type, this, allowImplicitConversion: true), alignment, suffix);
return new Interpolation(Translate(call.Arguments[1]).ConvertTo(call.GetParameter(1)!.Type, this, allowImplicitConversion: true), alignment, suffix);
}
switch (call.Method.Name)
@ -3465,7 +3468,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3465,7 +3468,7 @@ namespace ICSharpCode.Decompiler.CSharp
var elementsStack = new Stack<List<TranslatedExpression>>();
var elements = new List<TranslatedExpression>(block.Instructions.Count);
elementsStack.Push(elements);
List<IL.Transforms.AccessPathElement> currentPath = null;
List<IL.Transforms.AccessPathElement>? currentPath = null;
var indexVariables = new Dictionary<ILVariable, ILInstruction>();
foreach (var inst in block.Instructions.Skip(1))
{
@ -3512,7 +3515,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3512,7 +3515,7 @@ namespace ICSharpCode.Decompiler.CSharp
Debug.Assert(lastElement.Member is IMethod);
elementsStack.Peek().Add(
new CallBuilder(this, typeSystem, settings)
.BuildCollectionInitializerExpression(lastElement.OpCode, (IMethod)lastElement.Member, initObjRR, info.Values)
.BuildCollectionInitializerExpression(lastElement.OpCode, (IMethod)lastElement.Member, initObjRR, info.Values!)
.WithILInstruction(inst)
);
break;
@ -3525,13 +3528,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3525,13 +3528,13 @@ namespace ICSharpCode.Decompiler.CSharp
Debug.Assert(property.Setter != null, $"Indexer property {property} has no setter");
elementsStack.Peek().Add(
new CallBuilder(this, typeSystem, settings)
.BuildDictionaryInitializerExpression(lastElement.OpCode, property.Setter, initObjRR, GetIndices(lastElement.Indices, indexVariables).ToList(), info.Values.Single())
.BuildDictionaryInitializerExpression(lastElement.OpCode, property.Setter, initObjRR, GetIndices(lastElement.Indices, indexVariables).ToList(), info.Values!.Single())
.WithILInstruction(inst)
);
}
else
{
var value = Translate(info.Values.Single(), typeHint: memberRR.Type)
var value = Translate(info.Values!.Single(), typeHint: memberRR.Type)
.ConvertTo(memberRR.Type, this, allowImplicitConversion: true);
var assignment = new NamedExpression(lastElement.Member.Name, value)
.WithILInstruction(inst).WithRR(memberRR);
@ -3542,7 +3545,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3542,7 +3545,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
while (elementsStack.Count > 1)
{
var methodElement = currentPath[elementsStack.Count - 1];
var methodElement = currentPath![elementsStack.Count - 1];
var pathElement = currentPath[elementsStack.Count - 2];
var values = elementsStack.Pop();
elementsStack.Peek().Add(
@ -3616,7 +3619,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3616,7 +3619,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var stloc = block.Instructions.FirstOrDefault() as StLoc;
var final = block.FinalInstruction as LdLoc;
if (stloc == null || final == null || !stloc.Value.MatchNewArr(out IType type))
if (stloc == null || final == null || !stloc.Value.MatchNewArr(out IType? type))
throw new ArgumentException("given Block is invalid!");
if (stloc.Variable != final.Variable || stloc.Variable.Kind != VariableKind.InitializerTarget)
throw new ArgumentException("given Block is invalid!");
@ -3635,11 +3638,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3635,11 +3638,11 @@ namespace ICSharpCode.Decompiler.CSharp
for (int i = 1; i < block.Instructions.Count; i++)
{
if (!block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType t) || !type.Equals(t))
if (!block.Instructions[i].MatchStObj(out ILInstruction? target, out ILInstruction? value, out IType? t) || !type.Equals(t))
throw new ArgumentException("given Block is invalid!");
if (!target.MatchLdElema(out t, out ILInstruction array) || !type.Equals(t))
if (!target.MatchLdElema(out t, out ILInstruction? array) || !type.Equals(t))
throw new ArgumentException("given Block is invalid!");
if (!array.MatchLdLoc(out ILVariable v) || v != final.Variable)
if (!array.MatchLdLoc(out ILVariable? v) || v != final.Variable)
throw new ArgumentException("given Block is invalid!");
while (container.Count < dimensions)
{
@ -3670,7 +3673,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3670,7 +3673,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
ArraySpecifier[] additionalSpecifiers;
AstType typeExpression;
AstType? typeExpression;
if (settings.AnonymousTypes && type.ContainsAnonymousType())
{
typeExpression = null;
@ -3980,20 +3983,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3980,20 +3983,20 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal (TranslatedExpression, IType, StringToInt) TranslateSwitchValue(SwitchInstruction inst, bool isExpressionContext)
internal (TranslatedExpression, IType, StringToInt?) TranslateSwitchValue(SwitchInstruction inst, bool isExpressionContext)
{
TranslatedExpression value;
IType governingType;
// prepare expression and expected type
// first try to guess a governing type
if (inst.Value is StringToInt strToInt)
StringToInt? strToInt = inst.Value as StringToInt;
if (strToInt != null)
{
value = Translate(strToInt.Argument);
governingType = strToInt.ExpectedType ?? compilation.FindType(KnownTypeCode.String);
}
else
{
strToInt = null;
value = Translate(inst.Value);
governingType = inst.Type ?? value.Type;
@ -4191,7 +4194,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4191,7 +4194,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitAwait(Await inst, TranslationContext context)
{
IType expectedType = null;
IType? expectedType = null;
if (inst.GetAwaiterMethod != null)
{
if (inst.GetAwaiterMethod.IsStatic)
@ -4269,7 +4272,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4269,7 +4272,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicGetMemberInstruction(DynamicGetMemberInstruction inst, TranslationContext context)
{
var target = TranslateDynamicTarget(inst.Target, inst.TargetArgumentInfo);
return new MemberReferenceExpression(target, inst.Name)
return new MemberReferenceExpression(target, inst.Name!)
.WithILInstruction(inst)
.WithRR(new DynamicMemberResolveResult(target.ResolveResult, inst.Name));
}
@ -4415,7 +4418,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4415,7 +4418,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var target = TranslateDynamicTarget(inst.Target, inst.TargetArgumentInfo);
var value = TranslateDynamicArgument(inst.Value, inst.ValueArgumentInfo);
var member = new MemberReferenceExpression(target, inst.Name)
var member = new MemberReferenceExpression(target, inst.Name!)
.WithoutILInstruction()
.WithRR(new DynamicMemberResolveResult(target.ResolveResult, inst.Name));
return Assignment(member, value).WithILInstruction(inst);
@ -4581,7 +4584,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4581,7 +4584,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
var value = TranslateDynamicArgument(inst.Value, inst.ValueArgumentInfo);
var ae = new AssignmentExpression(target, AssignmentExpression.GetAssignmentOperatorTypeFromExpressionType(inst.Operation).Value, value);
var ae = new AssignmentExpression(target, AssignmentExpression.GetAssignmentOperatorTypeFromExpressionType(inst.Operation)!.Value, value);
if (inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext))
ae.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
else
@ -4740,7 +4743,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4740,7 +4743,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (subPattern.HasDesignator)
{
if (!conversionMapping.TryGetValue(subPattern.Variable, out ILVariable value))
if (!conversionMapping.TryGetValue(subPattern.Variable, out ILVariable? value))
{
value = subPattern.Variable;
}
@ -4845,7 +4848,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4845,7 +4848,7 @@ namespace ICSharpCode.Decompiler.CSharp
Debug.Fail("Invalid sub pattern");
continue;
}
IMember member;
IMember? member;
if (testedOperand is CallInstruction call)
{
member = call.Method.AccessorOwner;
@ -4860,7 +4863,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4860,7 +4863,7 @@ namespace ICSharpCode.Decompiler.CSharp
continue;
}
recursivePatternExpression.SubPatterns.Add(
new NamedArgumentExpression { Name = member.Name, Expression = TranslatePattern(subPattern, member.ReturnType) }
new NamedArgumentExpression { Name = member!.Name, Expression = TranslatePattern(subPattern, member.ReturnType) }
.WithRR(new MemberResolveResult(null, member))
);
}

4
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs

@ -26,6 +26,8 @@ @@ -26,6 +26,8 @@
using System.ComponentModel;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
public enum BraceStyle
@ -74,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -74,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
[TypeConverter(typeof(ExpandableObjectConverter))]
public class CSharpFormattingOptions
{
public string Name {
public string? Name {
get;
set;
}

30
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Util; @@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Util;
using Attribute = ICSharpCode.Decompiler.CSharp.Syntax.Attribute;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
/// <summary>
@ -390,7 +392,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -390,7 +392,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
/// Determines whether the specified identifier is a keyword in the given context.
/// If <paramref name="context"/> is <see langword="null" /> all keywords are treated as unconditional.
/// </summary>
public static bool IsKeyword(string identifier, AstNode context = null)
public static bool IsKeyword(string identifier, AstNode? context = null)
{
// only 2-10 char lower-case identifiers can be keywords
if (identifier.Length > maxKeywordLength || identifier.Length < 2 || identifier[0] < 'a')
@ -497,7 +499,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -497,7 +499,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
NewLine();
return;
}
BlockStatement block = embeddedStatement as BlockStatement;
BlockStatement? block = embeddedStatement as BlockStatement;
if (block != null)
{
WriteBlock(block, policy.StatementBraceStyle);
@ -519,7 +521,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -519,7 +521,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
protected virtual void WriteMethodBody(BlockStatement body, BraceStyle style, bool newLine = true)
protected virtual void WriteMethodBody(BlockStatement? body, BraceStyle style, bool newLine = true)
{
if (body is null)
{
@ -540,7 +542,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -540,7 +542,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
protected virtual void WritePrivateImplementationType(AstType privateImplementationType)
protected virtual void WritePrivateImplementationType(AstType? privateImplementationType)
{
if (privateImplementationType is not null)
{
@ -640,11 +642,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -640,11 +642,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
// "int a; new List<int> { a = 1 };" is an object initalizers and invalid, but
// "int a; new List<int> { { a = 1 } };" is a valid collection initializer.
AssignmentExpression ae = expr as AssignmentExpression;
AssignmentExpression? ae = expr as AssignmentExpression;
return ae != null && ae.Operator == AssignmentOperatorType.Assign;
}
protected bool IsObjectOrCollectionInitializer(AstNode node)
protected bool IsObjectOrCollectionInitializer(AstNode? node)
{
if (!(node is ArrayInitializerExpression))
{
@ -1273,7 +1275,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1273,7 +1275,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
unaryOperatorExpression.Expression.AcceptVisitor(this);
if (IsPostfixOperator(opType))
{
WriteToken(opSymbol);
WriteToken(opSymbol!);
}
EndNode(unaryOperatorExpression);
}
@ -1407,7 +1409,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1407,7 +1409,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
Space();
WriteKeyword(QueryJoinClause.IntoKeyword);
WriteIdentifier(queryJoinClause.IntoIdentifierToken);
WriteIdentifier(queryJoinClause.IntoIdentifierToken!);
}
EndNode(queryJoinClause);
}
@ -1861,7 +1863,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1861,7 +1863,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(gotoStatement);
WriteKeyword(GotoStatement.GotoKeyword);
WriteIdentifier(gotoStatement.LabelToken);
WriteIdentifier(gotoStatement.LabelToken!);
Semicolon();
EndNode(gotoStatement);
}
@ -1904,7 +1906,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1904,7 +1906,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteIdentifier(labelStatement.GetChildByRole<Identifier>(SlotKind.Identifier));
WriteToken(Roles.Colon);
bool foundLabelledStatement = false;
for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling)
for (AstNode? tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling)
{
if (tmp.Slot?.Kind == labelStatement.Slot?.Kind)
{
@ -2109,7 +2111,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2109,7 +2111,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (!string.IsNullOrEmpty(catchClause.VariableName))
{
Space();
WriteIdentifier(catchClause.VariableNameToken);
WriteIdentifier(catchClause.VariableNameToken!);
}
Space(policy.SpacesWithinCatchParentheses);
RPar();
@ -2297,7 +2299,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2297,7 +2299,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(constructorDeclaration);
WriteAttributes(constructorDeclaration.Attributes);
WriteModifiers(constructorDeclaration.Modifiers);
TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration;
TypeDeclaration? type = constructorDeclaration.Parent as TypeDeclaration;
if (type != null && type.Name != constructorDeclaration.Name)
WriteIdentifier((Identifier)type.NameToken.Clone());
else
@ -2343,7 +2345,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2343,7 +2345,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
Space();
}
WriteToken(DestructorDeclaration.TildeToken);
TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration;
TypeDeclaration? type = destructorDeclaration.Parent as TypeDeclaration;
if (type != null && type.Name != destructorDeclaration.Name)
WriteIdentifier((Identifier)type.NameToken.Clone());
else
@ -2632,7 +2634,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2632,7 +2634,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
if (!string.IsNullOrEmpty(parameterDeclaration.Name))
{
WriteIdentifier(parameterDeclaration.NameToken);
WriteIdentifier(parameterDeclaration.NameToken!);
}
if (parameterDeclaration.DefaultExpression is not null)
{

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs

@ -24,6 +24,8 @@ @@ -24,6 +24,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
/// <summary>

8
ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs

@ -22,6 +22,8 @@ using System.Linq; @@ -22,6 +22,8 @@ using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
/// <summary>
@ -53,7 +55,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -53,7 +55,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
var v = new GenericGrammarAmbiguityVisitor();
v.genericNestingLevel = 1;
for (AstNode node = binaryOperatorExpression.Right; node != null; node = node.GetNextNode())
for (AstNode? node = binaryOperatorExpression.Right; node != null; node = node.GetNextNode())
{
if (node.AcceptVisitor(v))
return v.ambiguityFound;
@ -78,7 +80,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -78,7 +80,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override bool VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
{
if (binaryOperatorExpression.Left.AcceptVisitor(this))
if (binaryOperatorExpression.Left!.AcceptVisitor(this))
return true;
Debug.Assert(genericNestingLevel > 0);
switch (binaryOperatorExpression.Operator)
@ -105,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -105,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
ambiguityFound = binaryOperatorExpression.Right is ParenthesizedExpression;
return true; // stop visiting
}
return binaryOperatorExpression.Right.AcceptVisitor(this);
return binaryOperatorExpression.Right!.AcceptVisitor(this);
}
public override bool VisitIdentifierExpression(IdentifierExpression identifierExpression)

6
ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs

@ -21,6 +21,8 @@ using System.IO; @@ -21,6 +21,8 @@ using System.IO;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
public abstract class TokenWriter
@ -46,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -46,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
/// <summary>
/// Writes a primitive/literal value
/// </summary>
public abstract void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None);
public abstract void WritePrimitiveValue(object? value, LiteralFormat format = LiteralFormat.None);
public abstract void WritePrimitiveType(string type);
@ -129,7 +131,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -129,7 +131,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
decoratedWriter.WriteToken(token);
}
public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None)
public override void WritePrimitiveValue(object? value, LiteralFormat format = LiteralFormat.None)
{
decoratedWriter.WritePrimitiveValue(value, format);
}

15
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs

@ -21,6 +21,8 @@ using System.Linq; @@ -21,6 +21,8 @@ using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
class InsertMissingTokensDecorator : DecoratingTokenWriter
@ -128,13 +130,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -128,13 +130,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
TextLocation start = locationProvider.Location;
if (keyword == "this")
{
ThisReferenceExpression node = nodes.Peek().LastOrDefault() as ThisReferenceExpression;
ThisReferenceExpression? node = nodes.Peek().LastOrDefault() as ThisReferenceExpression;
if (node != null)
node.StorePrintStart(start);
}
else if (keyword == "base")
{
BaseReferenceExpression node = nodes.Peek().LastOrDefault() as BaseReferenceExpression;
BaseReferenceExpression? node = nodes.Peek().LastOrDefault() as BaseReferenceExpression;
if (node != null)
node.StorePrintStart(start);
}
@ -145,17 +147,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -145,17 +147,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override void WriteIdentifier(Identifier identifier)
{
AssignPendingStartLocations();
if (identifier is not null)
identifier.SetStartLocation(locationProvider.Location);
identifier.SetStartLocation(locationProvider.Location);
currentList.Add(identifier);
base.WriteIdentifier(identifier);
lastTokenEnd = locationProvider.Location;
}
public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None)
public override void WritePrimitiveValue(object? value, LiteralFormat format = LiteralFormat.None)
{
AssignPendingStartLocations();
Expression node = nodes.Peek().LastOrDefault() as Expression;
Expression? node = nodes.Peek().LastOrDefault() as Expression;
var startLocation = locationProvider.Location;
base.WritePrimitiveValue(value, format);
if (node is PrimitiveExpression)
@ -172,7 +173,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -172,7 +173,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override void WritePrimitiveType(string type)
{
AssignPendingStartLocations();
PrimitiveType node = nodes.Peek().LastOrDefault() as PrimitiveType;
PrimitiveType? node = nodes.Peek().LastOrDefault() as PrimitiveType;
if (node != null)
node.StorePrintStart(locationProvider.Location);
base.WritePrimitiveType(type);

18
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -20,6 +20,8 @@ using System; @@ -20,6 +20,8 @@ using System;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
/// <summary>
@ -165,8 +167,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -165,8 +167,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
/// <summary>
/// Parenthesizes the expression if it does not have the minimum required precedence.
/// </summary>
static void ParenthesizeIfRequired(Expression expr, PrecedenceLevel minimumPrecedence)
static void ParenthesizeIfRequired(Expression? expr, PrecedenceLevel minimumPrecedence)
{
if (expr == null)
return;
if (GetPrecedence(expr) < minimumPrecedence)
{
Parenthesize(expr);
@ -222,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -222,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
{
ParenthesizeIfRequired(unaryOperatorExpression.Expression, GetPrecedence(unaryOperatorExpression));
UnaryOperatorExpression child = unaryOperatorExpression.Expression as UnaryOperatorExpression;
UnaryOperatorExpression? child = unaryOperatorExpression.Expression as UnaryOperatorExpression;
if (child != null && InsertParenthesesForReadability)
Parenthesize(child);
base.VisitUnaryOperatorExpression(unaryOperatorExpression);
@ -237,7 +241,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -237,7 +241,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
// There's a nasty issue in the C# grammar: cast expressions including certain operators are ambiguous in some cases
// "(int)-1" is fine, but "(A)-b" is not a cast.
UnaryOperatorExpression uoe = castExpression.Expression as UnaryOperatorExpression;
UnaryOperatorExpression? uoe = castExpression.Expression as UnaryOperatorExpression;
if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not))
{
if (TypeCanBeMisinterpretedAsExpression(castExpression.Type))
@ -246,7 +250,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -246,7 +250,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
// The above issue can also happen with PrimitiveExpressions representing negative values:
PrimitiveExpression pe = castExpression.Expression as PrimitiveExpression;
PrimitiveExpression? pe = castExpression.Expression as PrimitiveExpression;
if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type))
{
TypeCode typeCode = Type.GetTypeCode(pe.Value.GetType());
@ -290,7 +294,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -290,7 +294,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
// SimpleTypes can always be misinterpreted as IdentifierExpressions
// MemberTypes can be misinterpreted as MemberReferenceExpressions if they don't use double colon
// PrimitiveTypes or ComposedTypes can never be misinterpreted as expressions.
MemberType mt = type as MemberType;
MemberType? mt = type as MemberType;
if (mt != null)
return !mt.IsDoubleColon;
else
@ -356,9 +360,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -356,9 +360,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
|| op == BinaryOperatorType.ExclusiveOr;
}
BinaryOperatorType? GetBinaryOperatorType(Expression expr)
BinaryOperatorType? GetBinaryOperatorType(Expression? expr)
{
BinaryOperatorExpression boe = expr as BinaryOperatorExpression;
BinaryOperatorExpression? boe = expr as BinaryOperatorExpression;
if (boe != null)
return boe.Operator;
else

4
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs

@ -20,6 +20,8 @@ using System; @@ -20,6 +20,8 @@ using System;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
class InsertRequiredSpacesDecorator : DecoratingTokenWriter
@ -148,7 +150,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -148,7 +150,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
lastWritten = LastWritten.Whitespace;
}
public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None)
public override void WritePrimitiveValue(object? value, LiteralFormat format = LiteralFormat.None)
{
if (lastWritten == LastWritten.KeywordOrIdentifier)
{

14
ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs

@ -23,6 +23,8 @@ using System.Text; @@ -23,6 +23,8 @@ using System.Text;
using ICSharpCode.Decompiler.CSharp.Syntax;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
/// <summary>
@ -230,10 +232,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -230,10 +232,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
TextWriter writer = new StringWriter();
TextWriterTokenWriter tokenWriter = new TextWriterTokenWriter(writer);
tokenWriter.WritePrimitiveValue(value);
return writer.ToString();
return writer.ToString()!;
}
public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None)
public override void WritePrimitiveValue(object? value, LiteralFormat format = LiteralFormat.None)
{
if (value == null)
{
@ -263,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -263,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (value is string)
{
string tmp = ConvertString(value.ToString());
string tmp = ConvertString(value.ToString()!);
column += tmp.Length + 2;
Length += tmp.Length + 2;
textWriter.Write('"');
@ -409,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -409,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
else
{
textWriter.Write(value.ToString());
int length = value.ToString().Length;
int length = value.ToString()!.Length;
column += length;
Length += length;
}
@ -437,7 +439,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -437,7 +439,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
/// Gets the escape sequence for the specified character.
/// </summary>
/// <remarks>This method does not convert ' or ".</remarks>
static string ConvertChar(char ch)
static string? ConvertChar(char ch)
{
switch (ch)
{
@ -499,7 +501,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -499,7 +501,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StringBuilder sb = new StringBuilder();
foreach (char ch in str)
{
string s = ch == '"' ? "\\\"" : ConvertChar(ch);
string? s = ch == '"' ? "\\\"" : ConvertChar(ch);
if (s != null)
sb.Append(s);
else

14
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -11,6 +11,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -11,6 +11,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation;
using static ICSharpCode.Decompiler.Metadata.ILOpCodeExtensions;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
class RequiredNamespaceCollector
@ -37,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -37,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp
var collector = new RequiredNamespaceCollector(namespaces);
foreach (var type in module.TypeDefinitions)
{
collector.CollectNamespaces(type, module, (CodeMappingInfo)null);
collector.CollectNamespaces(type, module, (CodeMappingInfo?)null);
}
collector.HandleAttributes(module.GetAssemblyAttributes());
collector.HandleAttributes(module.GetModuleAttributes());
@ -50,13 +52,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -50,13 +52,13 @@ namespace ICSharpCode.Decompiler.CSharp
collector.HandleAttributes(module.GetModuleAttributes());
}
public static void CollectNamespaces(IEntity entity, MetadataModule module, HashSet<string> namespaces)
public static void CollectNamespaces(IEntity? entity, MetadataModule module, HashSet<string> namespaces)
{
var collector = new RequiredNamespaceCollector(namespaces);
collector.CollectNamespaces(entity, module);
}
void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo mappingInfo = null)
void CollectNamespaces(IEntity? entity, MetadataModule module, CodeMappingInfo? mappingInfo = null)
{
if (entity == null || entity.MetadataToken.IsNil || module.MetadataFile is not MetadataFile corFile)
return;
@ -230,7 +232,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -230,7 +232,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
void HandleAttributeValue(IType type, object value)
void HandleAttributeValue(IType type, object? value)
{
CollectNamespacesForTypeReference(type);
if (value is IType typeofType)
@ -343,7 +345,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -343,7 +345,7 @@ namespace ICSharpCode.Decompiler.CSharp
case HandleKind.MethodDefinition:
case HandleKind.MethodSpecification:
case HandleKind.MemberReference:
IMember member;
IMember? member;
try
{
member = module.ResolveEntity(handle, genericContext) as IMember;
@ -394,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -394,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
void CollectNamespacesForMemberReference(IMember member)
void CollectNamespacesForMemberReference(IMember? member)
{
switch (member)
{

14
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.DebugInfo; @@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
@ -75,7 +77,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -75,7 +77,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// The function containing this sequence point.
/// </summary>
internal ILFunction Function;
internal ILFunction? Function;
public StatePerSequencePoint(AstNode primaryNode)
{
@ -94,7 +96,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -94,7 +96,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Collects information for the current sequence point.
StatePerSequencePoint current;
void VisitAsSequencePoint(AstNode node)
void VisitAsSequencePoint(AstNode? node)
{
if (node is null)
return;
@ -240,7 +242,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -240,7 +242,7 @@ namespace ICSharpCode.Decompiler.CSharp
public override void VisitQueryFromClause(QueryFromClause queryFromClause)
{
if (queryFromClause.Parent.FirstChild != queryFromClause)
if (queryFromClause.Parent!.FirstChild != queryFromClause)
{
AddToSequencePoint(queryFromClause);
VisitAsSequencePoint(queryFromClause.Expression);
@ -459,7 +461,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -459,7 +461,7 @@ namespace ICSharpCode.Decompiler.CSharp
current = outerStates.Pop();
}
void AddToSequencePointRaw(ILFunction function, IEnumerable<Interval> ranges)
void AddToSequencePointRaw(ILFunction? function, IEnumerable<Interval> ranges)
{
current.Intervals.AddRange(ranges);
Debug.Assert(current.Function == null || current.Function == function);
@ -489,7 +491,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -489,7 +491,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (HasUsableILRange(inst) && current.Intervals != null)
{
current.Intervals.AddRange(inst.ILRanges);
var function = inst.Parent.Ancestors.OfType<ILFunction>().FirstOrDefault();
var function = inst.Parent!.Ancestors.OfType<ILFunction>().FirstOrDefault();
Debug.Assert(current.Function == null || current.Function == function);
current.Function = function;
}
@ -570,7 +572,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -570,7 +572,7 @@ namespace ICSharpCode.Decompiler.CSharp
newList.Add(hidden);
}
List<int> sequencePointCandidates = function.SequencePointCandidates;
List<int> sequencePointCandidates = function.SequencePointCandidates!;
int currSPCandidateIndex = 0;
for (int i = 0; i < newList.Count - 1; i++)

83
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
@ -30,6 +31,8 @@ using ICSharpCode.Decompiler.Semantics; @@ -30,6 +31,8 @@ using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
sealed class StatementBuilder : ILVisitor<TranslatedStatement>
@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.currentReturnContainer = (BlockContainer)currentFunction.Body;
this.currentIsIterator = currentFunction.IsIterator;
this.currentResultType = currentFunction.IsAsync
? currentFunction.AsyncReturnType
? currentFunction.AsyncReturnType!
: currentFunction.ReturnType;
this.typeSystem = typeSystem;
this.settings = settings;
@ -150,7 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -150,7 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp
return new IfElseStatement(condition, trueStatement, falseStatement).WithILInstruction(inst);
}
internal IEnumerable<ConstantResolveResult> CreateTypedCaseLabel(long i, IType type, List<(string Key, int Value)> map = null)
internal IEnumerable<ConstantResolveResult> CreateTypedCaseLabel(long i, IType type, List<(string? Key, int Value)>? map = null)
{
object value;
// unpack nullable type, if necessary:
@ -171,7 +174,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -171,7 +174,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (type.Kind == TypeKind.Enum)
{
var enumType = type.GetDefinition().EnumUnderlyingType;
var enumType = type.GetDefinition()!.EnumUnderlyingType;
TypeCode typeCode = ReflectionHelper.GetTypeCode(enumType);
if (typeCode != TypeCode.Empty)
{
@ -202,12 +205,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -202,12 +205,12 @@ namespace ICSharpCode.Decompiler.CSharp
return TranslateSwitch(null, inst).WithILInstruction(inst);
}
SwitchStatement TranslateSwitch(BlockContainer switchContainer, SwitchInstruction inst)
SwitchStatement TranslateSwitch(BlockContainer? switchContainer, SwitchInstruction inst)
{
var oldBreakTarget = breakTarget;
breakTarget = switchContainer; // 'break' within a switch would only leave the switch
var oldCaseLabelMapping = caseLabelMapping;
caseLabelMapping = new Dictionary<Block, ConstantResolveResult>();
caseLabelMapping = new Dictionary<Block, ConstantResolveResult?>();
var (value, type, strToInt) = exprBuilder.TranslateSwitchValue(inst, false);
@ -219,7 +222,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -219,7 +222,7 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var section in inst.Sections)
{
// This is used in the block-label mapping.
ConstantResolveResult firstValueResolveResult;
ConstantResolveResult? firstValueResolveResult;
var astSection = new Syntax.SwitchSection();
// Create case labels:
if (section == defaultSection)
@ -246,7 +249,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -246,7 +249,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
case Branch br:
// we can only inline the block, if all branches are in the switchContainer.
if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType<Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
if (br.TargetContainer == switchContainer && switchContainer!.Descendants.OfType<Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
caseLabelMapping.Add(br.TargetBlock, firstValueResolveResult);
break;
default:
@ -262,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -262,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
case Branch br:
// we can only inline the block, if all branches are in the switchContainer.
if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType<Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
if (br.TargetContainer == switchContainer && switchContainer!.Descendants.OfType<Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
ConvertSwitchSectionBody(astSection, br.TargetBlock);
else
ConvertSwitchSectionBody(astSection, section.Body);
@ -303,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -303,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
Debug.Assert(block.FinalInstruction.OpCode == OpCode.Nop);
}
if (endContainerLabels.TryGetValue(switchContainer, out string label))
if (endContainerLabels.TryGetValue(switchContainer, out string? label))
{
lastSectionStatements.Add(new LabelStatement { Label = label });
lastSectionStatements.Add(new BreakStatement());
@ -322,7 +325,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -322,7 +325,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (!bodyInst.HasFlag(InstructionFlags.EndPointUnreachable))
{
// we need to insert 'break;'
BlockStatement block = body as BlockStatement;
BlockStatement? block = body as BlockStatement;
if (block != null)
{
block.Add(new BreakStatement());
@ -335,11 +338,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -335,11 +338,11 @@ namespace ICSharpCode.Decompiler.CSharp
}
/// <summary>Target block that a 'continue;' statement would jump to</summary>
Block continueTarget;
Block? continueTarget;
/// <summary>Number of ContinueStatements that were created for the current continueTarget</summary>
int continueCount;
/// <summary>Maps blocks to cases.</summary>
Dictionary<Block, ConstantResolveResult> caseLabelMapping;
/// <summary>Maps blocks to cases. A null value marks the default case.</summary>
Dictionary<Block, ConstantResolveResult?>? caseLabelMapping;
protected internal override TranslatedStatement VisitBranch(Branch inst)
{
@ -359,7 +362,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -359,7 +362,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
/// <summary>Target container that a 'break;' statement would break out of</summary>
BlockContainer breakTarget;
BlockContainer? breakTarget;
/// <summary>Dictionary from BlockContainer to label name for 'goto of_container';</summary>
readonly Dictionary<BlockContainer, string> endContainerLabels = new Dictionary<BlockContainer, string>();
@ -401,7 +404,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -401,7 +404,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
return new ReturnStatement().WithILInstruction(inst);
}
if (!endContainerLabels.TryGetValue(inst.TargetContainer, out string label))
if (!endContainerLabels.TryGetValue(inst.TargetContainer, out string? label))
{
label = "end_" + inst.TargetLabel;
if (!duplicateLabels.TryGetValue(label, out int count))
@ -463,7 +466,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -463,7 +466,7 @@ namespace ICSharpCode.Decompiler.CSharp
catchClause.AddAnnotation(new ILVariableResolveResult(v, v.Type));
if (v.StoreCount > 1 || v.LoadCount > 0 || v.AddressCount > 0)
{
catchClause.VariableName = v.Name;
catchClause.VariableName = v.Name!;
catchClause.Type = exprBuilder.ConvertType(v.Type);
}
else if (!v.Type.IsKnownType(KnownTypeCode.Object))
@ -602,7 +605,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -602,7 +605,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
Statement TransformToForeach(UsingInstruction inst, Expression resource)
Statement? TransformToForeach(UsingInstruction inst, Expression resource)
{
if (!settings.ForEachStatement)
{
@ -680,7 +683,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -680,7 +683,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Handle explicit casts:
// This is the case if an explicit type different from the collection-item-type was used.
// For example: foreach (ClassA item in nonGenericEnumerable)
var type = singleGetter.Method.ReturnType;
var type = singleGetter!.Method.ReturnType;
ILInstruction instToReplace = singleGetter;
bool useVar = false;
switch (instToReplace.Parent)
@ -707,13 +710,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -707,13 +710,13 @@ namespace ICSharpCode.Decompiler.CSharp
break;
}
VariableDesignation designation = null;
VariableDesignation? designation = null;
// Handle the required foreach-variable transformation:
switch (transformation)
{
case RequiredGetCurrentTransformation.UseExistingVariable:
if (foreachVariable.Type.Kind != TypeKind.Dynamic)
if (foreachVariable!.Type.Kind != TypeKind.Dynamic)
foreachVariable.Type = type;
foreachVariable.Kind = VariableKind.ForeachLocal;
foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), decompileRun.UsingScope, foreachVariable);
@ -735,7 +738,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -735,7 +738,7 @@ namespace ICSharpCode.Decompiler.CSharp
VariableKind.Local, type,
AssignVariableNames.GenerateVariableName(currentFunction, type, decompileRun.UsingScope)
);
instToReplace.Parent.ReplaceWith(new LdLoca(localCopyVariable));
instToReplace.Parent!.ReplaceWith(new LdLoca(localCopyVariable));
body.Instructions.Insert(0, new StLoc(localCopyVariable, new LdLoc(foreachVariable)));
body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace));
break;
@ -747,7 +750,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -747,7 +750,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (designation == null)
{
designation = new SingleVariableDesignation { Identifier = foreachVariable.Name };
designation = new SingleVariableDesignation { Identifier = foreachVariable!.Name };
// Add the variable annotation for highlighting
designation.AddAnnotation(new ILVariableResolveResult(foreachVariable, foreachVariable.Type));
}
@ -773,7 +776,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -773,7 +776,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Construct the foreach loop.
var foreachStmt = new ForeachStatement {
IsAsync = isAsync,
VariableType = useVar ? new SimpleType("var") : exprBuilder.ConvertType(foreachVariable.Type),
VariableType = useVar ? new SimpleType("var") : exprBuilder.ConvertType(foreachVariable!.Type),
VariableDesignation = designation,
InExpression = collectionExpr.Detach(),
EmbeddedStatement = foreachBody
@ -851,7 +854,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -851,7 +854,7 @@ namespace ICSharpCode.Decompiler.CSharp
return NormalizeTypeVisitor.TypeErasure.EquivalentTypes(a, b);
}
private bool IsDynamicCastToIEnumerable(Expression expr, out Expression dynamicExpr)
private bool IsDynamicCastToIEnumerable(Expression expr, [NotNullWhen(true)] out Expression? dynamicExpr)
{
if (!(expr is CastExpression cast))
{
@ -874,7 +877,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -874,7 +877,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// Otherwise returns the unmodified container.
/// </summary>
/// <param name="optionalLeaveInst">If the leave is a return/break and has no side-effects, we can move the return out of the using-block and put it after the loop, otherwise returns null.</param>
BlockContainer UnwrapNestedContainerIfPossible(BlockContainer container, out Leave optionalLeaveInst)
BlockContainer UnwrapNestedContainerIfPossible(BlockContainer container, out Leave? optionalLeaveInst)
{
optionalLeaveInst = null;
// Check block structure:
@ -954,7 +957,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -954,7 +957,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// <param name="singleGetter">Returns the call instruction invoking Current's getter.</param>
/// <param name="foreachVariable">Returns the the foreach variable, if a suitable was found. This variable is only assigned once and its assignment is the first statement in <paramref name="loopBody"/>.</param>
/// <returns><see cref="RequiredGetCurrentTransformation"/> for details.</returns>
RequiredGetCurrentTransformation DetectGetCurrentTransformation(BlockContainer usingContainer, Block loopBody, BlockContainer loopContainer, ILVariable enumerator, ILInstruction moveNextUsage, out CallInstruction singleGetter, out ILVariable foreachVariable)
RequiredGetCurrentTransformation DetectGetCurrentTransformation(BlockContainer usingContainer, Block loopBody, BlockContainer loopContainer, ILVariable enumerator, ILInstruction moveNextUsage, out CallInstruction? singleGetter, out ILVariable? foreachVariable)
{
singleGetter = null;
foreachVariable = null;
@ -966,7 +969,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -966,7 +969,7 @@ namespace ICSharpCode.Decompiler.CSharp
// => no foreach
if (loads.Length != 1 || !ParentIsCurrentGetter(loads[0]))
return RequiredGetCurrentTransformation.NoForeach;
singleGetter = (CallInstruction)loads[0].Parent;
singleGetter = (CallInstruction)loads[0].Parent!;
// singleGetter is not part of the first instruction in body or cannot be uninlined
// => no foreach
if (!(singleGetter.IsDescendantOf(loopBody.Instructions[0])
@ -1089,7 +1092,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1089,7 +1092,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (targetType.IsReferenceType ?? false)
return false;
switch (inst.Parent.OpCode)
switch (inst.Parent!.OpCode)
{
case OpCode.Call:
case OpCode.CallVirt:
@ -1173,7 +1176,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1173,7 +1176,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ResolveResult(inst.Variable.Type));
}
}
fixedStmt.Variables.Add(new VariableInitializer(inst.Variable.Name, initExpr).WithILVariable(inst.Variable));
fixedStmt.Variables.Add(new VariableInitializer(inst.Variable.Name!, initExpr).WithILVariable(inst.Variable));
fixedStmt.EmbeddedStatement = Convert(inst.Body);
return fixedStmt.WithILInstruction(inst);
}
@ -1236,8 +1239,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1236,8 +1239,8 @@ namespace ICSharpCode.Decompiler.CSharp
Statement ConvertLoop(BlockContainer container)
{
ILInstruction condition;
Block loopBody;
ILInstruction? condition;
Block? loopBody;
BlockStatement blockStatement;
continueCount = 0;
breakTarget = container;
@ -1387,19 +1390,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1387,19 +1390,19 @@ namespace ICSharpCode.Decompiler.CSharp
LocalFunctionDeclarationStatement TranslateFunction(ILFunction function)
{
var astBuilder = exprBuilder.astBuilder;
var method = (MethodDeclaration)astBuilder.ConvertEntity(function.ReducedMethod);
var method = (MethodDeclaration)astBuilder.ConvertEntity(function.ReducedMethod!);
var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index);
var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index!.Value);
foreach (var (i, p) in method.Parameters.WithIndex())
{
if (variables.TryGetValue(i, out var v))
{
p.Name = v.Name;
p.Name = v.Name!;
}
}
if (function.Method.HasBody)
if (function.Method!.HasBody)
{
var nestedBuilder = new StatementBuilder(
typeSystem,
@ -1428,7 +1431,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1428,7 +1431,7 @@ namespace ICSharpCode.Decompiler.CSharp
method.Modifiers |= Modifiers.Extern;
}
CSharpDecompiler.AddAnnotationsToDeclaration(function.ReducedMethod, method, function);
CSharpDecompiler.AddAnnotationsToDeclaration(function.ReducedMethod!, method, function);
CSharpDecompiler.CleanUpMethodDeclaration(method, method.Body, function, function.Method.HasBody);
CSharpDecompiler.RemoveAttribute(method, KnownAttribute.CompilerGenerated);
var stmt = new LocalFunctionDeclarationStatement(method);
@ -1471,7 +1474,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1471,7 +1474,7 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Add(Convert(block.FinalInstruction));
}
}
if (endContainerLabels.TryGetValue(container, out string label))
if (endContainerLabels.TryGetValue(container, out string? label))
{
if (isLoop && !(blockStatement.LastOrDefault() is ContinueStatement))
{
@ -1491,7 +1494,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1491,7 +1494,7 @@ namespace ICSharpCode.Decompiler.CSharp
string EnsureUniqueLabel(Block block)
{
if (labels.TryGetValue(block, out string label))
if (labels.TryGetValue(block, out string? label))
return label;
if (!duplicateLabels.TryGetValue(block.Label, out int count))
{
@ -1509,10 +1512,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1509,10 +1512,10 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (!leave.Value.MatchNop())
return false;
Block block = (Block)leave.Parent;
Block block = (Block)leave.Parent!;
if (leave.ChildIndex != block.Instructions.Count - 1 || block.FinalInstruction.OpCode != OpCode.Nop)
return false;
BlockContainer container = (BlockContainer)block.Parent;
BlockContainer container = (BlockContainer)block.Parent!;
return block.ChildIndex == container.Blocks.Count - 1
&& container == leave.TargetContainer;
}

5
ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs

@ -310,9 +310,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -310,9 +310,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Insert(IndexOf(existingItem!) + 1, newItem);
}
public void InsertBefore(T existingItem, T newItem)
public void InsertBefore(T? existingItem, T newItem)
{
int index = IndexOf(existingItem);
// A null existingItem yields IndexOf == -1, so the new item is appended.
int index = IndexOf(existingItem!);
Insert(index < 0 ? list.Count : index, newItem);
}

103
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
@ -31,6 +32,8 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -31,6 +32,8 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
/// <summary>
@ -38,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -38,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </summary>
public class TypeSystemAstBuilder
{
readonly CSharpResolver resolver;
readonly CSharpResolver? resolver;
#region Constructor
/// <summary>
@ -479,13 +482,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -479,13 +482,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
AstType ConvertTypeHelper(IType genericType, IReadOnlyList<IType> typeArguments)
{
ITypeDefinition typeDef = genericType.GetDefinition();
ITypeDefinition? typeDef = genericType.GetDefinition();
Debug.Assert(typeDef != null || genericType.Kind == TypeKind.Unknown);
Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount);
if (UseKeywordsForBuiltinTypes && typeDef != null)
{
string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
string? keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
if (keyword != null)
{
return new PrimitiveType(keyword);
@ -527,10 +530,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -527,10 +530,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
localTypeArguments = Empty<IType>.Array;
}
ResolveResult rr = resolver.LookupSimpleNameOrTypeName(typeDef.Name, localTypeArguments, NameLookupMode);
TypeResolveResult trr = rr as TypeResolveResult;
TypeResolveResult? trr = rr as TypeResolveResult;
if (trr != null || (localTypeArguments.Length == 0 && resolver.IsVariableReferenceWithSameType(rr, typeDef.Name, out trr)))
{
if (!trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments))
if (!trr!.IsError && TypeMatches(trr.Type, typeDef, typeArguments))
{
// We can use the short type name
SimpleType shortResult = MakeSimpleType(typeDef.Name);
@ -591,7 +594,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -591,7 +594,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (!TypeDefMatches(typeDef, type.GetDefinition()))
return false;
ParameterizedType pt = type as ParameterizedType;
ParameterizedType? pt = type as ParameterizedType;
if (pt == null)
{
return typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument);
@ -606,14 +609,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -606,14 +609,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
bool TypeDefMatches(ITypeDefinition typeDef, IType type)
bool TypeDefMatches(ITypeDefinition typeDef, IType? type)
{
if (type == null || type.Name != typeDef.Name || type.Namespace != typeDef.Namespace || type.TypeParameterCount != typeDef.TypeParameterCount)
return false;
bool defIsNested = typeDef.DeclaringTypeDefinition != null;
bool typeIsNested = type.DeclaringType != null;
if (defIsNested && typeIsNested)
return TypeDefMatches(typeDef.DeclaringTypeDefinition, type.DeclaringType);
return TypeDefMatches(typeDef.DeclaringTypeDefinition!, type.DeclaringType);
else
return defIsNested == typeIsNested;
}
@ -642,12 +645,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -642,12 +645,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult nrr)
public AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult? nrr)
{
return ConvertNamespace(namespaceName, out nrr, requiresGlobalPrefix: false);
}
AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult nrr, bool requiresGlobalPrefix)
AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult? nrr, bool requiresGlobalPrefix)
{
if (resolver != null)
{
@ -702,7 +705,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -702,7 +705,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
};
if (AddResolveResultAnnotations)
{
var @namespace = resolver.Compilation.RootNamespace.GetChildNamespace(namespaceName);
var @namespace = resolver!.Compilation.RootNamespace.GetChildNamespace(namespaceName);
if (@namespace != null)
ns.AddAnnotation(nrr = new NamespaceResolveResult(@namespace));
}
@ -731,7 +734,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -731,7 +734,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
bool IsValidNamespace(string firstNamespacePart, out NamespaceResolveResult nrr)
bool IsValidNamespace(string firstNamespacePart, out NamespaceResolveResult? nrr)
{
nrr = null;
if (resolver == null)
@ -795,7 +798,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -795,7 +798,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType);
foreach (var namedArg in attribute.NamedArguments)
{
NamedExpression namedArgument = new NamedExpression(namedArg.Name, ConvertConstantValue(namedArg.Type, namedArg.Value));
NamedExpression namedArgument = new NamedExpression(namedArg.Name!, ConvertConstantValue(namedArg.Type, namedArg.Value));
if (AddResolveResultAnnotations)
{
IMember member = CustomAttribute.MemberForNamedArgument(attribute.AttributeType, namedArg);
@ -817,10 +820,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -817,10 +820,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return attr;
}
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attributes, string target = null)
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attributes, string? target = null)
{
if (SortAttributes)
attributes = attributes.OrderBy(a => a, new DelegateComparer<IAttribute>(CompareAttribute));
attributes = attributes.OrderBy(a => a, new DelegateComparer<IAttribute>((a, b) => CompareAttribute(a!, b!)));
return attributes.Select(a => {
var section = new AttributeSection(ConvertAttribute(a));
if (target != null)
@ -863,7 +866,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -863,7 +866,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
var argA = a.NamedArguments[i];
var argB = b.NamedArguments[i];
result = argA.Name.CompareTo(argB.Name);
result = argA.Name!.CompareTo(argB.Name);
if (result != 0)
return result;
result = CompareType(argA.Type, argB.Type);
@ -893,7 +896,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -893,7 +896,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
throw new ArgumentNullException(nameof(type));
AstType astType = ConvertTypeHelper(type);
string shortName = null;
string? shortName = null;
if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal))
{
shortName = type.Name.Remove(type.Name.Length - 9);
@ -919,16 +922,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -919,16 +922,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return astType;
}
private void ApplyShortAttributeNameIfPossible(IType type, AstType astType, string shortName)
private void ApplyShortAttributeNameIfPossible(IType type, AstType astType, string? shortName)
{
switch (astType)
{
case SimpleType st:
ResolveResult shortRR = null;
ResolveResult withExtraAttrSuffix = resolver.LookupSimpleNameOrTypeName(type.Name + "Attribute", EmptyList<IType>.Instance, NameLookupMode.Type);
ResolveResult? shortRR = null;
ResolveResult withExtraAttrSuffix = resolver!.LookupSimpleNameOrTypeName(type.Name + "Attribute", EmptyList<IType>.Instance, NameLookupMode.Type);
if (shortName != null)
{
shortRR = resolver.LookupSimpleNameOrTypeName(shortName, EmptyList<IType>.Instance, NameLookupMode.Type);
shortRR = resolver!.LookupSimpleNameOrTypeName(shortName, EmptyList<IType>.Instance, NameLookupMode.Type);
}
// short type is either unknown or not an attribute type -> we can use the short name.
if (shortRR != null && (shortRR is UnknownIdentifierResolveResult || !IsAttributeType(shortRR)))
@ -972,7 +975,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -972,7 +975,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
private bool IsAttributeType(IType type)
private bool IsAttributeType(IType? type)
{
return type != null && type.GetNonInterfaceBaseTypes().Any(t => t.IsKnownType(KnownTypeCode.Attribute));
}
@ -1066,7 +1069,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1066,7 +1069,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// which is of type <c>int</c>.
/// However, the returned expression will always be implicitly convertible to <paramref name="type"/>.
/// </summary>
public Expression ConvertConstantValue(IType type, object constantValue)
public Expression ConvertConstantValue(IType type, object? constantValue)
{
return ConvertConstantValue(type, type, constantValue);
}
@ -1074,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1074,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// <summary>
/// Creates an Expression for the given constant value.
/// </summary>
public Expression ConvertConstantValue(IType expectedType, IType type, object constantValue)
public Expression ConvertConstantValue(IType expectedType, IType type, object? constantValue)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
@ -1132,7 +1135,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1132,7 +1135,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
if (underlyingType.IsKnownType(KnownTypeCode.Double) || underlyingType.IsKnownType(KnownTypeCode.Single))
return ConvertFloatingPointLiteral(underlyingType, constantValue);
IType literalType = underlyingType;
IType? literalType = underlyingType;
bool integerTypeMismatch = underlyingType.IsCSharpSmallIntegerType() || underlyingType.IsCSharpNativeIntegerType();
if (integerTypeMismatch)
{
@ -1161,7 +1164,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1161,7 +1164,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
bool IsSpecialConstant(IType expectedType, object constant, out Expression expression)
bool IsSpecialConstant(IType expectedType, object constant, [NotNullWhen(true)] out Expression? expression)
{
expression = null;
if (!specialConstants.TryGetValue(constant, out var info))
@ -1292,7 +1295,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1292,7 +1295,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Expression ConvertEnumValue(IType type, long val)
{
ITypeDefinition enumDefinition = type.GetDefinition();
ITypeDefinition enumDefinition = type.GetDefinition()!;
TypeCode enumBaseTypeCode = ReflectionHelper.GetTypeCode(enumDefinition.EnumUnderlyingType);
var fields = enumDefinition.Fields
.Select(PrepareConstant)
@ -1311,7 +1314,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1311,7 +1314,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (IsFlagsEnum(enumDefinition))
{
long enumValue = val;
Expression expr = null;
Expression? expr = null;
long negatedEnumValue = ~val;
// limit negatedEnumValue to the appropriate range
switch (enumBaseTypeCode)
@ -1329,7 +1332,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1329,7 +1332,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
negatedEnumValue &= uint.MaxValue;
break;
}
Expression negatedExpr = null;
Expression? negatedExpr = null;
foreach (var (fieldValue, field) in fields.OrderByDescending(f => CalculateHammingWeight(unchecked((ulong)f.value))))
{
if (fieldValue == 0)
@ -1373,10 +1376,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1373,10 +1376,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
(long value, IField field) PrepareConstant(IField field)
{
if (!field.IsConst)
return (-1, null);
object constantValue = field.GetConstantValue();
return (-1, null!);
object? constantValue = field.GetConstantValue();
if (constantValue == null)
return (-1, null);
return (-1, null!);
return ((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, checkForOverflow: false), field);
}
@ -1442,8 +1445,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1442,8 +1445,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// even if the expected type is float or double.
constantValue = CSharpPrimitiveCast.Cast(type.GetTypeCode(), constantValue, false);
bool isDouble = type.IsKnownType(KnownTypeCode.Double);
ICompilation compilation = type.GetDefinition().Compilation;
Expression expr = null;
ICompilation compilation = type.GetDefinition()!.Compilation;
Expression? expr = null;
string str;
if (isDouble)
@ -1522,7 +1525,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1522,7 +1525,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
const float MathF_PI = 3.14159274f;
const float MathF_E = 2.71828175f;
Expression TryExtractExpression(IType mathType, IType type, object literalValue, string memberName, bool isDouble)
Expression? TryExtractExpression(IType mathType, IType type, object literalValue, string memberName, bool isDouble)
{
Expression MakeFieldReference()
{
@ -1543,7 +1546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1543,7 +1546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return new CastExpression(ConvertType(type), fieldRef);
}
Expression ExtractExpression(long n, long d)
Expression? ExtractExpression(long n, long d)
{
Expression fieldReference = MakeFieldReference();
@ -1777,7 +1780,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1777,7 +1780,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case SymbolKind.TypeParameter:
return ConvertTypeParameter((ITypeParameter)symbol);
default:
IEntity entity = symbol as IEntity;
IEntity? entity = symbol as IEntity;
if (entity != null)
return ConvertEntity(entity);
throw new ArgumentException("Invalid value for SymbolKind: " + symbol.SymbolKind);
@ -1811,7 +1814,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1811,7 +1814,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case SymbolKind.Accessor:
IMethod accessor = (IMethod)entity;
Accessibility ownerAccessibility = accessor.AccessorOwner?.Accessibility ?? Accessibility.None;
return ConvertAccessor(accessor, accessor.AccessorKind, ownerAccessibility, false);
return ConvertAccessor(accessor, accessor.AccessorKind, ownerAccessibility, false)!;
default:
throw new ArgumentException("Invalid value for SymbolKind: " + entity.SymbolKind);
}
@ -1823,7 +1826,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1823,7 +1826,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
var subst = new TypeParameterSubstitution(group.TypeParameters, []);
ext.TypeParameters.AddRange(group.TypeParameters.Select(ConvertTypeParameter));
ext.ReceiverParameters.Add(ConvertParameter(group.MarkerMethod.Specialize(subst).Parameters.Single()));
ext.Constraints.AddRange(group.TypeParameters.Select(ConvertTypeParameterConstraint));
ext.Constraints.AddRange(group.TypeParameters.Select(ConvertTypeParameterConstraint).OfType<Constraint>());
return ext;
}
@ -1932,7 +1935,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1932,7 +1935,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// if the declared type is an enum, replace all references to System.Enum with the enum-underlying type
if (!typeDefinition.EnumUnderlyingType.IsKnownType(KnownTypeCode.Int32))
{
decl.BaseTypes.Add(ConvertType(typeDefinition.EnumUnderlyingType));
decl.BaseTypes.Add(ConvertType(typeDefinition.EnumUnderlyingType!));
}
}
else if ((typeDefinition.Kind == TypeKind.Struct || typeDefinition.Kind == TypeKind.Void) && baseType.IsKnownType(KnownTypeCode.ValueType))
@ -1974,7 +1977,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1974,7 +1977,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers)
{
ITypeDefinition d = invokeMethod.DeclaringTypeDefinition;
ITypeDefinition d = invokeMethod.DeclaringTypeDefinition!;
DelegateDeclaration decl = new DelegateDeclaration();
decl.Modifiers = modifiers & ~Modifiers.Sealed;
@ -2055,7 +2058,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2055,7 +2058,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
ct.HasReadOnlySpecifier = true;
}
Expression initializer = null;
Expression? initializer = null;
if (field.IsConst && this.ShowConstantValues)
{
try
@ -2071,7 +2074,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2071,7 +2074,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return decl;
}
BlockStatement GenerateBodyBlock()
BlockStatement? GenerateBodyBlock()
{
if (GenerateBody)
{
@ -2085,7 +2088,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2085,7 +2088,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
Accessor ConvertAccessor(IMethod accessor, MethodSemanticsAttributes kind, Accessibility ownerAccessibility, bool addParameterAttribute)
Accessor? ConvertAccessor(IMethod? accessor, MethodSemanticsAttributes kind, Accessibility ownerAccessibility, bool addParameterAttribute)
{
if (accessor == null)
return null;
@ -2155,7 +2158,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2155,7 +2158,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return decl;
}
static void MergeReadOnlyModifiers(EntityDeclaration decl, Accessor accessor1, Accessor accessor2)
static void MergeReadOnlyModifiers(EntityDeclaration decl, Accessor? accessor1, Accessor? accessor2)
{
if (accessor1 is null)
return;
@ -2164,7 +2167,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2164,7 +2167,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
accessor1.Modifiers &= ~Modifiers.Readonly;
decl.Modifiers |= Modifiers.Readonly;
}
else if (accessor1.HasModifier(Modifiers.Readonly) && accessor2.HasModifier(Modifiers.Readonly))
else if (accessor1.HasModifier(Modifiers.Readonly) && accessor2!.HasModifier(Modifiers.Readonly))
{
accessor1.Modifiers &= ~Modifiers.Readonly;
accessor2.Modifiers &= ~Modifiers.Readonly;
@ -2479,7 +2482,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2479,7 +2482,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return decl;
}
internal Constraint ConvertTypeParameterConstraint(ITypeParameter tp)
internal Constraint? ConvertTypeParameterConstraint(ITypeParameter tp)
{
if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && !tp.AllowsRefLikeType && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType))
{
@ -2543,7 +2546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2543,7 +2546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
static bool IsObjectOrValueType(IType type)
{
ITypeDefinition d = type.GetDefinition();
ITypeDefinition? d = type.GetDefinition();
return d != null && (d.KnownTypeCode == KnownTypeCode.Object || d.KnownTypeCode == KnownTypeCode.ValueType);
}
#endregion
@ -2554,7 +2557,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2554,7 +2557,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
VariableDeclarationStatement decl = new VariableDeclarationStatement();
decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None;
decl.Type = ConvertType(v.Type);
Expression initializer = null;
Expression? initializer = null;
if (v.IsConst)
{
try
@ -2576,7 +2579,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2576,7 +2579,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return new NamespaceDeclaration(ns.FullName);
}
AstType GetExplicitInterfaceType(IMember member)
AstType? GetExplicitInterfaceType(IMember member)
{
if (member.IsExplicitInterfaceImplementation)
{

2
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -805,7 +805,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -805,7 +805,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
foreach (var node in rootNode.Descendants)
{
ILVariable ilVar;
ILVariable? ilVar;
switch (node)
{
case IdentifierExpression id:

13
ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs

@ -52,15 +52,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -52,15 +52,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (fieldDecl.Variables.Count != 1)
continue;
string oldName = fieldDecl.Variables.Single().Name;
ISymbol symbol = fieldDecl.GetSymbol();
if (memberNames.Contains(oldName) && ((IField)symbol).Accessibility == Accessibility.Private)
ISymbol? symbol = fieldDecl.GetSymbol();
if (memberNames.Contains(oldName) && symbol is IField { Accessibility: Accessibility.Private })
{
string newName = PickNewName(memberNames, oldName);
if (symbol != null)
{
fieldDecl.Variables.Single().Name = newName;
renamedSymbols[symbol] = newName;
}
fieldDecl.Variables.Single().Name = newName;
renamedSymbols[symbol] = newName;
}
}
}
@ -69,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -69,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
if (node is IdentifierExpression || node is MemberReferenceExpression)
{
ISymbol symbol = node.GetSymbol();
ISymbol? symbol = node.GetSymbol();
if (symbol != null && renamedSymbols.TryGetValue(symbol, out string? newName))
{
node.GetChildByRole<Identifier>(SlotKind.Identifier).Name = newName;

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
return;
}
var method = (IMethod)invocationExpression.GetSymbol();
var method = (IMethod)invocationExpression.GetSymbol()!;
if (firstArgument is DirectionExpression dirExpr)
{
if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out)

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (mre.MemberName == "GroupJoin")
{
joinClause.IntoIdentifier = p2.Name; // into p2.Name
joinClause.IntoIdentifierToken.CopyAnnotationsFrom(p2);
joinClause.IntoIdentifierToken!.CopyAnnotationsFrom(p2);
}
joinClause.AddAnnotation(new QueryJoinClauseAnnotation(outerLambda.Annotation<IL.ILFunction>(), innerLambda.Annotation<IL.ILFunction>()));
query.Clauses.Add(joinClause);

6
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -235,7 +235,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -235,7 +235,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return true;
}
bool ForStatementUsesVariable(ForStatement statement, IL.ILVariable variable)
bool ForStatementUsesVariable(ForStatement statement, IL.ILVariable? variable)
{
if (statement.Condition?.DescendantsAndSelf.OfType<IdentifierExpression>().Any(ie => ie.GetILVariable() == variable) == true)
return true;
@ -515,7 +515,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -515,7 +515,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
break;
if (!int.TryParse(m.Get<PrimitiveExpression>("index").Single().Value?.ToString() ?? "", out int index) || index != i)
break;
upperBounds[i] = m.Get<IdentifierExpression>("variable").Single().GetILVariable();
upperBounds[i] = m.Get<IdentifierExpression>("variable").Single().GetILVariable()!;
stmt = stmt.GetNextStatement();
i++;
} while (stmt != null && upperBounds != null && i < upperBounds.Length);
@ -948,7 +948,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -948,7 +948,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// ignore tuple element names, dynamic and nullability
if (!NormalizeTypeVisitor.TypeErasure.EquivalentTypes(returnType, eventType))
return false;
var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.GetSymbol() as IMethod;
var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent!.GetSymbol() as IMethod;
if (combineMethod == null || combineMethod.Name != (isAddAccessor ? "Combine" : "Remove"))
return false;
return combineMethod.DeclaringType.FullName == "System.Delegate";

14
ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

@ -284,7 +284,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -284,7 +284,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
MemberToDeclaringSyntaxNodeMap = members
.Select(m => (symbol: m.GetSymbol(), entity: (EntityDeclaration)m))
.Where(_ => _.symbol is IMember)
.ToDictionary(_ => (IMember)_.symbol, _ => _.entity);
.ToDictionary(_ => (IMember)_.symbol!, _ => _.entity);
List<ConstructorDeclaration> constructorsNotChainedWithThis = [];
List<ConstructorDeclaration> allCtors = [];
@ -298,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -298,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
foreach (var ctor in members.OfType<ConstructorDeclaration>())
{
var ctorMethod = (IMethod)ctor.GetSymbol();
var ctorMethod = (IMethod)ctor.GetSymbol()!;
Debug.Assert(ctorMethod.IsConstructor);
Debug.Assert(ctorMethod.MetadataToken.IsNil == false);
@ -351,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -351,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// this constructor could be converted to a primary constructor
var ctor = constructorsNotChainedWithThis[0];
var ctorMethod = (IMethod)constructorsNotChainedWithThis[0].GetSymbol();
var ctorMethod = (IMethod)constructorsNotChainedWithThis[0].GetSymbol()!;
var initializer = InitializerSequence.Analyze(this, ctor, ctorMethod);
@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
bool isPrimaryCtor = constructorsNotChainedWithThis[0] == PrimaryConstructorDecl;
var sequence = isPrimaryCtor
? PrimaryConstructorInitializers
: InitializerSequence.Analyze(this, constructorsNotChainedWithThis[0], (IMethod)constructorsNotChainedWithThis[0].GetSymbol());
: InitializerSequence.Analyze(this, constructorsNotChainedWithThis[0], (IMethod)constructorsNotChainedWithThis[0].GetSymbol()!);
if (sequence == null)
return false;
@ -705,7 +705,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -705,7 +705,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return;
var ctor = InstanceConstructors[0];
var ctorMethod = (IMethod)ctor.GetSymbol();
var ctorMethod = (IMethod)ctor.GetSymbol()!;
if (TypeDefinition.Kind == TypeKind.Struct && ctorMethod.Parameters.Count == 0 && InstanceInitializers != null)
{
@ -810,7 +810,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -810,7 +810,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
foreach (var typeDeclaration in node.Descendants.OfType<TypeDeclaration>())
{
var currentTypeDefinition = (ITypeDefinition)typeDeclaration.GetSymbol();
var currentTypeDefinition = (ITypeDefinition)typeDeclaration.GetSymbol()!;
TransformDeclaration(currentTypeDefinition, typeDeclaration, typeDeclaration.Members);
}
}
@ -838,7 +838,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -838,7 +838,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
foreach (var constructorDeclaration in members.OfType<ConstructorDeclaration>())
{
analyzer.MoveConstructorInitializer(constructorDeclaration, (IMethod)constructorDeclaration.GetSymbol());
analyzer.MoveConstructorInitializer(constructorDeclaration, (IMethod)constructorDeclaration.GetSymbol()!);
}
analyzer.RemoveImplicitConstructor();

6
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Semantics; @@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
@ -156,7 +158,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -156,7 +158,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (descendant == Expression)
return this;
for (AstNode parent = descendant.Parent; parent != null; parent = parent.Parent)
for (AstNode? parent = descendant.Parent; parent != null; parent = parent.Parent)
{
foreach (var inst in parent.Annotations.OfType<ILInstruction>())
descendant.AddAnnotation(inst);
@ -664,7 +666,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -664,7 +666,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// In conditional contexts, remove the bool-cast emitted when converting
/// an "implicit operator bool" invocation.
/// </summary>
public TranslatedExpression UnwrapImplicitBoolConversion(Func<IType, bool> typeFilter = null)
public TranslatedExpression UnwrapImplicitBoolConversion(Func<IType, bool>? typeFilter = null)
{
if (!this.Type.IsKnownType(KnownTypeCode.Boolean))
return this;

2
ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs

@ -6,6 +6,8 @@ using System.Linq; @@ -6,6 +6,8 @@ using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
[DebuggerDisplay("{Statement}")]

2
ICSharpCode.Decompiler/CSharp/TranslationContext.cs

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
using ICSharpCode.Decompiler.TypeSystem;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>

2
ILSpy/Languages/CSharpHighlightingTokenWriter.cs

@ -437,7 +437,7 @@ namespace ICSharpCode.ILSpy.Languages @@ -437,7 +437,7 @@ namespace ICSharpCode.ILSpy.Languages
}
}
public override void WritePrimitiveValue(object value, ICSharpCode.Decompiler.CSharp.Syntax.LiteralFormat format)
public override void WritePrimitiveValue(object? value, ICSharpCode.Decompiler.CSharp.Syntax.LiteralFormat format)
{
HighlightingColor? color = null;
if (value is null)

Loading…
Cancel
Save