diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs index 03834fc5f..b6f2e41ed 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs @@ -17,11 +17,28 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Reflection; +using System.Runtime.CompilerServices; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { internal class MemberTests { + public class IndexerNonDefaultName + { + [IndexerName("Foo")] + public int this[int index] { + get { + return 0; + } + } + } + + [DefaultMember("Bar")] + public class NoDefaultMember + { + } + public const int IntConstant = 1; public const decimal DecimalConstant = 2m; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il index da40d0564..247a3805c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il @@ -32,6 +32,57 @@ .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests extends [mscorlib]System.Object { + .class auto ansi nested public beforefieldinit IndexerNonDefaultName + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 46 6F 6F 00 00 ) // ...Foo.. + .method public hidebysig specialname + instance int32 get_Foo(int32 index) cil managed + { + // Code size 7 (0x7) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0005 + + IL_0005: ldloc.0 + IL_0006: ret + } // end of method IndexerNonDefaultName::get_Foo + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method IndexerNonDefaultName::.ctor + + .property instance int32 Foo(int32) + { + .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests/IndexerNonDefaultName::get_Foo(int32) + } // end of property IndexerNonDefaultName::Foo + } // end of class IndexerNonDefaultName + + .class auto ansi nested public beforefieldinit NoDefaultMember + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 42 61 72 00 00 ) // ...Bar.. + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method NoDefaultMember::.ctor + + } // end of class NoDefaultMember + .field public static literal int32 IntConstant = int32(0x00000001) .field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8, diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il index ca67438f1..88744f124 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il @@ -32,6 +32,51 @@ .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests extends [mscorlib]System.Object { + .class auto ansi nested public beforefieldinit IndexerNonDefaultName + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 46 6F 6F 00 00 ) // ...Foo.. + .method public hidebysig specialname + instance int32 get_Foo(int32 index) cil managed + { + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } // end of method IndexerNonDefaultName::get_Foo + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method IndexerNonDefaultName::.ctor + + .property instance int32 Foo(int32) + { + .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests/IndexerNonDefaultName::get_Foo(int32) + } // end of property IndexerNonDefaultName::Foo + } // end of class IndexerNonDefaultName + + .class auto ansi nested public beforefieldinit NoDefaultMember + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 42 61 72 00 00 ) // ...Bar.. + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method NoDefaultMember::.ctor + + } // end of class NoDefaultMember + .field public static literal int32 IntConstant = int32(0x00000001) .field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8, diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il index 80e7127ac..31a544d3a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il @@ -36,6 +36,51 @@ .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests extends [mscorlib]System.Object { + .class auto ansi nested public beforefieldinit IndexerNonDefaultName + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 46 6F 6F 00 00 ) // ...Foo.. + .method public hidebysig specialname + instance int32 get_Foo(int32 index) cil managed + { + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } // end of method IndexerNonDefaultName::get_Foo + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method IndexerNonDefaultName::.ctor + + .property instance int32 Foo(int32) + { + .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests/IndexerNonDefaultName::get_Foo(int32) + } // end of property IndexerNonDefaultName::Foo + } // end of class IndexerNonDefaultName + + .class auto ansi nested public beforefieldinit NoDefaultMember + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 42 61 72 00 00 ) // ...Bar.. + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method NoDefaultMember::.ctor + + } // end of class NoDefaultMember + .field public static literal int32 IntConstant = int32(0x00000001) .field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8, diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il index d718bbccd..c23376411 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il @@ -36,6 +36,59 @@ .class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests extends [mscorlib]System.Object { + .class auto ansi nested public beforefieldinit IndexerNonDefaultName + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 46 6F 6F 00 00 ) // ...Foo.. + .method public hidebysig specialname + instance int32 get_Foo(int32 index) cil managed + { + // Code size 7 (0x7) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0005 + + IL_0005: ldloc.0 + IL_0006: ret + } // end of method IndexerNonDefaultName::get_Foo + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method IndexerNonDefaultName::.ctor + + .property instance int32 Foo(int32) + { + .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests/IndexerNonDefaultName::get_Foo(int32) + } // end of property IndexerNonDefaultName::Foo + } // end of class IndexerNonDefaultName + + .class auto ansi nested public beforefieldinit NoDefaultMember + extends [mscorlib]System.Object + { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 03 42 61 72 00 00 ) // ...Bar.. + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method NoDefaultMember::.ctor + + } // end of class NoDefaultMember + .field public static literal int32 IntConstant = int32(0x00000001) .field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant .custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8, diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 44b846562..e83fd4331 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1012,8 +1012,8 @@ namespace ICSharpCode.Decompiler.CSharp Debug.Assert(decompilationContext.CurrentMember == property); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property); - int lastDot = property.Name.LastIndexOf('.'); if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) { + int lastDot = property.Name.LastIndexOf('.'); propertyDecl.Name = property.Name.Substring(lastDot + 1); } FixParameterNames(propertyDecl); diff --git a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs index 608d83137..ce148131c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs @@ -89,7 +89,7 @@ namespace ICSharpCode.Decompiler.TypeSystem int dynamicTypeIndex = 0; int tupleTypeIndex = 0; - public ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames) + private ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames) { this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation)); this.hasDynamicAttribute = hasDynamicAttribute; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index f6db66626..a5a5cd1b8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -70,6 +70,9 @@ namespace ICSharpCode.Decompiler.TypeSystem PreserveSig, MethodImpl, + // Property attributes: + IndexerName, + // Parameter attributes: ParamArray, In, @@ -119,6 +122,8 @@ namespace ICSharpCode.Decompiler.TypeSystem new TopLevelTypeName("System.Runtime.InteropServices", nameof(DllImportAttribute)), new TopLevelTypeName("System.Runtime.InteropServices", nameof(PreserveSigAttribute)), new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplAttribute)), + // Property attributes: + new TopLevelTypeName("System.Runtime.CompilerServices", nameof(IndexerNameAttribute)), // Parameter attributes: new TopLevelTypeName("System", nameof(ParamArrayAttribute)), new TopLevelTypeName("System.Runtime.InteropServices", nameof(InAttribute)), diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 67713bb78..a3540908f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -158,6 +158,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; var propertyDef = metadata.GetPropertyDefinition(propertyHandle); + if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation) { + b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name); + } b.Add(propertyDef.GetCustomAttributes()); return b.Build(); }