Browse Source

Resolve TypeReference to DebugType and vice versa. Genetic types, nested types, arrays and pointers are supported.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5154 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
b2c463cd26
  1. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs
  2. 44
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugType.cs
  3. 191
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs
  4. 43
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Visitors/ExpressionEvaluator.cs

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs

@ -30,8 +30,8 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -30,8 +30,8 @@ namespace Debugger.AddIn.Visualizers.Utils
listType = DebugType.CreateFromType(itemType.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
var iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType);
// explicitely cast the variable to IEnumerable<T>, where T is itemType
Expression iEnumerableVariableExplicitCast = new CastExpression(iEnumerableType.ToTypeReference() , iEnumerableVariable, CastType.Cast);
return new ObjectCreateExpression(listType.ToTypeReference(), iEnumerableVariableExplicitCast.ToList());
Expression iEnumerableVariableExplicitCast = new CastExpression(iEnumerableType.GetTypeReference() , iEnumerableVariable, CastType.Cast);
return new ObjectCreateExpression(listType.GetTypeReference(), iEnumerableVariableExplicitCast.ToList());
}
/// <summary>

44
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugType.cs

@ -806,30 +806,6 @@ namespace Debugger.MetaData @@ -806,30 +806,6 @@ namespace Debugger.MetaData
}
}
public static DebugType CreateFromDottedName(AppDomain appDomain, string dottedName, params DebugType[] genericArguments)
{
// The most common case
DebugType result = CreateFromName(appDomain, dottedName, null, genericArguments);
if (result != null)
return result;
string[] names = dottedName.Split('.');
for(int take = names.Length - 1; take > 0; take--) {
string enclosingName = string.Join(".", names, 0, take);
DebugType enclosingType = CreateFromName(appDomain, enclosingName, null, genericArguments);
if (enclosingType != null) {
for(int nested = take; nested < names.Length; nested++) {
string nestedName = names[nested];
enclosingType = CreateFromName(appDomain, nestedName, enclosingType, genericArguments);
if (enclosingType == null)
return null;
}
return enclosingType;
}
}
return null;
}
public static DebugType CreateFromType(Module module, System.Type type)
{
if (type is DebugType)
@ -915,26 +891,6 @@ namespace Debugger.MetaData @@ -915,26 +891,6 @@ namespace Debugger.MetaData
return CreateFromSignature(module, typeSpecBlob, declaringType);
}
public static DebugType CreateFromTypeReference(AppDomain appDomain, TypeReference typeRef)
{
List<DebugType> genArgs = new List<DebugType>();
foreach(TypeReference argRef in typeRef.GenericTypes) {
genArgs.Add(CreateFromTypeReference(appDomain, argRef));
}
// TODO: A<T>.C<U>
string name = typeRef.Type;
if (genArgs.Count > 0)
name += '`' + genArgs.Count;
DebugType type = CreateFromDottedName(appDomain, name, genArgs.ToArray());
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);
}
return type;
}
public static DebugType CreateFromSignature(Module module, byte[] signature, DebugType declaringType)
{
SignatureReader sigReader = new SignatureReader(signature);

191
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Ast/ExpressionExtensionMethods.cs

@ -48,12 +48,12 @@ namespace ICSharpCode.NRefactory.Ast @@ -48,12 +48,12 @@ namespace ICSharpCode.NRefactory.Ast
Expression target;
if (memberInfo.IsStatic) {
target = new TypeReferenceExpression(
memberInfo.DeclaringType.ToTypeReference()
memberInfo.DeclaringType.GetTypeReference()
);
} else {
target = new ParenthesizedExpression(
new CastExpression(
memberInfo.DeclaringType.ToTypeReference(),
memberInfo.DeclaringType.GetTypeReference(),
Parenthesize(expresion),
CastType.Cast
)
@ -108,7 +108,7 @@ namespace ICSharpCode.NRefactory.Ast @@ -108,7 +108,7 @@ namespace ICSharpCode.NRefactory.Ast
for(int i = 0; i < args.Length; i++) {
typedArgs.Add(
new CastExpression(
method.GetParameters()[i].ParameterType.ToTypeReference(),
method.GetParameters()[i].ParameterType.GetTypeReference(),
Parenthesize(args[i]),
CastType.Cast
)
@ -117,56 +117,163 @@ namespace ICSharpCode.NRefactory.Ast @@ -117,56 +117,163 @@ namespace ICSharpCode.NRefactory.Ast
return typedArgs;
}
public static string GetDottedName(this Type type)
public static string PrettyPrint(this INode code)
{
string fullName = null;
for(Type currentType = type; currentType != null; currentType = currentType.DeclaringType) {
string name = currentType.Name;
if (name.IndexOf('`') != -1)
name = name.Substring(0, name.IndexOf('`'));
if (currentType.Namespace != string.Empty)
name = currentType.Namespace + "." + name;
if (fullName == null) {
fullName = name;
} else {
fullName = name + "." + fullName;
}
}
return fullName;
if (code == null) return string.Empty;
CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
code.AcceptVisitor(csOutVisitor, null);
return csOutVisitor.Text;
}
public static TypeReference ToTypeReference(this Type type)
public static TypeReference GetTypeReference(this Type type)
{
List<int> arrayRanks = new List<int>();
int pointerNest = 0;
while(true) {
// TODO: Combined arrays and pointers?
// TODO: Check
if (type.IsArray) {
arrayRanks.Insert(0, type.GetArrayRank() - 1);
type = type.GetElementType();
} else if (type.IsPointer) {
pointerNest++;
type = type.GetElementType();
} else {
break;
}
while(type.IsPointer) {
pointerNest++;
type = type.GetElementType();
}
List<int> arrayRanks = new List<int>();
while(type.IsArray) {
// C# uses reverse array order
arrayRanks.Add(type.GetArrayRank() - 1);
type = type.GetElementType();
}
string name = type.GetDottedName();
if (type.IsPointer)
throw new DebuggerException("C# does not support pointers to arrays");
string name = type.Name;
if (name.IndexOf('`') != -1)
name = name.Substring(0, name.IndexOf('`'));
if (!string.IsNullOrEmpty(type.Namespace))
name = type.Namespace + "." + name;
List<TypeReference> genArgs = new List<TypeReference>();
foreach(DebugType genArg in type.GetGenericArguments()) {
genArgs.Add(genArg.ToTypeReference());
// TODO: Does it inlucde parent gen arguments
foreach(Type genArg in type.GetGenericArguments())
genArgs.Add(genArg.GetTypeReference());
if (type.DeclaringType != null) {
TypeReference outterRef = type.DeclaringType.GetTypeReference();
InnerClassTypeReference innerRef = new InnerClassTypeReference(outterRef, name, genArgs);
innerRef.PointerNestingLevel = pointerNest;
innerRef.RankSpecifier = arrayRanks.ToArray();
return innerRef;
} else {
return new TypeReference(name, pointerNest, arrayRanks.ToArray(), genArgs);
}
TypeReference typeRef = new TypeReference(name, pointerNest, arrayRanks.ToArray(), genArgs);
return typeRef;
}
public static string PrettyPrint(this INode code)
/// <summary>
/// Converts tree into nested TypeReference/InnerClassTypeReference.
/// Dotted names are split into separate nodes.
/// </summary>
public static TypeReference NormalizeTypeReference(this INode expr)
{
if (code == null) return string.Empty;
CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
code.AcceptVisitor(csOutVisitor, null);
return csOutVisitor.Text;
if (expr is IdentifierExpression) {
return new TypeReference(
((IdentifierExpression)expr).Identifier,
((IdentifierExpression)expr).TypeArguments
);
} else if (expr is MemberReferenceExpression) {
TypeReference outter = NormalizeTypeReference(((MemberReferenceExpression)expr).TargetObject);
return new InnerClassTypeReference(
outter,
((MemberReferenceExpression)expr).MemberName,
((MemberReferenceExpression)expr).TypeArguments
);
} else if (expr is TypeReferenceExpression) {
return NormalizeTypeReference(((TypeReferenceExpression)expr).TypeReference);
} else if (expr is TypeReference) {
TypeReference typeRef = (TypeReference)expr;
string[] names = typeRef.Type.Split('.');
if (names.Length == 1)
return typeRef;
TypeReference newRef = null;
foreach(string name in names) {
if (newRef == null) {
newRef = new TypeReference(name, new List<TypeReference>());
} else {
newRef = new InnerClassTypeReference(newRef, name, new List<TypeReference>());
}
}
newRef.GenericTypes.AddRange(typeRef.GenericTypes);
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<TypeReference>());
}
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());
}
}
static string GetNameWithArgCounts(TypeReference typeRef)
{
string name = typeRef.Type;
if (typeRef.GenericTypes.Count > 0)
name += '`' + typeRef.GenericTypes.Count;
if (typeRef is InnerClassTypeReference) {
return GetNameWithArgCounts(((InnerClassTypeReference)typeRef).BaseType) + "." + name;
} else {
return name;
}
}
public static DebugType ResolveType(this INode expr, Debugger.AppDomain appDomain)
{
TypeReference typeRef = NormalizeTypeReference(expr);
List<TypeReference> genTypeRefs;
if (typeRef is InnerClassTypeReference) {
genTypeRefs = ((InnerClassTypeReference)typeRef).CombineToNormalTypeReference().GenericTypes;
} else {
genTypeRefs = typeRef.GenericTypes;
}
List<DebugType> genArgs = new List<DebugType>();
foreach(TypeReference genTypeRef in genTypeRefs) {
genArgs.Add(ResolveType(genTypeRef, appDomain));
}
DebugType type = null;
// Try to construct non-nested type
// If there are generic types up in the tree, it must be nested type
if (genArgs.Count == typeRef.GenericTypes.Count) {
string name = GetNameWithArgCounts(typeRef);
type = DebugType.CreateFromName(appDomain, name, null, genArgs.ToArray());
}
// Try to construct nested type
if (type != null && typeRef is InnerClassTypeReference) {
DebugType outter = ResolveType((InnerClassTypeReference)typeRef, appDomain);
if (outter == null)
return null;
string nestedName = typeRef.GenericTypes.Count == 0 ? typeRef.Type : typeRef.Type + "`" + typeRef.GenericTypes.Count;
type = DebugType.CreateFromName(appDomain, nestedName, outter, genArgs.ToArray());
}
if (type == null)
return null;
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);
}
return type;
}
}
}

