diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs index b5293f3f0f..eae9bc5d3b 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs @@ -127,12 +127,6 @@ namespace ICSharpCode.NRefactory.Ast public static TypeReference GetTypeReference(this Type type) { - int pointerNest = 0; - while(type.IsPointer) { - pointerNest++; - type = type.GetElementType(); - } - List arrayRanks = new List(); while(type.IsArray) { // C# uses reverse array order @@ -140,7 +134,13 @@ namespace ICSharpCode.NRefactory.Ast type = type.GetElementType(); } - if (type.IsPointer) + int pointerNest = 0; + while(type.IsPointer) { + pointerNest++; + type = type.GetElementType(); + } + + if (type.IsArray) throw new DebuggerException("C# does not support pointers to arrays"); string name = type.Name; @@ -149,19 +149,23 @@ namespace ICSharpCode.NRefactory.Ast if (!string.IsNullOrEmpty(type.Namespace)) name = type.Namespace + "." + name; - List genArgs = new List(); - // TODO: Does it inlucde parent gen arguments - foreach(Type genArg in type.GetGenericArguments()) - genArgs.Add(genArg.GetTypeReference()); + List genArgs = new List(); + genArgs.AddRange(type.GetGenericArguments()); + if (type.DeclaringType != null) + genArgs.RemoveRange(0, type.DeclaringType.GetGenericArguments().Length); + List genTypeRefs = new List(); + foreach(Type genArg in genArgs) { + genTypeRefs.Add(genArg.GetTypeReference()); + } if (type.DeclaringType != null) { TypeReference outterRef = type.DeclaringType.GetTypeReference(); - InnerClassTypeReference innerRef = new InnerClassTypeReference(outterRef, name, genArgs); + InnerClassTypeReference innerRef = new InnerClassTypeReference(outterRef, name, genTypeRefs); innerRef.PointerNestingLevel = pointerNest; innerRef.RankSpecifier = arrayRanks.ToArray(); return innerRef; } else { - return new TypeReference(name, pointerNest, arrayRanks.ToArray(), genArgs); + return new TypeReference(name, pointerNest, arrayRanks.ToArray(), genTypeRefs); } } @@ -185,6 +189,17 @@ namespace ICSharpCode.NRefactory.Ast ); } else if (expr is TypeReferenceExpression) { return NormalizeTypeReference(((TypeReferenceExpression)expr).TypeReference); + } else if (expr is InnerClassTypeReference) { // Frist - it is also TypeReference + InnerClassTypeReference typeRef = (InnerClassTypeReference)expr; + string[] names = typeRef.Type.Split('.'); + TypeReference newRef = NormalizeTypeReference(typeRef.BaseType); + foreach(string name in names) { + newRef = new InnerClassTypeReference(newRef, name, new List()); + } + newRef.GenericTypes.AddRange(typeRef.GenericTypes); + newRef.PointerNestingLevel = typeRef.PointerNestingLevel; + newRef.RankSpecifier = typeRef.RankSpecifier; + return newRef; } else if (expr is TypeReference) { TypeReference typeRef = (TypeReference)expr; string[] names = typeRef.Type.Split('.'); @@ -202,17 +217,6 @@ namespace ICSharpCode.NRefactory.Ast newRef.PointerNestingLevel = typeRef.PointerNestingLevel; newRef.RankSpecifier = typeRef.RankSpecifier; return newRef; - } else if (expr is InnerClassTypeReference) { - InnerClassTypeReference typeRef = (InnerClassTypeReference)expr; - string[] names = typeRef.Type.Split('.'); - TypeReference newRef = NormalizeTypeReference(typeRef.BaseType); - foreach(string name in names) { - newRef = new InnerClassTypeReference(newRef, name, new List()); - } - newRef.GenericTypes.AddRange(typeRef.GenericTypes); - newRef.PointerNestingLevel = typeRef.PointerNestingLevel; - newRef.RankSpecifier = typeRef.RankSpecifier; - return newRef; } else { throw new EvaluateException(expr, "Type expected. {0} seen.", expr.GetType()); } @@ -222,7 +226,7 @@ namespace ICSharpCode.NRefactory.Ast { string name = typeRef.Type; if (typeRef.GenericTypes.Count > 0) - name += '`' + typeRef.GenericTypes.Count; + name += "`" + typeRef.GenericTypes.Count.ToString(); if (typeRef is InnerClassTypeReference) { return GetNameWithArgCounts(((InnerClassTypeReference)typeRef).BaseType) + "." + name; } else { @@ -256,8 +260,8 @@ namespace ICSharpCode.NRefactory.Ast } // Try to construct nested type - if (type != null && typeRef is InnerClassTypeReference) { - DebugType outter = ResolveType((InnerClassTypeReference)typeRef, appDomain); + if (type == null && typeRef is InnerClassTypeReference) { + DebugType outter = ResolveType(((InnerClassTypeReference)typeRef).BaseType, appDomain); if (outter == null) return null; string nestedName = typeRef.GenericTypes.Count == 0 ? typeRef.Type : typeRef.Type + "`" + typeRef.GenericTypes.Count; @@ -270,8 +274,10 @@ namespace ICSharpCode.NRefactory.Ast for(int i = 0; i < typeRef.PointerNestingLevel; i++) { type = (DebugType)type.MakePointerType(); } - for(int i = typeRef.RankSpecifier.Length - 1; i >= 0; i--) { - type = (DebugType)type.MakeArrayType(typeRef.RankSpecifier[i] + 1); + if (typeRef.RankSpecifier != null) { + for(int i = typeRef.RankSpecifier.Length - 1; i >= 0; i--) { + type = (DebugType)type.MakeArrayType(typeRef.RankSpecifier[i] + 1); + } } return type; } diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/DebugType_Tests.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/DebugType_Tests.cs index 49769f9147..fd81fe2660 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/DebugType_Tests.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/DebugType_Tests.cs @@ -105,6 +105,7 @@ namespace Debugger.Tests // Arrays char[] szArray = "Test".ToCharArray(); char[,] mdArray = new char[2,3]; + char[][,] jagArray = new char[][,] { mdArray }; // Generics - nullables int? nullable_value = 5; @@ -223,7 +224,7 @@ namespace Debugger.Tests { mscorlib.dll (No symbols) DebugType_Tests.exe (Has symbols) - Break DebugType_Tests.cs:137,4-137,40 + Break DebugType_Tests.cs:138,4-138,40 @@ -1065,6 +1066,59 @@ namespace Debugger.Tests { + + + + + + + + + null + + + + + + + + { + public class B { + public class C { + + } + } + } + public static void Main() { new ExpressionEvaluator_Tests().Fun("function argument"); } - public void Fun(string arg) + public unsafe void Fun(string arg) { bool flag = true; byte b = 1; @@ -124,6 +132,9 @@ namespace Debugger.Tests DerivedClass myClass = new DerivedClass(); + int*[][,] complexType1 = new int*[][,] { new int*[,] { { (int*)0xDA1D } } }; + A.B.C[][,] complexType2 = new A.B.C[0][,]; + System.Diagnostics.Debugger.Break(); } } @@ -136,15 +147,11 @@ namespace Debugger.Tests { using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Visitors; + using NUnit.Framework; public partial class DebuggerTests { - [NUnit.Framework.Test] - public void ExpressionEvaluator_Tests() - { - StartTest(); - - string input = @" + string expressionsInput = @" b i pi @@ -195,16 +202,21 @@ namespace Debugger.Tests { flag !flag "; + + [NUnit.Framework.Test] + public void ExpressionEvaluator_Tests() + { + StartTest(); - input = input.Replace("'", "\""); + expressionsInput = expressionsInput.Replace("'", "\""); - foreach(string line in input.Split('\n')) { + foreach(string line in expressionsInput.Split('\n')) { Eval(line.Trim()); } // Test member hiding / overloading - Value myClass = process.SelectedStackFrame.GetLocalVariableValue("myClass"); + Value myClass = process.SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(); List expressions = new List(); foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) { @@ -237,6 +249,19 @@ namespace Debugger.Tests { Eval(line.Trim()); } + // Test type round tripping + + foreach(DebugLocalVariableInfo locVar in process.SelectedStackFrame.MethodInfo.GetLocalVariables()) { + if (locVar.Name.StartsWith("complexType")) { + TypeReference complexTypeRef = locVar.LocalType.GetTypeReference(); + string code = "typeof(" + complexTypeRef.PrettyPrint() + ")"; + TypeOfExpression complexTypeRefRT = (TypeOfExpression)ExpressionEvaluator.Parse(code, SupportedLanguage.CSharp); + DebugType type = complexTypeRefRT.TypeReference.ResolveType(process.SelectedStackFrame.AppDomain); + string status = locVar.LocalType.FullName == type.FullName ? "ok" : "fail"; + ObjectDumpToString("TypeResulution", string.Format(" {0} = {1} ({2})", code, type.FullName, status)); + } + } + EndTest(); } @@ -271,7 +296,7 @@ namespace Debugger.Tests { mscorlib.dll (No symbols) ExpressionEvaluator_Tests.exe (Has symbols) - Break ExpressionEvaluator_Tests.cs:127,4-127,40 + Break ExpressionEvaluator_Tests.cs:138,4-138,40 b = 1 i = 4 @@ -352,6 +377,8 @@ namespace Debugger.Tests { myClass.Convert(1, 2) = Incorrect parameter type for 's'. Excpeted System.String, seen System.Int32 myClass.Convert("abc", 2) = "converted to abc and 2" + typeof(System.Int32*[][,]) = System.Int32*[,][] (ok) + typeof(Debugger.Tests.ExpressionEvaluator_Tests.A<System.Int32>.B.C<System.Char>[][,]) = Debugger.Tests.ExpressionEvaluator_Tests+A`1+B+C`1[System.Int32,System.Char][,][] (ok)