Browse Source

Hide compiler-generated types for anonymous types and closures

pull/728/merge
Siegfried Pammer 9 years ago
parent
commit
907aa62c62
  1. 23
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 27
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  4. 7
      ICSharpCode.Decompiler/NRExtensions.cs

23
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -132,8 +132,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -132,8 +132,8 @@ namespace ICSharpCode.Decompiler.CSharp
TypeDefinition type = member as TypeDefinition;
if (type != null) {
if (type.DeclaringType != null) {
// if (settings.AnonymousMethods && IsClosureType(type))
// return true;
if (settings.AnonymousMethods && IsClosureType(type))
return true;
// if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
// return true;
// if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type))
@ -141,8 +141,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -141,8 +141,8 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (type.IsCompilerGenerated()) {
// if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
// return true;
// if (type.IsAnonymousType())
// return true;
if (type.IsAnonymousType())
return true;
}
}
@ -188,7 +188,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -188,7 +188,11 @@ namespace ICSharpCode.Decompiler.CSharp
static bool IsClosureType(TypeDefinition type)
{
return type.HasGeneratedName() && type.IsCompilerGenerated() && (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey"));
if (!type.HasGeneratedName() || !type.IsCompilerGenerated())
return false;
if (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey"))
return true;
return type.BaseType.FullName == "System.Object" && !type.HasInterfaces;
}
#endregion
@ -501,9 +505,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -501,9 +505,12 @@ namespace ICSharpCode.Decompiler.CSharp
return entityDecl;
}
foreach (var type in typeDef.NestedTypes) {
var nestedType = DoDecompile(type, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(nestedType);
typeDecl.Members.Add(nestedType);
var cecilType = typeSystem.GetCecil(type);
if (cecilType != null && !MemberIsHidden(cecilType, settings)) {
var nestedType = DoDecompile(type, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(nestedType);
typeDecl.Members.Add(nestedType);
}
}
foreach (var field in typeDef.Fields) {
var fieldDef = typeSystem.GetCecil(field) as FieldDefinition;

27
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -876,9 +876,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -876,9 +876,14 @@ namespace ICSharpCode.Decompiler.CSharp
var context = new SimpleTypeResolveContext(method);
StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(context), context, method);
var body = builder.ConvertAsBlock(function.Body);
bool isLambda = false;
if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
bool isMultiLineLambda = false;
// if there is an anonymous type involved, we are forced to use a lambda expression.
if (ame.Parameters.Any(p => p.Type.IsNull)) {
isLambda = true;
isMultiLineLambda = body.Statements.Count > 1;
} else if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
}
// Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
@ -895,19 +900,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -895,19 +900,18 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
// Replace all occurrences of 'this' in the method body with the delegate's target:
foreach (AstNode node in body.Descendants) {
if (node is ThisReferenceExpression)
node.ReplaceWith(target.Expression.Clone());
}
Expression replacement;
if (isLambda) {
LambdaExpression lambda = new LambdaExpression();
lambda.CopyAnnotationsFrom(ame);
ame.Parameters.MoveTo(lambda.Parameters);
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
returnExpr.Remove();
lambda.Body = returnExpr;
if (isMultiLineLambda) {
lambda.Body = body;
} else {
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
returnExpr.Remove();
lambda.Body = returnExpr;
}
replacement = lambda;
} else {
ame.Body = body;
@ -1062,7 +1066,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1062,7 +1066,8 @@ namespace ICSharpCode.Decompiler.CSharp
methodName = method.ImplementedInterfaceMembers[0].Name;
}
var mre = new MemberReferenceExpression(targetExpr, methodName);
mre.TypeArguments.AddRange(method.TypeArguments.Select(a => ConvertType(a)));
if (!method.TypeArguments.Any(t => t.ContainsAnonymousType()))
mre.TypeArguments.AddRange(method.TypeArguments.Select(a => ConvertType(a)));
var argumentExpressions = arguments.Select(arg => arg.Expression);
expr = new InvocationExpression(mre, argumentExpressions);
}

2
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -121,7 +121,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -121,7 +121,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
if (method == null || !(method.HasGeneratedName() || method.Name.Contains("$")))
return false;
if (!(method.IsCompilerGenerated() || IsPotentialClosure(decompiledTypeDefinition, method.DeclaringTypeDefinition)))
if (!(method.IsCompilerGeneratedOrIsInCompilerGeneratedClass() || IsPotentialClosure(decompiledTypeDefinition, method.DeclaringTypeDefinition)))
return false;
return true;
}

7
ICSharpCode.Decompiler/NRExtensions.cs

@ -99,6 +99,13 @@ namespace ICSharpCode.Decompiler @@ -99,6 +99,13 @@ namespace ICSharpCode.Decompiler
ContainsAnonType = true;
return base.VisitOtherType(type);
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (IsAnonymousType(type))
ContainsAnonType = true;
return base.VisitTypeDefinition(type);
}
}
}
}

Loading…
Cancel
Save