Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit b454359

Browse files
committed
Fix #445: Debug console crash when evaluating some types of expressions in a generic context
1 parent 90a8e0d commit b454359

1 file changed

Lines changed: 34 additions & 12 deletions

File tree

src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,30 @@ public ExpressionEvaluationVisitor(StackFrame context, Thread evalThread, ICompi
8888
this.allowSetValue = allowSetValue;
8989
}
9090

91+
/// <summary>
92+
/// Imports a type into the debugger's type system, and into the current generic context.
93+
/// </summary>
94+
IType Import(IType type)
95+
{
96+
IType importedType = debuggerTypeSystem.Import(type);
97+
if (importedType != null)
98+
return importedType.AcceptVisitor(context.MethodInfo.Substitution);
99+
else
100+
return null;
101+
}
102+
103+
/// <summary>
104+
/// Imports a type into the debugger's type system, and into the current generic context.
105+
/// </summary>
106+
IMember Import(IMember member)
107+
{
108+
IMember importedMember = debuggerTypeSystem.Import(member);
109+
if (importedMember != null)
110+
return importedMember.Specialize(context.MethodInfo.Substitution);
111+
else
112+
return null;
113+
}
114+
91115
public Value Convert(ResolveResult result)
92116
{
93117
if (result.IsCompileTimeConstant && !result.IsError)
@@ -122,7 +146,7 @@ Value Visit(ThisResolveResult result)
122146

123147
Value Visit(MemberResolveResult result)
124148
{
125-
var importedMember = debuggerTypeSystem.Import(result.Member);
149+
var importedMember = Import(result.Member);
126150
if (importedMember == null)
127151
throw new GetValueException("Member not found!");
128152
Value target = null;
@@ -136,7 +160,7 @@ Value Visit(MemberResolveResult result)
136160
}
137161
if (!allowMethodInvoke && (importedMember is IMethod))
138162
throw new InvalidOperationException("Method invocation not allowed in the current context!");
139-
Value val = Value.GetMemberValue(evalThread, target, importedMember.Specialize(context.MethodInfo.Substitution));
163+
Value val = Value.GetMemberValue(evalThread, target, importedMember);
140164
if (val == null)
141165
throw new GetValueException("Member not found!");
142166
return val;
@@ -316,7 +340,7 @@ Value VisitConditionalOperator(OperatorResolveResult result, BinaryOperatorType
316340
/// </remarks>
317341
Value Visit(TypeIsResolveResult result)
318342
{
319-
var importedType = NullableType.GetUnderlyingType(debuggerTypeSystem.Import(result.TargetType));
343+
var importedType = NullableType.GetUnderlyingType(Import(result.TargetType));
320344
var val = Convert(result.Input);
321345
var conversions = CSharpConversions.Get(debuggerTypeSystem);
322346
bool evalResult = false;
@@ -334,7 +358,7 @@ Value Visit(TypeIsResolveResult result)
334358

335359
Value Visit(TypeOfResolveResult result)
336360
{
337-
var type = debuggerTypeSystem.Import(result.ReferencedType);
361+
var type = Import(result.ReferencedType);
338362
if (type == null)
339363
throw new GetValueException("Error: cannot find '{0}'.", result.ReferencedType.FullName);
340364
return Eval.TypeOf(evalThread, type);
@@ -402,19 +426,17 @@ Value Visit(AmbiguousMemberResolveResult result)
402426

403427
Value Visit(InvocationResolveResult result)
404428
{
405-
var importedMember = debuggerTypeSystem.Import(result.Member);
406-
if (importedMember == null)
407-
throw new GetValueException("Member not found!");
429+
// InvokeMethod() will import the member, so work in the original compilation to find the method to invoke:
408430
IMethod usedMethod;
409-
if (importedMember is IProperty) {
410-
var prop = (IProperty)importedMember;
431+
if (result.Member is IProperty) {
432+
var prop = (IProperty)result.Member;
411433
if (!prop.CanGet)
412434
throw new GetValueException("Indexer does not have a getter.");
413435
usedMethod = prop.Getter;
414-
} else if (importedMember is IMethod) {
436+
} else if (result.Member is IMethod) {
415437
if (!allowMethodInvoke)
416438
throw new InvalidOperationException("Method invocation not allowed in the current context!");
417-
usedMethod = (IMethod)importedMember;
439+
usedMethod = (IMethod)result.Member;
418440
} else
419441
throw new GetValueException("Invoked member must be a method or property");
420442
Value target = null;
@@ -430,7 +452,7 @@ Value Visit(NamespaceResolveResult result)
430452

431453
Value InvokeMethod(Value thisValue, IMethod method, params Value[] arguments)
432454
{
433-
method = debuggerTypeSystem.Import(method);
455+
method = Import(method) as IMethod;
434456
if (method == null)
435457
throw new GetValueException("Method not found!");
436458
return Value.InvokeMethod(evalThread, thisValue, method, arguments);

0 commit comments

Comments
 (0)