diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 6edcaa2e2..fda33199b 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -771,5 +771,206 @@ namespace ICSharpCode.Decompiler.CSharp
}
return eventDecl;
}
+
+ #region Convert Type Reference
+ ///
+ /// Converts a type reference.
+ ///
+ /// The Cecil type reference that should be converted into
+ /// a type system type reference.
+ /// Attributes associated with the Cecil type reference.
+ /// This is used to support the 'dynamic' type.
+ public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
+ {
+ int typeIndex = 0;
+ return ConvertType(type, typeAttributes, ref typeIndex, options);
+ }
+
+ static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
+ {
+ while (type is OptionalModifierType || type is RequiredModifierType) {
+ type = ((TypeSpecification)type).ElementType;
+ }
+ if (type == null) {
+ return AstType.Null;
+ }
+
+ if (type is Mono.Cecil.ByReferenceType) {
+ typeIndex++;
+ // by reference type cannot be represented in C#; so we'll represent it as a pointer instead
+ return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakePointerType();
+ } else if (type is Mono.Cecil.PointerType) {
+ typeIndex++;
+ return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakePointerType();
+ } else if (type is Mono.Cecil.ArrayType) {
+ typeIndex++;
+ return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakeArrayType((type as Mono.Cecil.ArrayType).Rank);
+ } else if (type is GenericInstanceType) {
+ GenericInstanceType gType = (GenericInstanceType)type;
+ if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
+ typeIndex++;
+ return new ComposedType {
+ BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
+ HasNullableSpecifier = true
+ };
+ }
+ AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
+ List typeArguments = new List();
+ foreach (var typeArgument in gType.GenericArguments) {
+ typeIndex++;
+ typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
+ }
+ ApplyTypeArgumentsTo(baseType, typeArguments);
+ return baseType;
+ } else if (type is GenericParameter) {
+ return new SimpleType(type.Name);
+ } else if (type.IsNested) {
+ AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
+ string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
+ MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
+ memberType.AddAnnotation(type);
+ if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
+ AddTypeParameterDefininitionsTo(type, memberType);
+ }
+ return memberType;
+ } else {
+ string ns = type.Namespace ?? string.Empty;
+ string name = type.Name;
+ if (name == null)
+ throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
+
+ if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
+ return new Syntax.PrimitiveType("dynamic");
+ } else {
+ if (ns == "System") {
+ if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames)
+ != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) {
+ switch (name) {
+ case "SByte":
+ return new Syntax.PrimitiveType("sbyte");
+ case "Int16":
+ return new Syntax.PrimitiveType("short");
+ case "Int32":
+ return new Syntax.PrimitiveType("int");
+ case "Int64":
+ return new Syntax.PrimitiveType("long");
+ case "Byte":
+ return new Syntax.PrimitiveType("byte");
+ case "UInt16":
+ return new Syntax.PrimitiveType("ushort");
+ case "UInt32":
+ return new Syntax.PrimitiveType("uint");
+ case "UInt64":
+ return new Syntax.PrimitiveType("ulong");
+ case "String":
+ return new Syntax.PrimitiveType("string");
+ case "Single":
+ return new Syntax.PrimitiveType("float");
+ case "Double":
+ return new Syntax.PrimitiveType("double");
+ case "Decimal":
+ return new Syntax.PrimitiveType("decimal");
+ case "Char":
+ return new Syntax.PrimitiveType("char");
+ case "Boolean":
+ return new Syntax.PrimitiveType("bool");
+ case "Void":
+ return new Syntax.PrimitiveType("void");
+ case "Object":
+ return new Syntax.PrimitiveType("object");
+ }
+ }
+ }
+
+ name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
+
+ AstType astType;
+ if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
+ string[] parts = ns.Split('.');
+ AstType nsType = new SimpleType(parts[0]);
+ for (int i = 1; i < parts.Length; i++) {
+ nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+ }
+ astType = new MemberType { Target = nsType, MemberName = name };
+ } else {
+ astType = new SimpleType(name);
+ }
+ astType.AddAnnotation(type);
+
+ if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
+ AddTypeParameterDefininitionsTo(type, astType);
+ }
+ return astType;
+ }
+ }
+ }
+
+ static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
+ {
+ if (type.HasGenericParameters) {
+ List typeArguments = new List();
+ foreach (GenericParameter gp in type.GenericParameters) {
+ typeArguments.Add(new SimpleType(gp.Name));
+ }
+ ApplyTypeArgumentsTo(astType, typeArguments);
+ }
+ }
+
+ static void ApplyTypeArgumentsTo(AstType baseType, List typeArguments)
+ {
+ SimpleType st = baseType as SimpleType;
+ if (st != null) {
+ st.TypeArguments.AddRange(typeArguments);
+ }
+ MemberType mt = baseType as MemberType;
+ if (mt != null) {
+ TypeReference type = mt.Annotation();
+ if (type != null) {
+ int typeParameterCount;
+ ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
+ if (typeParameterCount > typeArguments.Count)
+ typeParameterCount = typeArguments.Count;
+ mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
+ typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
+ if (typeArguments.Count > 0)
+ ApplyTypeArgumentsTo(mt.Target, typeArguments);
+ } else {
+ mt.TypeArguments.AddRange(typeArguments);
+ }
+ }
+ }
+
+ const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
+
+ static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
+ {
+ if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
+ return false;
+ foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
+ if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) {
+ if (a.ConstructorArguments.Count == 1) {
+ CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
+ if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
+ return (bool)values[typeIndex].Value;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ #endregion
+
+ }
+
+ [Flags]
+ public enum ConvertTypeOptions
+ {
+ None = 0,
+ IncludeNamespace = 1,
+ IncludeTypeParameterDefinitions = 2,
+ DoNotUsePrimitiveTypeNames = 4
}
}
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 56ffeaae5..5a1651323 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy
bool showAllMembers = false;
int transformCount = int.MaxValue;
- #if DEBUG
+#if DEBUG
internal static IEnumerable GetDebugLanguages()
{
var decompiler = new CSharpDecompiler(ModuleDefinition.CreateModule("Dummy", ModuleKind.Dll), new DecompilerSettings());
@@ -70,20 +70,17 @@ namespace ICSharpCode.ILSpy
showAllMembers = true
};
}
- #endif
+#endif
- public override string Name
- {
+ public override string Name {
get { return name; }
}
- public override string FileExtension
- {
+ public override string FileExtension {
get { return ".cs"; }
}
- public override string ProjectFileExtension
- {
+ public override string ProjectFileExtension {
get { return ".csproj"; }
}
@@ -95,7 +92,7 @@ namespace ICSharpCode.ILSpy
decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1);
return decompiler;
}
-
+
void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
@@ -103,7 +100,7 @@ namespace ICSharpCode.ILSpy
var formattingPolicy = settings.CSharpFormattingOptions;
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
}
-
+
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(method.Module.Assembly, output);
@@ -117,11 +114,11 @@ namespace ICSharpCode.ILSpy
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method), decompiler.TypeSystem);
}
}
-
+
class SelectCtorTransform : IAstTransform
{
readonly IMethod ctor;
-
+
public SelectCtorTransform(IMethod ctor)
{
this.ctor = ctor;
@@ -197,7 +194,7 @@ namespace ICSharpCode.ILSpy
sealed class SelectFieldTransform : IAstTransform
{
readonly IField field;
-
+
public SelectFieldTransform(IField field)
{
this.field = field;
@@ -328,7 +325,7 @@ namespace ICSharpCode.ILSpy
output.WriteLine("// Runtime: " + runtimeName);
}
output.WriteLine();
-
+
// don't automatically load additional assemblies when an assembly node is selected in the tree view
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
CSharpDecompiler decompiler = new CSharpDecompiler(assembly.ModuleDefinition, options.DecompilerSettings);
@@ -343,25 +340,25 @@ namespace ICSharpCode.ILSpy
}
}
}
-
+
class ILSpyWholeProjectDecompiler : WholeProjectDecompiler
{
readonly LoadedAssembly assembly;
readonly DecompilationOptions options;
-
+
public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options)
{
this.assembly = assembly;
this.options = options;
base.Settings = options.DecompilerSettings;
}
-
+
protected override IEnumerable> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
if (fileName.EndsWith(".resource", StringComparison.OrdinalIgnoreCase)) {
using (ResourceReader reader = new ResourceReader(entryStream))
- using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write))
- using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
+ using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write))
+ using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
foreach (DictionaryEntry entry in reader) {
writer.AddResource((string)entry.Key, entry.Value);
}
@@ -395,6 +392,7 @@ namespace ICSharpCode.ILSpy
Settings = settings
});
}
+ */
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null)
{
@@ -407,7 +405,7 @@ namespace ICSharpCode.ILSpy
string TypeToString(ConvertTypeOptions options, TypeReference type, ICustomAttributeProvider typeAttributes = null)
{
- AstType astType = AstBuilder.ConvertType(type, typeAttributes, options);
+ AstType astType = CSharpDecompiler.ConvertType(type, typeAttributes, options);
StringWriter w = new StringWriter();
if (type.IsByReference) {
@@ -424,9 +422,9 @@ namespace ICSharpCode.ILSpy
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
+
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
- */
-
+
public override string FormatPropertyName(PropertyDefinition property, bool? isIndexer)
{
if (property == null)
@@ -466,15 +464,14 @@ namespace ICSharpCode.ILSpy
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name;
}
- /*
public override string FormatTypeName(TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
-
+
return TypeToString(ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type);
}
- */
+
public override bool ShowMember(MemberReference member)
{
return showAllMembers || !CSharpDecompiler.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);