Browse Source

#2390: Add support for generic object initializers.

pull/2408/head
Siegfried Pammer 5 years ago
parent
commit
d54016ce8f
  1. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs
  2. 7
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 10
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  4. 4
      ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs

@ -226,6 +226,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
public Item I; public Item I;
} }
#endif #endif
public interface IData
{
int Property { get; set; }
}
#endregion #endregion
#region Field initializer tests #region Field initializer tests
@ -1036,6 +1041,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
} }
} }
#endif #endif
private TData GenericObjectInitializer<TData>() where TData : IData, new()
{
return new TData {
Property = 42
};
}
#endregion #endregion
#region Collection initializer #region Collection initializer

7
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -3161,6 +3161,13 @@ namespace ICSharpCode.Decompiler.CSharp
expr = TranslateCallWithNamedArgs(callWithNamedArgs); expr = TranslateCallWithNamedArgs(callWithNamedArgs);
initObjRR = new InitializedObjectResolveResult(expr.Type); initObjRR = new InitializedObjectResolveResult(expr.Type);
break; break;
case Call c when c.Method.FullNameIs("System.Activator", "CreateInstance") && c.Method.TypeArguments.Count == 1:
IType type = c.Method.TypeArguments[0];
initObjRR = new InitializedObjectResolveResult(type);
expr = new ObjectCreateExpression(ConvertType(type))
.WithILInstruction(c)
.WithRR(new TypeResolveResult(type));
break;
default: default:
throw new ArgumentException("given Block is invalid!"); throw new ArgumentException("given Block is invalid!");
} }

10
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -151,6 +151,7 @@ namespace ICSharpCode.Decompiler.IL
break; break;
case BlockKind.CollectionInitializer: case BlockKind.CollectionInitializer:
case BlockKind.ObjectInitializer: case BlockKind.ObjectInitializer:
case BlockKind.WithInitializer:
var final2 = finalInstruction as LdLoc; var final2 = finalInstruction as LdLoc;
Debug.Assert(final2 != null); Debug.Assert(final2 != null);
var initVar2 = final2.Variable; var initVar2 = final2.Variable;
@ -161,6 +162,7 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(init2 is NewObj Debug.Assert(init2 is NewObj
|| init2 is DefaultValue || init2 is DefaultValue
|| (init2 is CallInstruction ci && TransformCollectionAndObjectInitializers.IsRecordCloneMethodCall(ci)) || (init2 is CallInstruction ci && TransformCollectionAndObjectInitializers.IsRecordCloneMethodCall(ci))
|| (init2 is CallInstruction c && c.Method.FullNameIs("System.Activator", "CreateInstance") && c.Method.TypeArguments.Count == 1)
|| (init2 is Block named && named.Kind == BlockKind.CallWithNamedArgs)); || (init2 is Block named && named.Kind == BlockKind.CallWithNamedArgs));
switch (init2) switch (init2)
{ {
@ -173,13 +175,19 @@ namespace ICSharpCode.Decompiler.IL
case Block callWithNamedArgs when callWithNamedArgs.Kind == BlockKind.CallWithNamedArgs: case Block callWithNamedArgs when callWithNamedArgs.Kind == BlockKind.CallWithNamedArgs:
type2 = ((CallInstruction)callWithNamedArgs.FinalInstruction).Method.ReturnType; type2 = ((CallInstruction)callWithNamedArgs.FinalInstruction).Method.ReturnType;
break; break;
case CallInstruction ci2 when TransformCollectionAndObjectInitializers.IsRecordCloneMethodCall(ci2):
type2 = ci2.Method.DeclaringType;
break;
case Call c2 when c2.Method.FullNameIs("System.Activator", "CreateInstance") && c2.Method.TypeArguments.Count == 1:
type2 = c2.Method.TypeArguments[0];
break;
default: default:
Debug.Assert(false); Debug.Assert(false);
break; break;
} }
for (int i = 1; i < Instructions.Count; i++) for (int i = 1; i < Instructions.Count; i++)
{ {
Debug.Assert(Instructions[i] is StLoc || AccessPathElement.GetAccessPath(Instructions[i], type2).Kind != IL.Transforms.AccessPathKind.Invalid); Debug.Assert(Instructions[i] is StLoc || AccessPathElement.GetAccessPath(Instructions[i], type2).Kind != AccessPathKind.Invalid);
} }
break; break;
case BlockKind.DeconstructionConversions: case BlockKind.DeconstructionConversions:

4
ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs

@ -95,6 +95,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
instType = defaultVal.Type; instType = defaultVal.Type;
break; break;
case Call c when c.Method.FullNameIs("System.Activator", "CreateInstance") && c.Method.TypeArguments.Count == 1:
instType = c.Method.TypeArguments[0];
blockKind = BlockKind.ObjectInitializer;
break;
case CallInstruction ci when context.Settings.WithExpressions && IsRecordCloneMethodCall(ci): case CallInstruction ci when context.Settings.WithExpressions && IsRecordCloneMethodCall(ci):
instType = ci.Method.DeclaringType; instType = ci.Method.DeclaringType;
blockKind = BlockKind.WithInitializer; blockKind = BlockKind.WithInitializer;

Loading…
Cancel
Save