diff --git a/ICSharpCode.Decompiler/CSharp/AstTypeBuilder.cs b/ICSharpCode.Decompiler/CSharp/AstTypeBuilder.cs index 39c87da3c..a3ea2f472 100644 --- a/ICSharpCode.Decompiler/CSharp/AstTypeBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/AstTypeBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; using ICSharpCode.Decompiler.CSharp.Syntax; @@ -8,6 +9,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; using FullTypeName = ICSharpCode.Decompiler.TypeSystem.FullTypeName; +using TopLevelTypeName = ICSharpCode.Decompiler.TypeSystem.TopLevelTypeName; namespace ICSharpCode.Decompiler.CSharp { @@ -23,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp public class AstTypeBuilder : ISignatureTypeProvider { - ConvertTypeOptions options; + readonly ConvertTypeOptions options; public AstTypeBuilder(ConvertTypeOptions options) { @@ -47,20 +49,30 @@ namespace ICSharpCode.Decompiler.CSharp return AstType.Create("System.IntPtr"); } + static readonly FullTypeName systemNullable = new TopLevelTypeName("System", "Nullable", 1); + public AstType GetGenericInstantiation(AstType genericType, ImmutableArray typeArguments) { - switch (genericType) { - case SimpleType st: - st.TypeArguments.AddRange(typeArguments); - return st; - case MemberType mt: - mt.TypeArguments.AddRange(typeArguments); - return mt; - default: - throw new NotImplementedException(); + var typeName = genericType.Annotations.OfType().FirstOrDefault(); + if (typeName == systemNullable && typeArguments.Length == 1) { + return typeArguments[0].MakeNullableType(); + } + if (typeName.IsNested && genericType is MemberType mt && typeArguments.Length > typeName.TypeParameterCount) { + // Some type arguments belong to the outer type: + int outerTpc = typeArguments.Length - typeName.TypeParameterCount; + Debug.Assert(outerTpc > 0); + GetGenericInstantiation(mt.Target, typeArguments.Slice(0, outerTpc).ToImmutableArray()); + foreach (var ta in typeArguments.Slice(typeArguments.Length - typeName.TypeParameterCount)) { + mt.AddChild(ta, Roles.TypeArgument); + } + } else { + foreach (var ta in typeArguments) { + genericType.AddChild(ta, Roles.TypeArgument); + } } + return genericType; } - + public AstType GetGenericMethodParameter(GenericContext genericContext, int index) { return new SimpleType(genericContext.GetGenericMethodTypeParameterName(index)); @@ -88,122 +100,16 @@ namespace ICSharpCode.Decompiler.CSharp public AstType GetPrimitiveType(PrimitiveTypeCode typeCode) { - switch (typeCode) { - case PrimitiveTypeCode.Boolean: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Boolean"); - return AstType.Create("System.Boolean"); - } - return new PrimitiveType("bool"); - case PrimitiveTypeCode.Byte: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Byte"); - return AstType.Create("System.Byte"); - } - return new PrimitiveType("byte"); - case PrimitiveTypeCode.SByte: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("SByte"); - return AstType.Create("System.SByte"); - } - return new PrimitiveType("sbyte"); - case PrimitiveTypeCode.Char: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Char"); - return AstType.Create("System.Char"); - } - return new PrimitiveType("char"); - case PrimitiveTypeCode.Int16: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Int16"); - return AstType.Create("System.Int16"); - } - return new PrimitiveType("short"); - case PrimitiveTypeCode.UInt16: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("UInt16"); - return AstType.Create("System.UInt16"); - } - return new PrimitiveType("ushort"); - case PrimitiveTypeCode.Int32: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Int32"); - return AstType.Create("System.In32"); - } - return new PrimitiveType("int"); - case PrimitiveTypeCode.UInt32: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("UInt32"); - return AstType.Create("System.UInt32"); - } - return new PrimitiveType("uint"); - case PrimitiveTypeCode.Int64: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Int64"); - return AstType.Create("System.Int64"); - } - return new PrimitiveType("long"); - case PrimitiveTypeCode.UInt64: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("UInt64"); - return AstType.Create("System.UInt64"); - } - return new PrimitiveType("ulong"); - case PrimitiveTypeCode.Single: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Single"); - return AstType.Create("System.Single"); - } - return new PrimitiveType("float"); - case PrimitiveTypeCode.Double: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Double"); - return AstType.Create("System.Double"); - } - return new PrimitiveType("double"); - case PrimitiveTypeCode.IntPtr: - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("IntPtr"); - return AstType.Create("System.IntPtr"); - case PrimitiveTypeCode.UIntPtr: - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("UIntPtr"); - return AstType.Create("System.UIntPtr"); - case PrimitiveTypeCode.Object: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("Object"); - return AstType.Create("System.Object"); - } - return new PrimitiveType("object"); - case PrimitiveTypeCode.String: - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) != 0) { - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("String"); - return AstType.Create("System.String"); - } - return new PrimitiveType("string"); - case PrimitiveTypeCode.TypedReference: - if ((options & ConvertTypeOptions.IncludeNamespace) == 0) - return AstType.Create("TypedReference"); - return AstType.Create("System.TypedReference"); - case PrimitiveTypeCode.Void: - return new PrimitiveType("void"); - default: - throw new NotSupportedException(); + var knownTypeCode = typeCode.ToKnownTypeCode(); + var ktr = Decompiler.TypeSystem.KnownTypeReference.Get(knownTypeCode); + if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) == 0) { + string keyword = Decompiler.TypeSystem.KnownTypeReference.GetCSharpNameByTypeCode(knownTypeCode); + if (keyword != null) + return new PrimitiveType(keyword); } + if ((options & ConvertTypeOptions.IncludeNamespace) == 0) + return new SimpleType(ktr.Name); + return AstType.Create(ktr.Namespace).MemberType(ktr.Name); } public AstType GetSZArrayType(AstType elementType) @@ -231,12 +137,12 @@ namespace ICSharpCode.Decompiler.CSharp { if (fullTypeName.IsNested) { int count = fullTypeName.GetNestedTypeAdditionalTypeParameterCount(fullTypeName.NestingLevel - 1); - if ((options & (ConvertTypeOptions.IncludeOuterTypeName | ConvertTypeOptions.IncludeNamespace)) != 0) { - var outerType = MakeAstType(fullTypeName.GetDeclaringType()); - return new MemberType(outerType, fullTypeName.Name); - } else { - return new SimpleType(fullTypeName.Name); - } + var outerType = MakeAstType(fullTypeName.GetDeclaringType()); + // Note: we must always emit the outer type name here; + // if not desired it can only be cleaned up after InsertDynamicTypeVisitor. + var nestedType = new MemberType(outerType, fullTypeName.Name); + nestedType.AddAnnotation(fullTypeName); + return nestedType; } AstType baseType; var topLevel = fullTypeName.TopLevelTypeName; @@ -245,6 +151,7 @@ namespace ICSharpCode.Decompiler.CSharp } else { baseType = AstType.Create(topLevel.Name); } + baseType.AddAnnotation(fullTypeName); return baseType; } } diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 57721976a..e45d0695a 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -57,7 +57,6 @@ namespace ICSharpCode.Decompiler.IL MethodSignature methodSignature; StackType methodReturnStackType; BlobReader reader; - int currentInstructionOffset; ImmutableStack currentStack; ILVariable[] parameterVariables; ILVariable[] localVariables; @@ -210,7 +209,7 @@ namespace ICSharpCode.Decompiler.IL /// void Warn(string message) { - Warnings.Add(string.Format("IL_{0:x4}: {1}", currentInstructionOffset, message)); + Warnings.Add(string.Format("IL_{0:x4}: {1}", reader.Offset, message)); } ImmutableStack MergeStacks(ImmutableStack a, ImmutableStack b) diff --git a/ICSharpCode.Decompiler/Metadata/Dom.cs b/ICSharpCode.Decompiler/Metadata/Dom.cs index 1d789d9b8..d4eb11753 100644 --- a/ICSharpCode.Decompiler/Metadata/Dom.cs +++ b/ICSharpCode.Decompiler/Metadata/Dom.cs @@ -824,7 +824,8 @@ namespace ICSharpCode.Decompiler.Metadata public FullTypeName GetPrimitiveType(PrimitiveTypeCode typeCode) { - return new TopLevelTypeName("System", typeCode.ToString()); + var ktr = KnownTypeReference.Get(typeCode.ToKnownTypeCode()); + return new TopLevelTypeName(ktr.Namespace, ktr.Name, ktr.TypeParameterCount); } public FullTypeName GetSZArrayType(FullTypeName elementType)