43
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Visitors/ExpressionEvaluator.cs

@ -16,6 +16,12 @@ using ICSharpCode.NRefactory.Ast; @@ -16,6 +16,12 @@ using ICSharpCode.NRefactory.Ast;
namespace ICSharpCode.NRefactory.Visitors
{
public class EvaluateException: GetValueException
{
public EvaluateException(INode code, string msg):base(code, msg) {}
public EvaluateException(INode code, string msgFmt, params object[] msgArgs):base(code, string.Format(msgFmt, msgArgs)) {}
}
public class ExpressionEvaluator: NotImplementedAstVisitor
{
const BindingFlags BindingFlagsAll = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
@ -173,36 +179,12 @@ namespace ICSharpCode.NRefactory.Visitors @@ -173,36 +179,12 @@ namespace ICSharpCode.NRefactory.Visitors
this.context = context;
}
DebugType ResoleType(Expression expr)
{
string name = GetTypeName(expr);
if (name == null)
return null;
// TODO: Generic arguments
return DebugType.CreateFromDottedName(context.AppDomain, name);
}
string GetTypeName(Expression expr)
{
if (expr is IdentifierExpression) {
return ((IdentifierExpression)expr).Identifier;
} else if (expr is MemberReferenceExpression) {
return GetTypeName(((MemberReferenceExpression)expr).TargetObject) + "." + ((MemberReferenceExpression)expr).MemberName;
} else if (expr is TypeReferenceExpression) {
TypeReference typeRef = ((TypeReferenceExpression)expr).TypeReference;
string genArity = typeRef.GenericTypes.Count > 0 ? "`" + typeRef.GenericTypes.Count : string.Empty;
return typeRef.Type + genArity;
} else {
return null;
}
}
public DebugType GetDebugType(INode expr)
{
if (expr is ParenthesizedExpression) {
return GetDebugType(((ParenthesizedExpression)expr).Expression);
} else if (expr is CastExpression) {
return DebugType.CreateFromTypeReference(context.AppDomain, ((CastExpression)expr).CastTo);
return ((CastExpression)expr).CastTo.ResolveType(context.AppDomain);
} else {
return null;
}
@ -372,7 +354,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -372,7 +354,7 @@ namespace ICSharpCode.NRefactory.Visitors
} catch (GetValueException) {
// Static
target = null;
targetType = ResoleType(memberRef.TargetObject);
targetType = memberRef.TargetObject.ResolveType(context.AppDomain);
if (targetType == null)
throw;
}
@ -409,8 +391,11 @@ namespace ICSharpCode.NRefactory.Visitors @@ -409,8 +391,11 @@ namespace ICSharpCode.NRefactory.Visitors
for (int i = 0; i < constructorParameters.Count; i++) {
constructorParameterValues[i] = Evaluate(constructorParameters[i]);
}
return Eval.NewObject(DebugType.CreateFromTypeReference(context.AppDomain, objectCreateExpression.CreateType),
constructorParameterValues, constructorParameterTypes);
return Eval.NewObject(
objectCreateExpression.CreateType.ResolveType(context.AppDomain),
constructorParameterValues,
constructorParameterTypes
);
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
@ -424,7 +409,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -424,7 +409,7 @@ namespace ICSharpCode.NRefactory.Visitors
} catch (GetValueException) {
// Static
target = null;
targetType = ResoleType(memberReferenceExpression.TargetObject);
targetType = memberReferenceExpression.TargetObject.ResolveType(context.AppDomain);
if (targetType == null)
throw;
}

Loading…
Cancel
Save