From 60428191177ce0081b777b351605ceebb4f0cb37 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 18 May 2020 23:41:48 +0200 Subject: [PATCH] Implement Block.CheckInvariant for BlockKind.ArrayInitializer, BlockKind.CollectionInitializer and BlockKind.ObjectInitializer --- .../IL/Instructions/Block.cs | 37 +++++++++++++++++++ ...ransformCollectionAndObjectInitializers.cs | 6 +-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index 5bb1a2dae..bab84c2b4 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL { @@ -131,6 +132,42 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(call.Arguments[0].MatchLdLoc(v)); } break; + case BlockKind.ArrayInitializer: + var final = finalInstruction as LdLoc; + Debug.Assert(final != null && final.Variable.Kind == VariableKind.InitializerTarget); + IType type = null; + Debug.Assert(Instructions[0].MatchStLoc(final.Variable, out var init) && init.MatchNewArr(out type)); + for (int i = 1; i < Instructions.Count; i++) { + Debug.Assert(Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out var t) && type != null && type.Equals(t)); + Debug.Assert(target.MatchLdElema(out t, out ILInstruction array) && type.Equals(t)); + Debug.Assert(array.MatchLdLoc(out ILVariable v) && v == final.Variable); + } + break; + case BlockKind.CollectionInitializer: + case BlockKind.ObjectInitializer: + var final2 = finalInstruction as LdLoc; + Debug.Assert(final2 != null && final2.Variable.Kind == VariableKind.InitializerTarget); + IType type2 = null; + Debug.Assert(Instructions[0].MatchStLoc(final2.Variable, out var init2)); + Debug.Assert(init2 is NewObj || init2 is DefaultValue || (init2 is Block named && named.Kind == BlockKind.CallWithNamedArgs)); + switch (init2) { + case NewObj newObj: + type2 = newObj.Method.DeclaringType; + break; + case DefaultValue defaultValue: + type2 = defaultValue.Type; + break; + case Block callWithNamedArgs when callWithNamedArgs.Kind == BlockKind.CallWithNamedArgs: + type2 = ((CallInstruction)callWithNamedArgs.FinalInstruction).Method.ReturnType; + break; + default: + Debug.Assert(false); + break; + } + for (int i = 1; i < Instructions.Count; i++) { + Debug.Assert(Instructions[i] is StLoc || IL.Transforms.AccessPathElement.GetAccessPath(Instructions[i], type2).Kind != IL.Transforms.AccessPathKind.Invalid); + } + break; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 6fd25b0ca..95c681449 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -260,7 +260,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms public override string ToString() => $"[{Member}, {Indices}]"; public static (AccessPathKind Kind, List Path, List Values, ILVariable Target) GetAccessPath( - ILInstruction instruction, IType rootType, DecompilerSettings settings, + ILInstruction instruction, IType rootType, DecompilerSettings settings = null, CSharpTypeResolveContext resolveContext = null, Dictionary possibleIndexVariables = null) { @@ -282,7 +282,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!CanBeUsedInInitializer(property, resolveContext, kind, path)) goto default; var isGetter = method.Equals(property?.Getter); var indices = call.Arguments.Skip(1).Take(call.Arguments.Count - (isGetter ? 1 : 2)).ToArray(); - if (indices.Length > 0 && !settings.DictionaryInitializers) goto default; + if (indices.Length > 0 && settings?.DictionaryInitializers == false) goto default; if (possibleIndexVariables != null) { // Mark all index variables as used foreach (var index in indices.OfType()) { @@ -373,7 +373,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!"Add".Equals(method.Name, StringComparison.Ordinal) || arguments.Count == 0) return false; if (method.IsExtensionMethod) - return settings.ExtensionMethodsInCollectionInitializers + return settings?.ExtensionMethodsInCollectionInitializers != false && CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall(method, resolveContext, ignoreTypeArguments: true); var targetType = GetReturnTypeFromInstruction(arguments[0]) ?? rootType; if (targetType == null)