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

27
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -876,9 +876,14 @@ namespace ICSharpCode.Decompiler.CSharp
var context = new SimpleTypeResolveContext(method); var context = new SimpleTypeResolveContext(method);
StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(context), context, method); StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(context), context, method);
var body = builder.ConvertAsBlock(function.Body); var body = builder.ConvertAsBlock(function.Body);
bool isLambda = false; 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); isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
} }
// Remove the parameter list from an AnonymousMethodExpression if the original method had no names, // Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
@ -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; Expression replacement;
if (isLambda) { if (isLambda) {
LambdaExpression lambda = new LambdaExpression(); LambdaExpression lambda = new LambdaExpression();
lambda.CopyAnnotationsFrom(ame); lambda.CopyAnnotationsFrom(ame);
ame.Parameters.MoveTo(lambda.Parameters); ame.Parameters.MoveTo(lambda.Parameters);
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression; if (isMultiLineLambda) {
returnExpr.Remove(); lambda.Body = body;
lambda.Body = returnExpr; } else {
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
returnExpr.Remove();
lambda.Body = returnExpr;
}
replacement = lambda; replacement = lambda;
} else { } else {
ame.Body = body; ame.Body = body;
@ -1062,7 +1066,8 @@ namespace ICSharpCode.Decompiler.CSharp
methodName = method.ImplementedInterfaceMembers[0].Name; methodName = method.ImplementedInterfaceMembers[0].Name;
} }
var mre = new MemberReferenceExpression(targetExpr, methodName); 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); var argumentExpressions = arguments.Select(arg => arg.Expression);
expr = new InvocationExpression(mre, argumentExpressions); expr = new InvocationExpression(mre, argumentExpressions);
} }

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

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

7
ICSharpCode.Decompiler/NRExtensions.cs

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

Loading…
Cancel
Save