Browse Source

Add support for type forwarding declarations ([TypeForwardedToAttribute]). Closes #190.

pull/194/merge
Daniel Grunwald 14 years ago
parent
commit
3779381796
  1. 68
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 31
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 15
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

68
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -128,6 +128,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -128,6 +128,7 @@ namespace ICSharpCode.Decompiler.Ast
ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly");
ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly");
ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module");
AddTypeForwarderAttributes(astCompileUnit, assemblyDefinition.MainModule, "assembly");
if (!onlyAssemblyLevel) {
foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
@ -142,6 +143,30 @@ namespace ICSharpCode.Decompiler.Ast @@ -142,6 +143,30 @@ namespace ICSharpCode.Decompiler.Ast
}
}
void AddTypeForwarderAttributes(CompilationUnit astCompileUnit, ModuleDefinition module, string target)
{
if (!module.HasExportedTypes)
return;
foreach (ExportedType type in module.ExportedTypes) {
if (type.IsForwarder) {
var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope));
astCompileUnit.AddChild(
new AttributeSection {
AttributeTarget = target,
Attributes = {
new NRefactory.CSharp.Attribute {
Type = new SimpleType("TypeForwardedTo")
.WithAnnotation(new TypeReference(
"System.Runtime.CompilerServices", "TypeForwardedToAttribute",
module, module.TypeSystem.Corlib)),
Arguments = { forwardedType }
}
}
}, AttributedNode.AttributeRole);
}
}
}
NamespaceDeclaration GetCodeNamespace(string name)
{
if (string.IsNullOrEmpty(name)) {
@ -306,6 +331,45 @@ namespace ICSharpCode.Decompiler.Ast @@ -306,6 +331,45 @@ namespace ICSharpCode.Decompiler.Ast
return name;
}
#region Create TypeOf Expression
/// <summary>
/// Creates a typeof-expression for the specified type.
/// </summary>
public static TypeOfExpression CreateTypeOfExpression(TypeReference type)
{
return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type)));
}
static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
{
TypeReference typeRef = type.Annotation<TypeReference>();
if (typeRef == null)
return type;
TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
if (typeDef == null || !typeDef.HasGenericParameters)
return type;
SimpleType sType = type as SimpleType;
MemberType mType = type as MemberType;
if (sType != null) {
while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
sType.TypeArguments.Add(new SimpleType(""));
}
}
if (mType != null) {
AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
mType.TypeArguments.Add(new SimpleType(""));
}
}
return type;
}
#endregion
#region Convert Type Reference
/// <summary>
/// Converts a type reference.
@ -1378,9 +1442,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1378,9 +1442,7 @@ namespace ICSharpCode.Decompiler.Ast
if (type != null && type.IsEnum) {
return MakePrimitive(Convert.ToInt64(argument.Value), type);
} else if (argument.Value is TypeReference) {
return new TypeOfExpression() {
Type = ConvertType((TypeReference)argument.Value),
};
return CreateTypeOfExpression((TypeReference)argument.Value);
} else {
return new PrimitiveExpression(argument.Value);
}

31
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand);
case ILCode.Ldtoken:
if (operand is Cecil.TypeReference) {
return new Ast.TypeOfExpression { Type = AddEmptyTypeArgumentsForUnboundGenerics(operandAsTypeRef) }.Member("TypeHandle");
return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle");
} else {
return InlineAssembly(byteCode, args);
}
@ -749,35 +749,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -749,35 +749,6 @@ namespace ICSharpCode.Decompiler.Ast
}
}
AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
{
TypeReference typeRef = type.Annotation<TypeReference>();
if (typeRef == null)
return type;
TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
if (typeDef == null || !typeDef.HasGenericParameters)
return type;
SimpleType sType = type as SimpleType;
MemberType mType = type as MemberType;
if (sType != null) {
while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
sType.TypeArguments.Add(new SimpleType(""));
}
}
if (mType != null) {
AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
mType.TypeArguments.Add(new SimpleType(""));
}
}
return type;
}
static readonly AstNode objectInitializerPattern = new AssignmentExpression(
new MemberReferenceExpression {
Target = new InitializedObjectExpression()

15
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -1096,6 +1096,21 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1096,6 +1096,21 @@ namespace ICSharpCode.Decompiler.Disassembler
public void WriteModuleHeader(ModuleDefinition module)
{
if (module.HasExportedTypes) {
foreach (ExportedType exportedType in module.ExportedTypes) {
output.Write(".class extern ");
if (exportedType.IsForwarder)
output.Write("forwarder ");
output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName);
OpenBlock(false);
if (exportedType.DeclaringType != null)
output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName));
else
output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name));
CloseBlock();
}
}
output.WriteLine(".module {0}", module.Name);
output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant());
// TODO: imagebase, file alignment, stackreserve, subsystem

Loading…
Cancel
Save