Browse Source

Add idiom for System.Type.GetTypeFromHandle(typeof(...).TypeHandle); don't create body for abstract methods.

pull/10/head
Daniel Grunwald 15 years ago
parent
commit
336412fff9
  1. 60
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 18
      ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs
  3. 53
      ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs
  4. 21
      ILSpy/CSharpLanguage.cs

60
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -99,6 +99,21 @@ namespace Decompiler @@ -99,6 +99,21 @@ namespace Decompiler
astCompileUnit.AddChild(node, CompilationUnit.MemberRole);
}
public void AddProperty(PropertyDefinition property)
{
astCompileUnit.AddChild(CreateProperty(property), CompilationUnit.MemberRole);
}
public void AddField(FieldDefinition field)
{
astCompileUnit.AddChild(CreateField(field), CompilationUnit.MemberRole);
}
public void AddEvent(EventDefinition ev)
{
astCompileUnit.AddChild(CreateEvent(ev), CompilationUnit.MemberRole);
}
public TypeDeclaration CreateType(TypeDefinition typeDef)
{
TypeDeclaration astType = new TypeDeclaration();
@ -111,6 +126,7 @@ namespace Decompiler @@ -111,6 +126,7 @@ namespace Decompiler
astType.ClassType = ClassType.Struct;
} else if (typeDef.IsInterface) {
astType.ClassType = ClassType.Interface;
astType.Modifiers &= ~Modifiers.Abstract;
} else {
astType.ClassType = ClassType.Class;
}
@ -143,10 +159,10 @@ namespace Decompiler @@ -143,10 +159,10 @@ namespace Decompiler
public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null)
{
int typeIndex = 0;
return CreateType(type, typeAttributes, ref typeIndex);
return ConvertType(type, typeAttributes, ref typeIndex);
}
static AstType CreateType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex)
static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex)
{
while (type is OptionalModifierType || type is RequiredModifierType) {
type = ((TypeSpecification)type).ElementType;
@ -158,27 +174,27 @@ namespace Decompiler @@ -158,27 +174,27 @@ namespace Decompiler
if (type is Mono.Cecil.ByReferenceType) {
typeIndex++;
// ignore by reference type (cannot be represented in C#)
return CreateType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex);
return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex);
} else if (type is Mono.Cecil.PointerType) {
typeIndex++;
return CreateType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex)
return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex)
.MakePointerType();
} else if (type is Mono.Cecil.ArrayType) {
typeIndex++;
return CreateType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex)
return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex)
.MakeArrayType((type as Mono.Cecil.ArrayType).Rank);
} else if (type is GenericInstanceType) {
GenericInstanceType gType = (GenericInstanceType)type;
AstType baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex);
AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex);
foreach (var typeArgument in gType.GenericArguments) {
typeIndex++;
baseType.AddChild(CreateType(typeArgument, typeAttributes, ref typeIndex), AstType.Roles.TypeArgument);
baseType.AddChild(ConvertType(typeArgument, typeAttributes, ref typeIndex), AstType.Roles.TypeArgument);
}
return baseType;
} else if (type is GenericParameter) {
return new SimpleType(type.Name);
} else if (type.IsNested) {
AstType typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex);
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex);
string namepart = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
return new MemberType { Target = typeRef, MemberName = namepart }.WithAnnotation(type);
} else {
@ -309,7 +325,7 @@ namespace Decompiler @@ -309,7 +325,7 @@ namespace Decompiler
modifiers |= Modifiers.Abstract;
else if (methodDef.IsFinal)
modifiers |= Modifiers.Sealed;
else if (methodDef.IsVirtual)
else if (methodDef.IsVirtual && methodDef.IsNewSlot)
modifiers |= Modifiers.Virtual;
return modifiers;
}
@ -352,9 +368,11 @@ namespace Decompiler @@ -352,9 +368,11 @@ namespace Decompiler
MethodDeclaration astMethod = new MethodDeclaration();
astMethod.Name = methodDef.Name;
astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType);
astMethod.Modifiers = ConvertModifiers(methodDef);
astMethod.Parameters = MakeParameters(methodDef.Parameters);
astMethod.Body = AstMethodBodyBuilder.CreateMetodBody(methodDef);
if (!methodDef.DeclaringType.IsInterface) {
astMethod.Modifiers = ConvertModifiers(methodDef);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef);
}
return astMethod;
}
@ -363,7 +381,7 @@ namespace Decompiler @@ -363,7 +381,7 @@ namespace Decompiler
ConstructorDeclaration astMethod = new ConstructorDeclaration();
astMethod.Modifiers = ConvertModifiers(methodDef);
astMethod.Parameters = MakeParameters(methodDef.Parameters);
astMethod.Body = AstMethodBodyBuilder.CreateMetodBody(methodDef);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef);
return astMethod;
}
@ -375,23 +393,33 @@ namespace Decompiler @@ -375,23 +393,33 @@ namespace Decompiler
astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
if (propDef.GetMethod != null) {
astProp.Getter = new Accessor {
Body = AstMethodBodyBuilder.CreateMetodBody(propDef.GetMethod)
Body = AstMethodBodyBuilder.CreateMethodBody(propDef.GetMethod)
};
}
if (propDef.SetMethod != null) {
astProp.Setter = new Accessor {
Body = AstMethodBodyBuilder.CreateMetodBody(propDef.SetMethod)
Body = AstMethodBodyBuilder.CreateMethodBody(propDef.SetMethod)
};
}
return astProp;
}
EventDeclaration CreateEvent(EventDefinition eventDef)
CustomEventDeclaration CreateEvent(EventDefinition eventDef)
{
EventDeclaration astEvent = new EventDeclaration();
CustomEventDeclaration astEvent = new CustomEventDeclaration();
astEvent.Name = eventDef.Name;
astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
if (eventDef.AddMethod != null) {
astEvent.AddAccessor = new Accessor {
Body = AstMethodBodyBuilder.CreateMethodBody(eventDef.AddMethod)
};
}
if (eventDef.RemoveMethod != null) {
astEvent.RemoveAccessor = new Accessor {
Body = AstMethodBodyBuilder.CreateMethodBody(eventDef.RemoveMethod)
};
}
return astEvent;
}

