Browse Source

Add support for anonymous types.

pull/124/head
Daniel Grunwald 14 years ago
parent
commit
be7ae61b8f
  1. 5
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 23
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 2
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  4. 30
      ICSharpCode.Decompiler/CecilExtensions.cs

5
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Ast
} else if (type != null && type.IsCompilerGenerated()) {
if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
return true;
if (type.Name.StartsWith("<>", StringComparison.Ordinal) && type.Name.Contains("AnonymousType"))
if (type.IsAnonymousType())
return true;
}
FieldDefinition field = member as FieldDefinition;
@ -885,11 +885,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -885,11 +885,12 @@ namespace ICSharpCode.Decompiler.Ast
return astField;
}
public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol)
public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol, bool isLambda = false)
{
foreach(ParameterDefinition paramDef in paramCol) {
ParameterDeclaration astParam = new ParameterDeclaration();
astParam.AddAnnotation(paramDef);
if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType()))
astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
astParam.Name = paramDef.Name;

23
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -91,7 +91,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -91,7 +91,12 @@ namespace ICSharpCode.Decompiler.Ast
Statement insertionPoint = astBlock.Statements.FirstOrDefault();
foreach (ILVariable v in localVariablesToDefine) {
var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name);
AstType type;
if (v.Type.ContainsAnonymousType())
type = new SimpleType("var");
else
type = AstBuilder.ConvertType(v.Type);
var newVarDecl = new VariableDeclarationStatement(type, v.Name);
astBlock.Statements.InsertBefore(insertionPoint, newVarDecl);
}
@ -603,6 +608,20 @@ namespace ICSharpCode.Decompiler.Ast @@ -603,6 +608,20 @@ namespace ICSharpCode.Decompiler.Ast
}
}
var oce = new Ast.ObjectCreateExpression();
if (declaringType.IsAnonymousType()) {
MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (methodDef != null) {
oce.Initializer = new ArrayInitializerExpression();
for (int i = 0; i < args.Count; i++) {
oce.Initializer.Elements.Add(
new NamedArgumentExpression {
Identifier = ctor.Parameters[i].Name,
Expression = args[i]
});
}
}
return oce;
}
oce.Type = AstBuilder.ConvertType(declaringType);
oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand);
@ -911,6 +930,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -911,6 +930,8 @@ namespace ICSharpCode.Decompiler.Ast
GenericInstanceMethod g = cecilMethod as GenericInstanceMethod;
if (g == null)
return null;
if (g.GenericArguments.Any(ta => ta.ContainsAnonymousType()))
return null;
return g.GenericArguments.Select(t => AstBuilder.ConvertType(t));
}

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

@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
// Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters, isLambda: true));
ame.HasParameterList = true;
// rename variables so that they don't conflict with the parameters:

30
ICSharpCode.Decompiler/CecilExtensions.cs

@ -204,5 +204,35 @@ namespace ICSharpCode.Decompiler @@ -204,5 +204,35 @@ namespace ICSharpCode.Decompiler
return true;
return IsCompilerGeneratedOrIsInCompilerGeneratedClass(member.DeclaringType);
}
public static bool IsAnonymousType(this TypeReference type)
{
if (type == null)
return false;
if (string.IsNullOrEmpty(type.Namespace) && type.Name.StartsWith("<>", StringComparison.Ordinal) && type.Name.Contains("AnonymousType")) {
TypeDefinition td = type.Resolve();
return td != null && td.IsCompilerGenerated();
}
return false;
}
public static bool ContainsAnonymousType(this TypeReference type)
{
GenericInstanceType git = type as GenericInstanceType;
if (git != null) {
if (IsAnonymousType(git))
return true;
for (int i = 0; i < git.GenericArguments.Count; i++) {
if (git.GenericArguments[i].ContainsAnonymousType())
return true;
}
return false;
}
TypeSpecification typeSpec = type as TypeSpecification;
if (typeSpec != null)
return typeSpec.ElementType.ContainsAnonymousType();
else
return false;
}
}
}

Loading…
Cancel
Save