Browse Source

Support for simple overloading (only applicability is considered)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5151 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
945ae21a7b
  1. 1
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 7
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugMethodInfo.cs
  3. 41
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugPropertyInfo.cs
  4. 153
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugType.cs
  5. 18
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/IOverloadable.cs
  6. 97
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/NRefactory/Visitors/ExpressionEvaluator.cs
  7. 65
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/ExpressionEvaluator_Tests.cs

1
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -96,6 +96,7 @@ @@ -96,6 +96,7 @@
<Compile Include="Src\MetaData\DebugPropertyInfo.cs" />
<Compile Include="Src\MetaData\DebugType.cs" />
<Compile Include="Src\MetaData\IDebugMemberInfo.cs" />
<Compile Include="Src\MetaData\IOverloadable.cs" />
<Compile Include="Src\Module.cs" />
<Compile Include="Src\ModuleCollection.cs" />
<Compile Include="Src\Mono.Cecil\Mono.Cecil.Binary\ImageFormatException.cs" />

7
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugMethodInfo.cs

@ -19,7 +19,7 @@ using Mono.Cecil.Signatures; @@ -19,7 +19,7 @@ using Mono.Cecil.Signatures;
namespace Debugger.MetaData
{
public class DebugMethodInfo: System.Reflection.MethodInfo, IDebugMemberInfo
public class DebugMethodInfo: System.Reflection.MethodInfo, IDebugMemberInfo, IOverloadable
{
DebugType declaringType;
MethodProps methodProps;
@ -624,5 +624,10 @@ namespace Debugger.MetaData @@ -624,5 +624,10 @@ namespace Debugger.MetaData
txt += this.FullName;
return txt;
}
IntPtr IOverloadable.GetSignarture()
{
return methodProps.SigBlob.Adress;
}
}
}

41
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/DebugPropertyInfo.cs

@ -9,10 +9,11 @@ using System; @@ -9,10 +9,11 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
namespace Debugger.MetaData
{
public class DebugPropertyInfo : System.Reflection.PropertyInfo, IDebugMemberInfo
public class DebugPropertyInfo : System.Reflection.PropertyInfo, IDebugMemberInfo, IOverloadable
{
DebugType declaringType;
MethodInfo getMethod;
@ -132,9 +133,14 @@ namespace Debugger.MetaData @@ -132,9 +133,14 @@ namespace Debugger.MetaData
{
if (GetGetMethod() != null) {
return GetGetMethod().GetParameters();
} else {
return null;
}
if (GetSetMethod() != null) {
List<ParameterInfo> pars = new List<ParameterInfo>();
pars.AddRange(GetSetMethod().GetParameters());
pars.RemoveAt(pars.Count - 1);
return pars.ToArray();
}
return null;
}
// public virtual Type[] GetOptionalCustomModifiers();
@ -190,7 +196,34 @@ namespace Debugger.MetaData @@ -190,7 +196,34 @@ namespace Debugger.MetaData
/// <inheritdoc/>
public override string ToString()
{
return this.PropertyType + " " + this.Name;
StringBuilder sb = new StringBuilder();
sb.Append(this.PropertyType);
sb.Append(" ");
sb.Append(this.Name);
if (GetIndexParameters().Length > 0) {
sb.Append("[");
bool first = true;
foreach(DebugParameterInfo p in GetIndexParameters()) {
if (!first)
sb.Append(", ");
first = false;
sb.Append(p.ParameterType.Name);
sb.Append(" ");
sb.Append(p.Name);
}
sb.Append("]");
}
return sb.ToString();
}
ParameterInfo[] IOverloadable.GetParameters()
{
return GetIndexParameters();
}
IntPtr IOverloadable.GetSignarture()
{
return ((IOverloadable)(getMethod ?? setMethod)).GetSignarture();
}
}
}

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