18
ICSharpCode.Decompiler/Ast/AstMetodBodyBuilder.cs

@ -17,7 +17,7 @@ namespace Decompiler @@ -17,7 +17,7 @@ namespace Decompiler
static Dictionary<string, Cecil.TypeReference> localVarTypes = new Dictionary<string, Cecil.TypeReference>();
static Dictionary<string, bool> localVarDefined = new Dictionary<string, bool>();
public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
public static BlockStatement CreateMethodBody(MethodDefinition methodDef)
{
AstMethodBodyBuilder builder = new AstMethodBodyBuilder();
builder.methodDef = methodDef;
@ -53,7 +53,7 @@ namespace Decompiler @@ -53,7 +53,7 @@ namespace Decompiler
public BlockStatement CreateMethodBody()
{
if (methodDef.Body == null) return new Ast.BlockStatement();
if (methodDef.Body == null) return null;
List<ILNode> body = new ILAstBuilder().Build(methodDef, true);
@ -122,7 +122,7 @@ namespace Decompiler @@ -122,7 +122,7 @@ namespace Decompiler
IEnumerable<Statement> TransformNode(Node node)
{
if (Options.NodeComments) {
yield return new CommentStatement("// " + node.Description);
yield return new CommentStatement(node.Description);
}
yield return new Ast.LabelStatement { Label = node.Label };
@ -547,7 +547,7 @@ namespace Decompiler @@ -547,7 +547,7 @@ namespace Decompiler
// TODO: Constructors are ignored
if (cecilMethod.Name == ".ctor") {
return new CommentStatement("// Constructor");
return new CommentStatement("Constructor");
}
// TODO: Hack, detect properties properly
@ -602,14 +602,16 @@ namespace Decompiler @@ -602,14 +602,16 @@ namespace Decompiler
case Code.Ldc_R8:
return new Ast.PrimitiveExpression(operand);
case Code.Ldfld:
return arg1.Member(((FieldReference) operand).Name);
return arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand);
case Code.Ldsfld:
return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType).Member(((FieldReference)operand).Name);
return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
.Member(((FieldReference)operand).Name).WithAnnotation(operand);
case Code.Stfld:
return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name), arg2);
return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand), arg2);
case Code.Stsfld:
return new AssignmentExpression(
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType).Member(((FieldReference)operand).Name),
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
.Member(((FieldReference)operand).Name).WithAnnotation(operand),
arg2);
case Code.Ldflda:
case Code.Ldsflda: throw new NotImplementedException();

53
ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs

@ -14,36 +14,49 @@ namespace Decompiler.Transforms.Ast @@ -14,36 +14,49 @@ namespace Decompiler.Transforms.Ast
base.VisitInvocationExpression(invocationExpression, data);
MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
if (methodRef == null)
return null;
var arguments = invocationExpression.Arguments.ToArray();
// Reduce "String.Concat(a, b)" to "a + b"
if (methodRef != null && methodRef.FullName == "System.String.Concat"
&& invocationExpression.Arguments.Count() >= 2)
if (methodRef != null && methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2)
{
var arguments = invocationExpression.Arguments.ToArray();
invocationExpression.Arguments = null; // detach arguments from invocationExpression
Expression expr = arguments[0];
for (int i = 1; i < arguments.Length; i++) {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
}
invocationExpression.ReplaceWith(expr);
return null;
}
if (methodRef != null) {
BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name);
if (bop != null && invocationExpression.Arguments.Count() == 2) {
var arguments = invocationExpression.Arguments.ToArray();
invocationExpression.Arguments = null; // detach arguments from invocationExpression
invocationExpression.ReplaceWith(
new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef)
);
}
UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name);
if (uop != null && invocationExpression.Arguments.Count() == 1) {
var arg = invocationExpression.Arguments.Single();
arg.Remove(); // detach argument
invocationExpression.ReplaceWith(
new UnaryOperatorExpression(uop.Value, arg).WithAnnotation(methodRef)
);
}
switch (methodRef.FullName) {
case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)":
if (arguments.Length == 1) {
MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
if (mre != null && mre.Target is TypeOfExpression && mre.MemberName == "TypeHandle") {
invocationExpression.ReplaceWith(mre.Target);
return null;
}
}
break;
}
BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name);
if (bop != null && arguments.Length == 2) {
invocationExpression.Arguments = null; // detach arguments from invocationExpression
invocationExpression.ReplaceWith(
new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef)
);
return null;
}
UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name);
if (uop != null && arguments.Length == 1) {
arguments[0].Remove(); // detach argument
invocationExpression.ReplaceWith(
new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef)
);
return null;
}
return null;

21
ILSpy/CSharpLanguage.cs

@ -43,6 +43,27 @@ namespace ICSharpCode.ILSpy @@ -43,6 +43,27 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.GenerateCode(output);
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddProperty(property);
codeDomBuilder.GenerateCode(output);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddField(field);
codeDomBuilder.GenerateCode(output);
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddEvent(ev);
codeDomBuilder.GenerateCode(output);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = new AstBuilder();

Loading…
Cancel
Save