Skip to content

Commit

Permalink
Merge branch 'WithNUnit' of git://github.com/arturek/ILSpy
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrunwald committed Mar 2, 2011
2 parents 1fecab6 + f25904a commit b16ca10
Show file tree
Hide file tree
Showing 22 changed files with 1,165 additions and 103 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -2,4 +2,5 @@ bin/
obj/ obj/


/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs /ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
/ILSpy/Properties/AssemblyInfo.cs /ILSpy/Properties/AssemblyInfo.cs
*.suo
177 changes: 167 additions & 10 deletions ICSharpCode.Decompiler/Ast/AstBuilder.cs
Expand Up @@ -6,8 +6,10 @@
using Decompiler.Transforms; using Decompiler.Transforms;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Ast = ICSharpCode.NRefactory.CSharp;
using ClassType = ICSharpCode.NRefactory.TypeSystem.ClassType; using ClassType = ICSharpCode.NRefactory.TypeSystem.ClassType;
using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier; using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier;


Expand Down Expand Up @@ -62,21 +64,25 @@ public void GenerateCode(ITextOutput output, Predicate<IAstTransform> transformA
astCompileUnit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null); astCompileUnit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null);
} }


public void AddAssembly(AssemblyDefinition assemblyDefinition) public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
{ {
astCompileUnit.AddChild( astCompileUnit.AddChild(
new UsingDeclaration { new UsingDeclaration {
Import = new SimpleType("System") Import = new SimpleType("System")
}, CompilationUnit.MemberRole); }, CompilationUnit.MemberRole);


foreach(TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { ConvertCustomAtributes(astCompileUnit, assemblyDefinition, AttributeTarget.Assembly);
// Skip nested types - they will be added by the parent type
if (typeDef.DeclaringType != null) continue; if(!onlyAssemblyLevel)
// Skip the <Module> class foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types)
if (typeDef.Name == "<Module>") continue; {

// Skip nested types - they will be added by the parent type
AddType(typeDef); if (typeDef.DeclaringType != null) continue;
} // Skip the <Module> class
if (typeDef.Name == "<Module>") continue;

AddType(typeDef);
}
} }


NamespaceDeclaration GetCodeNamespace(string name) NamespaceDeclaration GetCodeNamespace(string name)
Expand Down Expand Up @@ -159,13 +165,20 @@ public TypeDeclaration CreateType(TypeDefinition typeDef)




if (typeDef.IsEnum) { if (typeDef.IsEnum) {
long expectedEnumMemberValue = 0;
bool forcePrintingInitializers = IsFlagsEnum(typeDef);
foreach (FieldDefinition field in typeDef.Fields) { foreach (FieldDefinition field in typeDef.Fields) {
if (field.IsRuntimeSpecialName) { if (field.IsRuntimeSpecialName) {
// the value__ field // the value__ field
astType.AddChild(ConvertType(field.FieldType), TypeDeclaration.BaseTypeRole); astType.AddChild(ConvertType(field.FieldType), TypeDeclaration.BaseTypeRole);
} else { } else {
EnumMemberDeclaration enumMember = new EnumMemberDeclaration(); EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
enumMember.Name = CleanName(field.Name); enumMember.Name = CleanName(field.Name);
long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) {
enumMember.AddChild(new PrimitiveExpression(field.Constant), EnumMemberDeclaration.InitializerRole);
}
expectedEnumMemberValue = memberValue + 1;
astType.AddChild(enumMember, TypeDeclaration.MemberRole); astType.AddChild(enumMember, TypeDeclaration.MemberRole);
} }
} }
Expand All @@ -180,9 +193,15 @@ public TypeDeclaration CreateType(TypeDefinition typeDef)


AddTypeMembers(astType, typeDef); AddTypeMembers(astType, typeDef);
} }


ConvertCustomAtributes(astType, typeDef);
return astType; return astType;
} }

public void Transform(IAstTransform transform)
{
transform.Run(astCompileUnit);
}


string CleanName(string name) string CleanName(string name)
{ {
Expand Down Expand Up @@ -469,6 +488,8 @@ MethodDeclaration CreateMethod(MethodDefinition methodDef)
astMethod.Modifiers = ConvertModifiers(methodDef); astMethod.Modifiers = ConvertModifiers(methodDef);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context); astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
} }
ConvertCustomAtributes(astMethod, methodDef);
ConvertCustomAtributes(astMethod, methodDef.MethodReturnType, AttributeTarget.Return);
return astMethod; return astMethod;
} }