@ -253,7 +253,7 @@ namespace Debugger.MetaData @@ -253,7 +253,7 @@ namespace Debugger.MetaData
return elementType;
}
const BindingFlags supportedFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy;
const BindingFlags SupportedFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy;
/// <summary> Return member with the given token</summary>
public MemberInfo GetMember(uint token)
@ -273,7 +273,7 @@ namespace Debugger.MetaData @@ -273,7 +273,7 @@ namespace Debugger.MetaData
public T[] GetMembers<T>(string name, BindingFlags bindingFlags, Predicate<T> filter) where T:MemberInfo
{
BindingFlags unsupported = bindingFlags & ~supportedFlags;
BindingFlags unsupported = bindingFlags & ~SupportedFlags;
if (unsupported != 0)
throw new NotSupportedException("BindingFlags: " + unsupported);
@ -333,6 +333,111 @@ namespace Debugger.MetaData @@ -333,6 +333,111 @@ namespace Debugger.MetaData
return results.ToArray();
}
MemberInfo SelectOverload(MemberInfo[] candidates, Type[] argumentTypes)
{
if (candidates.Length == 0)
return null;
List<MemberInfo> applicable = new List<MemberInfo>();
foreach(MemberInfo candidate in candidates) {
bool isExactMatch;
if (IsApplicable(((IOverloadable)candidate).GetParameters(), argumentTypes, out isExactMatch))
applicable.Add(candidate);
if (isExactMatch)
return candidate;
}
if (applicable.Count == 0) {
if (candidates.Length == 1) {
throw new GetValueException("Incorrect parameter types");
} else {
throw new GetValueException("No applicable overload found");
}
} else if (applicable.Count == 1) {
return applicable[0];
} else {
// Remove base class definitions
IntPtr sig = ((IOverloadable)applicable[0]).GetSignarture();
for(int i = 1; i < applicable.Count;) {
if (sig == ((IOverloadable)applicable[i]).GetSignarture()) {
applicable.RemoveAt(i);
} else {
i++;
}
}
if (applicable.Count == 1)
return applicable[0];
StringBuilder overloads = new StringBuilder();
foreach(MemberInfo app in applicable) {
overloads.Append(Environment.NewLine);
overloads.Append(" ");
overloads.Append(app.ToString());
}
throw new GetValueException("More then one applicable overload found:" + overloads.ToString());
}
}
bool IsApplicable(ParameterInfo[] parameters, Type[] argumentTypes, out bool isExactMatch)
{
isExactMatch = false;
if (argumentTypes == null)
return true;
if (argumentTypes.Length != parameters.Length)
return false;
isExactMatch = true;
for(int i = 0; i < parameters.Length; i++) {
if (argumentTypes[i] != parameters[i].ParameterType) {
isExactMatch = false;
if (!CanImplicitelyConvert(argumentTypes[i], parameters[i].ParameterType))
return false;
}
}
return true;
}
static string Byte = typeof(byte).FullName;
static string Short = typeof(short).FullName;
static string Int = typeof(int).FullName;
static string Long = typeof(long).FullName;
static string SByte = typeof(sbyte).FullName;
static string UShort = typeof(ushort).FullName;
static string UInt = typeof(uint).FullName;
static string ULong = typeof(ulong).FullName;
static string Float = typeof(float).FullName;
static string Double = typeof(double).FullName;
static string Char = typeof(char).FullName;
static string Decimal = typeof(decimal).FullName;
bool CanImplicitelyConvert(Type fromType, Type toType)
{
if (fromType == toType)
return true;
if (fromType.IsPrimitive && toType.IsPrimitive) {
string f = fromType.FullName;
string t = toType.FullName;
if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
return true;
if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
return true;
if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
return true;
if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
return true;
if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
return true;
if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
return true;
if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
return true;
if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
return true;
if (f == Float && t == Double)
return true;
return false;
} else {
return toType.IsAssignableFrom(fromType);
}
}
/// <inheritdoc/>
public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
{
@ -440,21 +545,15 @@ namespace Debugger.MetaData @@ -440,21 +545,15 @@ namespace Debugger.MetaData
/// <inheritdoc/>
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] paramTypes, ParameterModifier[] modifiers)
{
// TODO: Finish
foreach(DebugMethodInfo candidate in GetMethods(name, bindingAttr)) {
if (paramTypes == null)
return candidate;
if (candidate.ParameterCount == paramTypes.Length) {
bool match = true;
for(int i = 0; i < paramTypes.Length; i++) {
if (paramTypes[i] != candidate.GetParameters()[i].ParameterType)
match = false;
}
if (match)
return candidate;
}
}
return null;
if (binder != null)
throw new NotSupportedException("binder");
if (callConvention != CallingConventions.Any)
throw new NotSupportedException("callConvention");
if (modifiers != null)
throw new NotSupportedException("modifiers");
MethodInfo[] candidates = GetMethods(name, bindingAttr);
return (MethodInfo)SelectOverload(candidates, paramTypes);
}
public MethodInfo[] GetMethods(string name, BindingFlags bindingAttr)
@ -493,6 +592,11 @@ namespace Debugger.MetaData @@ -493,6 +592,11 @@ namespace Debugger.MetaData
});
}
public PropertyInfo[] GetProperties(string name, BindingFlags bindingAttr)
{
return GetMembers<PropertyInfo>(name, bindingAttr, null);
}
/// <inheritdoc/>
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
@ -500,10 +604,17 @@ namespace Debugger.MetaData @@ -500,10 +604,17 @@ namespace Debugger.MetaData
}
/// <inheritdoc/>
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
// TODO: Finsih
return GetMember<PropertyInfo>(name, bindingAttr, null);
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] paramTypes, ParameterModifier[] modifiers)
{
if (binder != null)
throw new NotSupportedException("binder");
if (returnType != null)
throw new NotSupportedException("returnType");
if (modifiers != null)
throw new NotSupportedException("modifiers");
PropertyInfo[] candidates = GetProperties(name, bindingAttr);
return (PropertyInfo)SelectOverload(candidates, paramTypes);
}
/// <inheritdoc/>

