Browse Source

Fix tests `LocalFunctions.NestedCapture1`

pull/1797/head
SilverFox 6 years ago
parent
commit
33f96fd888
  1. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  2. 3
      ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
  3. 14
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

8
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -502,11 +502,15 @@ namespace LocalFunctions
{ {
return Method1_1; return Method1_1;
void Method1_1(object containerBuilder) => void Method1_1(object containerBuilder)
{
Method1_2(containerBuilder); Method1_2(containerBuilder);
}
void Method1_2(object containerBuilder) => void Method1_2(object containerBuilder)
{
action(containerBuilder); action(containerBuilder);
}
} }
} }

3
ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs

@ -379,8 +379,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
if (closureVar.Kind == VariableKind.NamedArgument) if (closureVar.Kind == VariableKind.NamedArgument)
return false; return false;
ITypeDefinition potentialDisplayClass = UnwrapByRef(closureVar.Type).GetDefinition(); if (!TransformDisplayClassUsage.IsClosure(context, closureVar, null, out _, out _))
if (!TransformDisplayClassUsage.IsPotentialClosure(context, potentialDisplayClass))
return false; return false;
if (i - firstArgumentIndex >= 0) { if (i - firstArgumentIndex >= 0) {
Debug.Assert(i - firstArgumentIndex < function.Method.Parameters.Count && IsClosureParameter(function.Method.Parameters[i - firstArgumentIndex], resolveContext)); Debug.Assert(i - firstArgumentIndex < function.Method.Parameters.Count && IsClosureParameter(function.Method.Parameters[i - firstArgumentIndex], resolveContext));

14
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
foreach (var v in f.Variables.ToArray()) { foreach (var v in f.Variables.ToArray()) {
if (context.Settings.YieldReturn && HandleMonoStateMachine(function, v, decompilationContext, f)) if (context.Settings.YieldReturn && HandleMonoStateMachine(function, v, decompilationContext, f))
continue; continue;
if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(v, out ITypeDefinition closureType, out var inst)) { if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(context, v, instructionsToRemove, out ITypeDefinition closureType, out var inst)) {
AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false); AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false);
} }
if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) { if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) {
@ -110,30 +110,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
bool IsClosure(ILVariable variable, out ITypeDefinition closureType, out ILInstruction initializer) internal static bool IsClosure(ILTransformContext context, ILVariable variable, List<ILInstruction> instructionsToRemove, out ITypeDefinition closureType, out ILInstruction initializer)
{ {
closureType = null; closureType = null;
initializer = null; initializer = null;
if (variable.IsSingleDefinition && variable.StoreInstructions.SingleOrDefault() is StLoc inst) { if (variable.IsSingleDefinition && variable.StoreInstructions.SingleOrDefault() is StLoc inst) {
initializer = inst; initializer = inst;
if (IsClosureInit(inst, out closureType)) { if (IsClosureInit(context, inst, out closureType)) {
instructionsToRemove.Add(inst); instructionsToRemove?.Add(inst);
return true; return true;
} }
} }
closureType = variable.Type.GetDefinition(); closureType = variable.Type.GetDefinition();
if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct && variable.HasInitialValue && IsPotentialClosure(this.context, closureType)) { if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct && variable.HasInitialValue && IsPotentialClosure(context, closureType)) {
initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
return true; return true;
} }
return false; return false;
} }
bool IsClosureInit(StLoc inst, out ITypeDefinition closureType) static bool IsClosureInit(ILTransformContext context, StLoc inst, out ITypeDefinition closureType)
{ {
if (inst.Value is NewObj newObj) { if (inst.Value is NewObj newObj) {
closureType = newObj.Method.DeclaringTypeDefinition; closureType = newObj.Method.DeclaringTypeDefinition;
return closureType != null && IsPotentialClosure(this.context, newObj); return closureType != null && IsPotentialClosure(context, newObj);
} }
closureType = null; closureType = null;
return false; return false;

Loading…
Cancel
Save