Expand Down Expand Up @@ -513,12 +534,18 @@ PropertyDeclaration CreateProperty(PropertyDefinition propDef)
astProp.Getter = new Accessor { astProp.Getter = new Accessor {
Body = AstMethodBodyBuilder.CreateMethodBody(propDef.GetMethod, context) Body = AstMethodBodyBuilder.CreateMethodBody(propDef.GetMethod, context)
}.WithAnnotation(propDef.GetMethod); }.WithAnnotation(propDef.GetMethod);
ConvertCustomAtributes(astProp.Getter, propDef.GetMethod);
ConvertCustomAtributes(astProp.Getter, propDef.GetMethod.MethodReturnType, AttributeTarget.Return);
} }
if (propDef.SetMethod != null) { if (propDef.SetMethod != null) {
astProp.Setter = new Accessor { astProp.Setter = new Accessor {
Body = AstMethodBodyBuilder.CreateMethodBody(propDef.SetMethod, context) Body = AstMethodBodyBuilder.CreateMethodBody(propDef.SetMethod, context)
}.WithAnnotation(propDef.SetMethod); }.WithAnnotation(propDef.SetMethod);
ConvertCustomAtributes(astProp.Setter, propDef.SetMethod);
ConvertCustomAtributes(astProp.Setter, propDef.SetMethod.MethodReturnType, AttributeTarget.Return);
ConvertCustomAtributes(astProp.Setter, propDef.SetMethod.Parameters.Last(), AttributeTarget.Param);
} }
ConvertCustomAtributes(astProp, propDef);
return astProp; return astProp;
} }


Expand Down Expand Up @@ -556,6 +583,7 @@ FieldDeclaration CreateField(FieldDefinition fieldDef)
else else
initializer.Initializer = new PrimitiveExpression(fieldDef.Constant); initializer.Initializer = new PrimitiveExpression(fieldDef.Constant);
} }
ConvertCustomAtributes(astField, fieldDef);
return astField; return astField;
} }


Expand All @@ -571,8 +599,137 @@ public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<Param
} }
// TODO: params, this // TODO: params, this


ConvertCustomAtributes(astParam, paramDef);
yield return astParam; yield return astParam;
} }
} }

static void ConvertCustomAtributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, AttributeTarget target = AttributeTarget.None)
{
if (customAttributeProvider.HasCustomAttributes)
{
var section = new AttributeSection();
section.AttributeTarget = target;
foreach (var customAttribute in customAttributeProvider.CustomAttributes)
{
ICSharpCode.NRefactory.CSharp.Attribute attribute = new ICSharpCode.NRefactory.CSharp.Attribute();
attribute.Type = ConvertType(customAttribute.AttributeType);
section.Attributes.Add(attribute);

if(customAttribute.HasConstructorArguments)
foreach (var parameter in customAttribute.ConstructorArguments)
{
Expression parameterValue = ConvertArgumentValue(parameter);
attribute.Arguments.Add(parameterValue);
}

if (customAttribute.HasProperties)
foreach (var propertyNamedArg in customAttribute.Properties)
{
var propertyReference = customAttribute.AttributeType.Resolve().Properties.First(pr => pr.Name == propertyNamedArg.Name);
var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference);
var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument);
attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue));
}

if (customAttribute.HasFields)
foreach (var fieldNamedArg in customAttribute.Fields)
{
var fieldReference = customAttribute.AttributeType.Resolve().Fields.First(f => f.Name == fieldNamedArg.Name);
var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference);
var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument);
attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue));
}
}

attributedNode.AddChild(section, AttributedNode.AttributeRole);
}
}

private static Expression ConvertArgumentValue(CustomAttributeArgument parameter)
{
var type = parameter.Type.Resolve();
Expression parameterValue;
if (type.IsEnum)
{
parameterValue = MakePrimitive(Convert.ToInt64(parameter.Value), type);
}
else if (parameter.Value is TypeReference)
{
parameterValue = new TypeOfExpression()
{
Type = ConvertType((TypeReference)parameter.Value),
};
}
else
{
parameterValue = new PrimitiveExpression(parameter.Value);
}
return parameterValue;
}