18
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/MetaData/IOverloadable.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Reflection;
namespace Debugger.MetaData
{
interface IOverloadable
{
ParameterInfo[] GetParameters();
IntPtr GetSignarture();
}
}

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

@ -173,6 +173,41 @@ namespace ICSharpCode.NRefactory.Visitors @@ -173,6 +173,41 @@ 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);
} else {
return null;
}
}
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
{
BinaryOperatorType op;
@ -243,17 +278,6 @@ namespace ICSharpCode.NRefactory.Visitors @@ -243,17 +278,6 @@ namespace ICSharpCode.NRefactory.Visitors
return Evaluate(castExpression.Expression);
}
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);
} else {
return null;
}
}
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
string identifier = identifierExpression.Identifier;
@ -318,33 +342,20 @@ namespace ICSharpCode.NRefactory.Visitors @@ -318,33 +342,20 @@ namespace ICSharpCode.NRefactory.Visitors
}
}
DebugPropertyInfo pi = (DebugPropertyInfo)target.Type.GetProperty("Item");
Type[] indexerTypes = GetTypes(indexerExpression.Indexes);
DebugPropertyInfo pi = (DebugPropertyInfo)target.Type.GetProperty("Item", indexerTypes);
if (pi == null) throw new GetValueException("The object does not have an indexer property");
return target.GetPropertyValue(pi, indexes.ToArray());
}
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)
Type[] GetTypes(List<Expression> args)
{
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;
List<DebugType> argTypes = new List<DebugType>();
foreach(Expression arg in args) {
DebugType argType = GetDebugType(arg) ?? Evaluate(arg).Type;
argTypes.Add(argType);
}
return argTypes.ToArray();
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
@ -376,26 +387,10 @@ namespace ICSharpCode.NRefactory.Visitors @@ -376,26 +387,10 @@ namespace ICSharpCode.NRefactory.Visitors
throw new GetValueException("Member reference expected for method invocation");
}
}
MethodInfo method;
IList<MemberInfo> methods = targetType.GetMember(methodName, MemberTypes.Method, BindingFlagsAllDeclared);
if (methods.Count == 0)
methods = targetType.GetMember(methodName, MemberTypes.Method, BindingFlagsAll);
if (methods.Count == 0) {
Type[] argTypes = GetTypes(invocationExpression.Arguments);
MethodInfo method = targetType.GetMethod(methodName, BindingFlagsAll, null, argTypes, null);
if (method == null)
throw new GetValueException("Method " + methodName + " not found");
} else if (methods.Count == 1) {
method = (MethodInfo)methods[0];
} else {
List<DebugType> argTypes = new List<DebugType>();
foreach(Expression expr in invocationExpression.Arguments) {
DebugType argType = GetDebugType(expr);
if (argType == null)
argType = Evaluate(expr).Type;
argTypes.Add(argType);
}
method = targetType.GetMethod(methodName, argTypes.ToArray());
if (method == null)
throw new GetValueException("Can not find overload with given types");
}
List<Value> args = new List<Value>();
foreach(Expression expr in invocationExpression.Arguments) {
args.Add(Evaluate(expr));

65
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/Tests/ExpressionEvaluator_Tests.cs

@ -26,6 +26,17 @@ namespace Debugger.Tests @@ -26,6 +26,17 @@ namespace Debugger.Tests
{
return "base Foo - int";
}
public string Foo(double d)
{
return "base Foo - double";
}
public string this[long i] {
get {
return "base indexer - long";
}
}
}
public class DerivedClass: BaseClass
@ -55,6 +66,11 @@ namespace Debugger.Tests @@ -55,6 +66,11 @@ namespace Debugger.Tests
return "static method";
}
public string Foo(object o)
{
return "derived Foo - object";
}
new public string Foo(int i)
{
return "derived Foo - int";
@ -64,6 +80,23 @@ namespace Debugger.Tests @@ -64,6 +80,23 @@ namespace Debugger.Tests
{
return "derived Foo - string";
}
public string this[double d] {
get {
return "derived indexer - double";
}
}
public string this[string s] {
get {
return "derived indexer - string";
}
}
public string Convert(string s, double d)
{
return "converted to " + s + " and " + d;
}
}
public enum MyEnum { A = 3, B = 6 };
@ -188,6 +221,23 @@ namespace Debugger.Tests { @@ -188,6 +221,23 @@ namespace Debugger.Tests {
Eval(expr.PrettyPrint());
}
string input2 = @"
myClass.Foo(1.0)
myClass.Foo(myClass)
myClass.Foo(1)
myClass.Foo('abc')
myClass[1]
myClass[(long)1]
myClass[1.0]
myClass['abc']
myClass.Convert(1,2)
";
input2 = input2.Replace("'", "\"");
foreach(string line in input2.Split('\n')) {
Eval(line.Trim());
}
EndTest();
}
@ -222,7 +272,7 @@ namespace Debugger.Tests { @@ -222,7 +272,7 @@ namespace Debugger.Tests {
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>ExpressionEvaluator_Tests.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:94,4-94,40</DebuggingPaused>
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:127,4-127,40</DebuggingPaused>
<Eval> </Eval>
<Eval> b = 1 </Eval>
<Eval> i = 4 </Eval>
@ -290,6 +340,19 @@ namespace Debugger.Tests { @@ -290,6 +340,19 @@ namespace Debugger.Tests {
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Foo((System.Int32)1) = "base Foo - int" </Eval>
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).Foo((System.Int32)1) = "derived Foo - int" </Eval>
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).Foo((System.String)"a") = "derived Foo - string" </Eval>
<Eval> </Eval>
<Eval> myClass.Foo(1.0) = "base Foo - double" </Eval>
<Eval> myClass.Foo(myClass) = "derived Foo - object" </Eval>
<Eval> myClass.Foo(1) = "derived Foo - int" </Eval>
<Eval> myClass.Foo("abc") = "derived Foo - string" </Eval>
<Eval> myClass[1] = Error evaluating "myClass[1]": More then one applicable overload found:
System.String Item[Double d]
System.String Item[Int64 i] </Eval>
<Eval> myClass[(long)1] = "base indexer - long" </Eval>
<Eval> myClass[1.0] = "derived indexer - double" </Eval>
<Eval> myClass["abc"] = "derived indexer - string" </Eval>
<Eval> myClass.Convert(1,2) = Error evaluating "myClass.Convert(1, 2)": Incorrect parameter types </Eval>
<Eval> </Eval>
<ProcessExited />
</Test>
</DebuggerTests>

Loading…
Cancel
Save