diff --git a/ICSharpCode.Decompiler.Tests/CustomAttributes/S_CustomAttributes.cs b/ICSharpCode.Decompiler.Tests/CustomAttributes/S_CustomAttributes.cs index ef189c87e..bec4928b9 100644 --- a/ICSharpCode.Decompiler.Tests/CustomAttributes/S_CustomAttributes.cs +++ b/ICSharpCode.Decompiler.Tests/CustomAttributes/S_CustomAttributes.cs @@ -17,8 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; -namespace aa +namespace CustomAttributes { public static class CustomAttributes { @@ -45,21 +46,47 @@ namespace aa [My(null)] MaxUInt64 = 18446744073709551615uL } - [AttributeUsage(AttributeTargets.Class)] + [AttributeUsage(AttributeTargets.Field)] public class TypesAttribute : Attribute { public TypesAttribute(Type type) { } } - [Types(typeof(int))] - private class Class1 + private class SomeType { } - [Types(null)] - private class Class2 + private class SomeType + { + } + private struct DataType { + private int i; } + [Types(typeof(int))] + private static int typeattr_int; + [Types(null)] + private static int typeattr_null; + [Types(typeof(List))] + private static int typeattr_list_of_int; + [Types(typeof(List<>))] + private static int typeattr_list_unbound; + [Types(typeof(SomeType))] + private static int typeattr_sometype_of_datatype; + [Types(typeof(SomeType))] + private static int typeattr_sometype_of_datatype2; + [Types(typeof(SomeType))] + private static int typeattr_sometype_of_datatype_and_int; + [Types(typeof(SomeType))] + private static int typeattr_sometype_of_datatype_array_and_int; + [Types(typeof(SomeType, int>))] + private static int typeattr_sometype_of_nested_sometype; + [Types(typeof(SomeType))] + private static int typeattr_sometype_of_int_and_datatype; + [Types(typeof(int[]))] + private static int typeattr_array_of_int; + [Types(typeof(int[,,,][,]))] + private static int typeattr_multidim_array_of_int; [My(EnumWithFlag.Item1 | EnumWithFlag.Item2)] private static int field; diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs index 34dd735e0..df99fa91e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs @@ -234,7 +234,11 @@ namespace ICSharpCode.Decompiler.TypeSystem } } - static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos) + /// + /// Parses the reflection name starting at pos. + /// If local is true, only parses local type names, not assembly qualified type names. + /// + static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, bool local=false) { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); @@ -256,9 +260,8 @@ namespace ICSharpCode.Decompiler.TypeSystem } } else { // not a type parameter reference: read the actual type name - int tpc; - string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); - string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); + string typeName = ReadTypeName(reflectionTypeName, ref pos, out int tpc); + string assemblyName = local ? null : SkipAheadAndReadAssemblyName(reflectionTypeName, pos); reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); } // read type suffixes @@ -279,29 +282,30 @@ namespace ICSharpCode.Decompiler.TypeSystem // this might be an array or a generic type if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); - if (reflectionTypeName[pos] == '[') { + if (reflectionTypeName[pos] != ']' && reflectionTypeName[pos] != ',') { // it's a generic type List typeArguments = new List(); - pos++; - typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') - pos++; - else - throw new ReflectionNameParseException(pos, "Expected end of type argument"); - - while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { - pos++; - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') - pos++; - else - throw new ReflectionNameParseException(pos, "Expected another type argument"); - - typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); - - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + bool first = true; + while (first || pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { + if (first) { + first = false; + } else { + pos++; // skip ',' + } + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { + // non-local type names are enclosed in another set of [] pos++; - else - throw new ReflectionNameParseException(pos, "Expected end of type argument"); + + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); + + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + pos++; + else + throw new ReflectionNameParseException(pos, "Expected end of type argument"); + } else { + // local type names occur directly in the outer [] + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, local: true)); + } } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { @@ -325,14 +329,14 @@ namespace ICSharpCode.Decompiler.TypeSystem } } break; - case ',': + case ',' when !local: // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') pos++; break; default: pos--; // reset pos to the character we couldn't read - if (reflectionTypeName[pos] == ']') + if (reflectionTypeName[pos] == ']' || reflectionTypeName[pos] == ',') return reference; // return from a nested generic else throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'");