internal static Expression MakePrimitive(long val, TypeReference type)
{
if (TypeAnalysis.IsBoolean(type) && val == 0)
return new Ast.PrimitiveExpression(false);
else if (TypeAnalysis.IsBoolean(type) && val == 1)
return new Ast.PrimitiveExpression(true);
if (type != null)
{ // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve();
if (enumDefinition != null && enumDefinition.IsEnum)
{
foreach (FieldDefinition field in enumDefinition.Fields)
{
if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
return ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
else if (!field.IsStatic && field.IsRuntimeSpecialName)
type = field.FieldType; // use primitive type of the enum
}
if (IsFlagsEnum(enumDefinition))
{
long enumValue = val;
Expression expr = null;
foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic))
{
long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
if (fieldValue == 0)
continue; // skip None enum value

if ((fieldValue & enumValue) == fieldValue)
{
var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
if (expr == null)
expr = fieldExpression;
else
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression);

enumValue &= ~fieldValue;
if (enumValue == 0)
break;
}
}
if(enumValue == 0 && expr != null)
return expr;
}
TypeCode enumBaseTypeCode = TypeAnalysis.GetTypeCode(type);
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(enumDefinition));
}
}
TypeCode code = TypeAnalysis.GetTypeCode(type);
if (code == TypeCode.Object)
return new Ast.PrimitiveExpression((int)val);
else
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false));
}

static bool IsFlagsEnum(TypeDefinition type)
{
if (!type.HasCustomAttributes)
return false;

return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute");
}
} }
} }
38 changes: 10 additions & 28 deletions ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
Expand Up @@ -527,7 +527,7 @@ AstNode TransformByteCode(ILExpression byteCode)
return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand)); return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand));
} }
case Code.Ldc_I4: case Code.Ldc_I4:
return MakePrimitive((int)operand, byteCode.InferredType); return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType);
case Code.Ldc_I8: case Code.Ldc_I8:
case Code.Ldc_R4: case Code.Ldc_R4:
case Code.Ldc_R8: case Code.Ldc_R8:
Expand Down Expand Up @@ -786,47 +786,29 @@ Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Ceci
if (TypeAnalysis.IsBoolean(actualType)) if (TypeAnalysis.IsBoolean(actualType))
return expr; return expr;
if (actualIsIntegerOrEnum) { if (actualIsIntegerOrEnum) {
return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, MakePrimitive(0, actualType)); return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType));
} else { } else {
return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression());
} }
} }
if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) {
return new ConditionalExpression { return new ConditionalExpression {
Condition = expr, Condition = expr,
TrueExpression = MakePrimitive(1, reqType), TrueExpression = AstBuilder.MakePrimitive(1, reqType),
FalseExpression = MakePrimitive(0, reqType) FalseExpression = AstBuilder.MakePrimitive(0, reqType)
}; };
} }

if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType))
{
return expr.CastTo(AstBuilder.ConvertType(actualType));
}

if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) { if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) {
return expr.CastTo(AstBuilder.ConvertType(reqType)); return expr.CastTo(AstBuilder.ConvertType(reqType));
} }
return expr; return expr;
} }
} }

Expression MakePrimitive(long val, TypeReference type)
{
if (TypeAnalysis.IsBoolean(type) && val == 0)
return new Ast.PrimitiveExpression(false);
else if (TypeAnalysis.IsBoolean(type) && val == 1)
return new Ast.PrimitiveExpression(true);
if (type != null) { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve();
if (enumDefinition != null && enumDefinition.IsEnum) {
foreach (FieldDefinition field in enumDefinition.Fields) {
if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
return AstBuilder.ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
else if (!field.IsStatic && field.IsRuntimeSpecialName)
type = field.FieldType; // use primitive type of the enum
}
}
}
TypeCode code = TypeAnalysis.GetTypeCode(type);
if (code == TypeCode.Object)
return new Ast.PrimitiveExpression((int)val);
else
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false));
}
} }
} }
Expand Up @@ -48,6 +48,7 @@ public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, obj
if (ctors.Length == 1 && ctors[0].Body.Children.Count() == 0 if (ctors.Length == 1 && ctors[0].Body.Children.Count() == 0
&& ctors[0].Initializer.ConstructorInitializerType == ConstructorInitializerType.Base && ctors[0].Initializer.ConstructorInitializerType == ConstructorInitializerType.Base
&& ctors[0].Initializer.Arguments.Count() == 0 && ctors[0].Initializer.Arguments.Count() == 0
&& ctors[0].Parameters.Count == 0
&& ctors[0].Modifiers == ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public)) && ctors[0].Modifiers == ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public))
{ {
ctors[0].Remove(); ctors[0].Remove();
Expand Down
9 changes: 9 additions & 0 deletions ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
Expand Up @@ -647,6 +647,15 @@ public static bool IsIntegerOrEnum(TypeReference type)
{ {
return IsSigned(type) != null; return IsSigned(type) != null;
} }

public static bool IsEnum(TypeReference type)
{
if (type == null)
return false;
// unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
TypeDefinition typeDef = type.Resolve() as TypeDefinition;
return typeDef != null && typeDef.IsEnum;
}


static bool? IsSigned(TypeReference type) static bool? IsSigned(TypeReference type)
{ {
Expand Down

0 comments on commit b16ca10

Please sign in to comment.