diff --git a/ICSharpCode.Decompiler/CSharp/Annotations.cs b/ICSharpCode.Decompiler/CSharp/Annotations.cs index 8da11f0f9..e9429557b 100644 --- a/ICSharpCode.Decompiler/CSharp/Annotations.cs +++ b/ICSharpCode.Decompiler/CSharp/Annotations.cs @@ -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 /// Retrieves the associated with this AstNode, or null if no symbol /// is associated with the node. /// - public static ISymbol GetSymbol(this AstNode node) + public static ISymbol? GetSymbol(this AstNode node) { var rr = node.Annotation(); if (rr is MethodGroupResolveResult mgrr) @@ -157,7 +159,7 @@ namespace ICSharpCode.Decompiler.CSharp /// Retrieves the associated with this , /// or null if no variable is associated with this identifier. /// - public static ILVariable GetILVariable(this IdentifierExpression expr) + public static ILVariable? GetILVariable(this IdentifierExpression expr) { if (expr.Annotation() is ILVariableResolveResult rr) return rr.Variable; @@ -169,7 +171,7 @@ namespace ICSharpCode.Decompiler.CSharp /// Retrieves the associated with this , /// or null if no variable is associated with this initializer. /// - public static ILVariable GetILVariable(this VariableInitializer vi) + public static ILVariable? GetILVariable(this VariableInitializer vi) { if (vi.Annotation() is ILVariableResolveResult rr) return rr.Variable; @@ -181,7 +183,7 @@ namespace ICSharpCode.Decompiler.CSharp /// Retrieves the associated with this , /// or null if no variable is associated with this foreach statement. /// - public static ILVariable GetILVariable(this ForeachStatement loop) + public static ILVariable? GetILVariable(this ForeachStatement loop) { if (loop.Annotation() is ILVariableResolveResult rr) return rr.Variable; diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 83355f8f9..f09270828 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -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; using SRM = System.Reflection.Metadata; +#nullable enable + 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 ilTransforms = GetILTransforms(); @@ -210,12 +213,12 @@ namespace ICSharpCode.Decompiler.CSharp /// /// Gets or sets the optional provider for debug info. /// - public IDebugInfoProvider DebugInfoProvider { get; set; } + public IDebugInfoProvider? DebugInfoProvider { get; set; } /// /// Gets or sets the optional provider for XML documentation strings. /// - public IDocumentationProvider DocumentationProvider { get; set; } + public IDocumentationProvider? DocumentationProvider { get; set; } /// /// IL transforms. @@ -275,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp /// The module containing the member. /// The metadata token/handle of the member. Can be a TypeDef, MethodDef or FieldDef. /// 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. - 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 return typeSystemAstBuilder; } - IDocumentationProvider CreateDefaultDocumentationProvider() + IDocumentationProvider? CreateDefaultDocumentationProvider() { try { @@ -783,8 +786,8 @@ namespace ICSharpCode.Decompiler.CSharp void DoDecompileTypes(IEnumerable 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 } 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 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(); syntaxTree = new SyntaxTree(); @@ -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 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 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 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(SlotKind.TypeParameter) @@ -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 { 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 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 fieldsAndProperties = isRecord - ? recordDecompiler.FieldsAndProperties + ? recordDecompiler!.FieldsAndProperties : typeDef.Fields.Concat(typeDef.Properties); // For COM interop scenarios, the relative order of virtual functions/properties matters: @@ -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 case EnumValueDisplayMode.AllHex: foreach (var enumMember in typeDecl.Members.OfType()) { - 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 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 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 { 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 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 } 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 && 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 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 { 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 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(SlotKind.Parameter)) { if (parameters.TryGetValue(i, out var v)) @@ -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 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 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 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 } } - 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 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 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 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 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 } 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); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs b/ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs index 66c4cdb57..39d75af15 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs @@ -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 diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 0e81ae130..540bd86a0 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -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; 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 public TranslatedExpression[] Arguments; public IParameter[] ExpectedParameters; public string[] ParameterNames; - public string[] ArgumentNames; + public string[]? ArgumentNames; public int FirstOptionalArgumentIndex; public BitSet IsPrimitiveValue; - public IReadOnlyList ArgumentToParameterMap; + public IReadOnlyList? ArgumentToParameterMap; public bool AddNamesToPrimitiveValues; public bool UseImplicitlyTypedOut; @@ -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 { 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 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 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 public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList callArguments, - IReadOnlyList argumentToParameterMap = null, - IType constrainedTo = null) + IReadOnlyList? argumentToParameterMap = null, + IType? constrainedTo = null) { if (method.IsExplicitInterfaceImplementation && callOpCode == OpCode.Call) { @@ -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 } 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 } 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 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 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 } public ExpressionWithResolveResult BuildDictionaryInitializerExpression(OpCode callOpCode, IMethod method, - InitializedObjectResolveResult target, IReadOnlyList indices, ILInstruction value = null) + InitializedObjectResolveResult target, IReadOnlyList indices, ILInstruction? value = null) { if (method is null) throw new ArgumentNullException(nameof(method)); @@ -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 return false; if (!arguments.Skip(1).All(a => !a.Expression.DescendantsAndSelf.OfType().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 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 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 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 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 } } - private ArgumentList BuildArgumentList(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method, - int firstParamIndex, IReadOnlyList callArguments, IReadOnlyList argumentToParameterMap) + private ArgumentList BuildArgumentList(ExpectedTargetDetails expectedTargetDetails, ResolveResult? target, IMethod method, + int firstParamIndex, IReadOnlyList callArguments, IReadOnlyList? argumentToParameterMap) { ArgumentList list = new ArgumentList(); // Translate arguments to the expected parameter types var arguments = new List(method.Parameters.Count); - string[] argumentNames = null; + string[]? argumentNames = null; Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count); var expectedParameters = new List(method.Parameters.Count); // parameters, but in argument order bool isExpandedForm = false; @@ -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 expectedParameters, ref List 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 } return false; - bool ExtractArguments(out IType elementType, out List parameters, out List arguments) + bool ExtractArguments([NotNullWhen(true)] out IType? elementType, [NotNullWhen(true)] out List? parameters, [NotNullWhen(true)] out List? arguments) { elementType = null; parameters = null; @@ -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 } 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 return OverloadResolutionErrors.None; } - bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method, - IList arguments, string[] argumentNames, out IMember foundMember) + bool IsUnambiguousAccess(ExpectedTargetDetails expectedTargetDetails, ResolveResult? target, IMethod method, + IList 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 foundMember = null; if (target == null) { - var result = resolver.ResolveSimpleName(method.AccessorOwner.Name, + var result = resolver.ResolveSimpleName(method.AccessorOwner!.Name, EmptyList.Instance, isInvocationTarget: false) as MemberResolveResult; if (result == null || result.IsError) @@ -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 else { var result = lookup.Lookup(target, - method.AccessorOwner.Name, + method.AccessorOwner!.Name, EmptyList.Instance, isInvocation: false) as MemberResolveResult; if (result == null || result.IsError) @@ -1633,10 +1638,10 @@ namespace ICSharpCode.Decompiler.CSharp } ExpressionWithResolveResult HandleAccessorCall(ExpectedTargetDetails expectedTargetDetails, IMethod method, - TranslatedExpression target, List arguments, string[] argumentNames) + TranslatedExpression target, List 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 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 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 } 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 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 } 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 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 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 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 } - (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 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 typeArguments = EmptyList.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 } break; } - return (currentTarget, addTypeArguments, method.Name, result); + return (currentTarget, addTypeArguments, method.Name, result!); } else { @@ -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 typeArguments = EmptyList.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 { result = mgrr.WithChosenMethod(method); } - return (currentTarget, addTypeArguments, method.Name, result); + return (currentTarget, addTypeArguments, method.Name, result!); } } @@ -2071,7 +2076,7 @@ namespace ICSharpCode.Decompiler.CSharp return oce; } - bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult target, IReadOnlyList typeArguments, bool isExtensionMethodReference, out ResolveResult result) + bool IsUnambiguousMethodReference(ExpectedTargetDetails expectedTargetDetails, IMethod method, ResolveResult? target, IReadOnlyList typeArguments, bool isExtensionMethodReference, [NotNullWhen(true)] out ResolveResult? result) { Log.WriteLine("IsUnambiguousMethodReference: Performing overload resolution for " + method); diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 41ed4ba6b..7630597d6 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -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 { /// @@ -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 } } - 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 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 } } - 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()) { - 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 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 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 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 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 { Expression expr; IType constantType; - object constantValue; + object? constantValue; if (type.IsReferenceType == true) { expr = new NullReferenceExpression(); @@ -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 } 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 } } - internal TranslatedExpression CallUnsafeIntrinsic(string name, Expression[] arguments, IType returnType, ILInstruction inst = null, IEnumerable typeArguments = null) + internal TranslatedExpression CallUnsafeIntrinsic(string name, Expression[] arguments, IType returnType, ILInstruction? inst = null, IEnumerable? typeArguments = null) { var target = new MemberReferenceExpression { Target = new TypeReferenceExpression(astBuilder.ConvertType(compilation.FindType(KnownTypeCode.Unsafe))), @@ -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 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 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 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 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 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 IEnumerable MakeParameters(IReadOnlyList 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 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 } } - 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 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 { 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 var elementsStack = new Stack>(); var elements = new List(block.Instructions.Count); elementsStack.Push(elements); - List currentPath = null; + List? currentPath = null; var indexVariables = new Dictionary(); foreach (var inst in block.Instructions.Skip(1)) { @@ -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 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 } 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 { 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 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 } } ArraySpecifier[] additionalSpecifiers; - AstType typeExpression; + AstType? typeExpression; if (settings.AnonymousTypes && type.ContainsAnonymousType()) { typeExpression = null; @@ -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 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 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 { 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 } 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 { 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 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 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)) ); } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs index 9154eaffd..d0cb2bd99 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs @@ -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 [TypeConverter(typeof(ExpandableObjectConverter))] public class CSharpFormattingOptions { - public string Name { + public string? Name { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 7d92761f2..9949072f2 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Util; using Attribute = ICSharpCode.Decompiler.CSharp.Syntax.Attribute; +#nullable enable + 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 is all keywords are treated as unconditional. /// - 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 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 } } - 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 } } - 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 { // "int a; new List { a = 1 };" is an object initalizers and invalid, but // "int a; new List { { 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 unaryOperatorExpression.Expression.AcceptVisitor(this); if (IsPostfixOperator(opType)) { - WriteToken(opSymbol); + WriteToken(opSymbol!); } EndNode(unaryOperatorExpression); } @@ -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 { StartNode(gotoStatement); WriteKeyword(GotoStatement.GotoKeyword); - WriteIdentifier(gotoStatement.LabelToken); + WriteIdentifier(gotoStatement.LabelToken!); Semicolon(); EndNode(gotoStatement); } @@ -1904,7 +1906,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteIdentifier(labelStatement.GetChildByRole(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 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 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 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 } if (!string.IsNullOrEmpty(parameterDeclaration.Name)) { - WriteIdentifier(parameterDeclaration.NameToken); + WriteIdentifier(parameterDeclaration.NameToken!); } if (parameterDeclaration.DefaultExpression is not null) { diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs index 6718681d3..24e42daf4 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs @@ -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 { /// diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs index e4e340d2b..7e4d52039 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs @@ -22,6 +22,8 @@ using System.Linq; using ICSharpCode.Decompiler.CSharp.Syntax; +#nullable enable + 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 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 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) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs index 6566dc65a..e5d7ed968 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs @@ -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 /// /// Writes a primitive/literal value /// - 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 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); } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index 2c303237c..9c6398c15 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -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 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 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 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); diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs index dfd1132be..762a1ef5a 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -20,6 +20,8 @@ using System; using ICSharpCode.Decompiler.CSharp.Syntax; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { /// @@ -165,8 +167,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// /// Parenthesizes the expression if it does not have the minimum required precedence. /// - 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 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 } // 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 } } // 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 // 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 || 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 diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs index 3c94be5d4..94bc37f60 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs @@ -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 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) { diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs index 2f450c2a1..8819f804c 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs @@ -23,6 +23,8 @@ using System.Text; using ICSharpCode.Decompiler.CSharp.Syntax; +#nullable enable + 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 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 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 /// Gets the escape sequence for the specified character. /// /// This method does not convert ' or ". - static string ConvertChar(char ch) + static string? ConvertChar(char ch) { switch (ch) { @@ -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 diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index 412885564..a63e88a49 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -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 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 collector.HandleAttributes(module.GetModuleAttributes()); } - public static void CollectNamespaces(IEntity entity, MetadataModule module, HashSet namespaces) + public static void CollectNamespaces(IEntity? entity, MetadataModule module, HashSet 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 } } - 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 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 } } - void CollectNamespacesForMemberReference(IMember member) + void CollectNamespacesForMemberReference(IMember? member) { switch (member) { diff --git a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs index 1a1f0a226..cda185d56 100644 --- a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs @@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Util; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp { /// @@ -75,7 +77,7 @@ namespace ICSharpCode.Decompiler.CSharp /// /// The function containing this sequence point. /// - internal ILFunction Function; + internal ILFunction? Function; public StatePerSequencePoint(AstNode primaryNode) { @@ -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 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 current = outerStates.Pop(); } - void AddToSequencePointRaw(ILFunction function, IEnumerable ranges) + void AddToSequencePointRaw(ILFunction? function, IEnumerable ranges) { current.Intervals.AddRange(ranges); Debug.Assert(current.Function == null || current.Function == function); @@ -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().FirstOrDefault(); + var function = inst.Parent!.Ancestors.OfType().FirstOrDefault(); Debug.Assert(current.Function == null || current.Function == function); current.Function = function; } @@ -570,7 +572,7 @@ namespace ICSharpCode.Decompiler.CSharp newList.Add(hidden); } - List sequencePointCandidates = function.SequencePointCandidates; + List sequencePointCandidates = function.SequencePointCandidates!; int currSPCandidateIndex = 0; for (int i = 0; i < newList.Count - 1; i++) diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 6127a5bf8..e733d1100 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -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; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp { sealed class StatementBuilder : ILVisitor @@ -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 return new IfElseStatement(condition, trueStatement, falseStatement).WithILInstruction(inst); } - internal IEnumerable CreateTypedCaseLabel(long i, IType type, List<(string Key, int Value)> map = null) + internal IEnumerable 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 } 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 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(); + caseLabelMapping = new Dictionary(); var (value, type, strToInt) = exprBuilder.TranslateSwitchValue(inst, false); @@ -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 { case Branch br: // we can only inline the block, if all branches are in the switchContainer. - if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer)) + if (br.TargetContainer == switchContainer && switchContainer!.Descendants.OfType().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 { case Branch br: // we can only inline the block, if all branches are in the switchContainer. - if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer)) + if (br.TargetContainer == switchContainer && switchContainer!.Descendants.OfType().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 } 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 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 } /// Target block that a 'continue;' statement would jump to - Block continueTarget; + Block? continueTarget; /// Number of ContinueStatements that were created for the current continueTarget int continueCount; - /// Maps blocks to cases. - Dictionary caseLabelMapping; + /// Maps blocks to cases. A null value marks the default case. + Dictionary? caseLabelMapping; protected internal override TranslatedStatement VisitBranch(Branch inst) { @@ -359,7 +362,7 @@ namespace ICSharpCode.Decompiler.CSharp } /// Target container that a 'break;' statement would break out of - BlockContainer breakTarget; + BlockContainer? breakTarget; /// Dictionary from BlockContainer to label name for 'goto of_container'; readonly Dictionary endContainerLabels = new Dictionary(); @@ -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 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 } } - Statement TransformToForeach(UsingInstruction inst, Expression resource) + Statement? TransformToForeach(UsingInstruction inst, Expression resource) { if (!settings.ForEachStatement) { @@ -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 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(), decompileRun.UsingScope, foreachVariable); @@ -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 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 // 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 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 /// Otherwise returns the unmodified container. /// /// 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. - 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 /// Returns the call instruction invoking Current's getter. /// Returns the the foreach variable, if a suitable was found. This variable is only assigned once and its assignment is the first statement in . /// for details. - 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 // => 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 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 .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 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 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 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 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 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 { 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; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs index 966bcaff4..72031cccd 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs @@ -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); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 7331e5526..6533709f2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -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; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp.Syntax { /// @@ -38,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class TypeSystemAstBuilder { - readonly CSharpResolver resolver; + readonly CSharpResolver? resolver; #region Constructor /// @@ -479,13 +482,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AstType ConvertTypeHelper(IType genericType, IReadOnlyList 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 localTypeArguments = Empty.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 { 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 } } - 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 } } - 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 }; 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 } } - 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 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 return attr; } - private IEnumerable ConvertAttributes(IEnumerable attributes, string target = null) + private IEnumerable ConvertAttributes(IEnumerable attributes, string? target = null) { if (SortAttributes) - attributes = attributes.OrderBy(a => a, new DelegateComparer(CompareAttribute)); + attributes = attributes.OrderBy(a => a, new DelegateComparer((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 { 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 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 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.Instance, NameLookupMode.Type); + ResolveResult? shortRR = null; + ResolveResult withExtraAttrSuffix = resolver!.LookupSimpleNameOrTypeName(type.Name + "Attribute", EmptyList.Instance, NameLookupMode.Type); if (shortName != null) { - shortRR = resolver.LookupSimpleNameOrTypeName(shortName, EmptyList.Instance, NameLookupMode.Type); + shortRR = resolver!.LookupSimpleNameOrTypeName(shortName, EmptyList.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 } } - 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 /// which is of type int. /// However, the returned expression will always be implicitly convertible to . /// - 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 /// /// Creates an Expression for the given constant value. /// - 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 } 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 } } - 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 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 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 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 (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 // 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 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 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 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 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 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()); return ext; } @@ -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 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 { ct.HasReadOnlySpecifier = true; } - Expression initializer = null; + Expression? initializer = null; if (field.IsConst && this.ShowConstantValues) { try @@ -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 } } - 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 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 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 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 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 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 return new NamespaceDeclaration(ns.FullName); } - AstType GetExplicitInterfaceType(IMember member) + AstType? GetExplicitInterfaceType(IMember member) { if (member.IsExplicitInterfaceImplementation) { diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index ad8d2edd2..36de87f5e 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -805,7 +805,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { foreach (var node in rootNode.Descendants) { - ILVariable ilVar; + ILVariable? ilVar; switch (node) { case IdentifierExpression id: diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs index 6021d0254..de1e44003 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs @@ -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 { 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(SlotKind.Identifier).Name = newName; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index 587429a8b..6f88527b4 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -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) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs index d115ed1c7..8501a7559 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs @@ -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(), innerLambda.Annotation())); query.Clauses.Add(joinClause); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index fd4e72165..15e0031ae 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -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().Any(ie => ie.GetILVariable() == variable) == true) return true; @@ -515,7 +515,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms break; if (!int.TryParse(m.Get("index").Single().Value?.ToString() ?? "", out int index) || index != i) break; - upperBounds[i] = m.Get("variable").Single().GetILVariable(); + upperBounds[i] = m.Get("variable").Single().GetILVariable()!; stmt = stmt.GetNextStatement(); i++; } while (stmt != null && upperBounds != null && i < upperBounds.Length); @@ -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("delegateCombine").Single().Parent.GetSymbol() as IMethod; + var combineMethod = m.Get("delegateCombine").Single().Parent!.GetSymbol() as IMethod; if (combineMethod == null || combineMethod.Name != (isAddAccessor ? "Combine" : "Remove")) return false; return combineMethod.DeclaringType.FullName == "System.Delegate"; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs index a981df05c..85c4d42b3 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs @@ -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 constructorsNotChainedWithThis = []; List allCtors = []; @@ -298,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms foreach (var ctor in members.OfType()) { - 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 // 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 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 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 foreach (var typeDeclaration in node.Descendants.OfType()) { - var currentTypeDefinition = (ITypeDefinition)typeDeclaration.GetSymbol(); + var currentTypeDefinition = (ITypeDefinition)typeDeclaration.GetSymbol()!; TransformDeclaration(currentTypeDefinition, typeDeclaration, typeDeclaration.Members); } } @@ -838,7 +838,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms foreach (var constructorDeclaration in members.OfType()) { - analyzer.MoveConstructorInitializer(constructorDeclaration, (IMethod)constructorDeclaration.GetSymbol()); + analyzer.MoveConstructorInitializer(constructorDeclaration, (IMethod)constructorDeclaration.GetSymbol()!); } analyzer.RemoveImplicitConstructor(); diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index 66d0eab36..efbf1ee69 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -29,6 +29,8 @@ using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; +#nullable enable + 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()) descendant.AddAnnotation(inst); @@ -664,7 +666,7 @@ namespace ICSharpCode.Decompiler.CSharp /// In conditional contexts, remove the bool-cast emitted when converting /// an "implicit operator bool" invocation. /// - public TranslatedExpression UnwrapImplicitBoolConversion(Func typeFilter = null) + public TranslatedExpression UnwrapImplicitBoolConversion(Func? typeFilter = null) { if (!this.Type.IsKnownType(KnownTypeCode.Boolean)) return this; diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs b/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs index 989813ce0..300971814 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs @@ -6,6 +6,8 @@ using System.Linq; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp { [DebuggerDisplay("{Statement}")] diff --git a/ICSharpCode.Decompiler/CSharp/TranslationContext.cs b/ICSharpCode.Decompiler/CSharp/TranslationContext.cs index 6afbbfbb1..f4f910fee 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslationContext.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslationContext.cs @@ -18,6 +18,8 @@ using ICSharpCode.Decompiler.TypeSystem; +#nullable enable + namespace ICSharpCode.Decompiler.CSharp { /// diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index b46b74b0c..2efe84690 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -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)