Browse Source

Relax rules for object and collection initializer detection to properly decompile query expressions.

pull/1108/head
Siegfried Pammer 7 years ago
parent
commit
2d427cf534
  1. 26
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs
  2. 1347
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.il
  3. 1243
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.opt.il
  4. 1534
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.opt.roslyn.il
  5. 1556
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.roslyn.il
  6. 10
      ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs

26
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs

@ -19,11 +19,24 @@ @@ -19,11 +19,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class QueryExpressions
{
public class HbmParam
{
public string Name {
get;
set;
}
public string[] Text {
get;
set;
}
}
public class Customer
{
public int CustomerID;
@ -127,6 +140,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -127,6 +140,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
select b + c;
}
public object HibernateApplyGeneratorQuery()
{
return (from pi in customers.GetType().GetProperties()
let pname = pi.Name
let pvalue = pi.GetValue(customers, null)
select new HbmParam {
Name = pname,
Text = new string[1] {
(pvalue == null) ? "null" : pvalue.ToString()
}
}).ToArray();
}
public object Join()
{
return from c in customers

1347
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.il

File diff suppressed because it is too large Load Diff

1243
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.opt.il

File diff suppressed because it is too large Load Diff

1534
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.opt.roslyn.il

File diff suppressed because it is too large Load Diff

1556
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.roslyn.il

File diff suppressed because it is too large Load Diff

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

@ -50,11 +50,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -50,11 +50,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
IType instType;
switch (initInst) {
case NewObj newObjInst:
if (newObjInst.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor) {
if (newObjInst.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor && !context.Function.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) {
// on statement level (no other expressions on IL stack),
// prefer to keep local variables (but not stack slots),
// unless we are in a constructor (where inlining object initializers might be critical
// for the base ctor call)
// for the base ctor call) or a compiler-generated delegate method, which might be used in a query expression.
return false;
}
// Do not try to transform display class usages or delegate construction.
@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switch (body.Instructions[i + pos]) {
case CallInstruction call:
if (!(call is CallVirt || call is Call)) continue;
var newCall = (CallInstruction)call.Clone();
var newCall = call;
var newTarget = newCall.Arguments[0];
foreach (var load in newTarget.Descendants.OfType<IInstructionWithVariableOperand>())
if ((load is LdLoc || load is LdLoca) && load.Variable == v)
@ -127,14 +127,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -127,14 +127,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
initializerBlock.Instructions.Add(newCall);
break;
case StObj stObj:
var newStObj = (StObj)stObj.Clone();
var newStObj = stObj;
foreach (var load in newStObj.Target.Descendants.OfType<IInstructionWithVariableOperand>())
if ((load is LdLoc || load is LdLoca) && load.Variable == v)
load.Variable = finalSlot;
initializerBlock.Instructions.Add(newStObj);
break;
case StLoc stLoc:
var newStLoc = (StLoc)stLoc.Clone();
var newStLoc = stLoc;
initializerBlock.Instructions.Add(newStLoc);
break;
}

Loading…
Cancel
Save