HRESULT CoalesceExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ HRESULT Status;
+ ToRelease<ICorDebugValue> iCorRealValueRightOp;
+ ToRelease<ICorDebugValue> iCorRightOpValue;
+ CorElementType elemTypeRightOp;
+ IfFailRet(GetFrontStackEntryValue(&iCorRightOpValue, evalStack, ed, output));
+ IfFailRet(GetRealValueWithType(iCorRightOpValue, &iCorRealValueRightOp, &elemTypeRightOp));
+ auto rightOperand = std::move(evalStack.front());
+ evalStack.pop_front();
+
+ ToRelease<ICorDebugValue> iCorRealValueLeftOp;
+ ToRelease<ICorDebugValue> iCorLeftOpValue;
+ CorElementType elemTypeLeftOp;
+ IfFailRet(GetFrontStackEntryValue(&iCorLeftOpValue, evalStack, ed, output));
+ IfFailRet(GetRealValueWithType(iCorLeftOpValue, &iCorRealValueLeftOp, &elemTypeLeftOp));
+ std::string typeNameLeft;
+ std::string typeNameRigth;
+
+ //TODO add implementation for object type ?? other
+ if((elemTypeRightOp == ELEMENT_TYPE_STRING && elemTypeLeftOp == ELEMENT_TYPE_STRING)
+ || ((elemTypeRightOp == ELEMENT_TYPE_CLASS && elemTypeLeftOp == ELEMENT_TYPE_CLASS)
+ && SUCCEEDED(TypePrinter::NameForTypeByValue(iCorRealValueLeftOp, typeNameLeft))
+ && SUCCEEDED(TypePrinter::NameForTypeByValue(iCorRealValueRightOp, typeNameRigth))
+ && typeNameLeft == typeNameRigth))
+ {
+ ToRelease<ICorDebugReferenceValue> pRefValue;
+ IfFailRet(iCorLeftOpValue->QueryInterface(IID_ICorDebugReferenceValue, (LPVOID*) &pRefValue));
+ BOOL isNull = FALSE;
+ IfFailRet(pRefValue->IsNull(&isNull));
+
+ if (isNull == TRUE)
+ {
+ evalStack.pop_front();
+ evalStack.push_front(std::move(rightOperand));
+ }
+ return S_OK;
+ }
+ //TODO add proccesing for parent-child class relationship
+ std::string typeName1;
+ std::string typeName2;
+ IfFailRet(TypePrinter::GetTypeOfValue(iCorRealValueLeftOp, typeName1));
+ IfFailRet(TypePrinter::GetTypeOfValue(iCorRealValueRightOp, typeName2));
+ output = "error CS0019: Operator ?? cannot be applied to operands of type '" + typeName1 + "' and '" + typeName2 + "'";
+ return E_INVALIDARG;
}
HRESULT ThisExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
case SyntaxKind.GreaterThanOrEqualExpression:
case SyntaxKind.LessThanOrEqualExpression:
case SyntaxKind.QualifiedName:
+ case SyntaxKind.CoalesceExpression:
/* TODO
case SyntaxKind.AliasQualifiedName:
case SyntaxKind.SizeOfExpression:
/*
case SyntaxKind.TypeOfExpression:
- case SyntaxKind.CoalesceExpression:
*/
stackMachineProgram.Commands.Add(new NoOperandsCommand(node.Kind(), CurrentScopeFlags.Peek()));
break;
return 10;
}
}
+
+ public class coalesce_test_A
+ {
+ public string A = "A";
+ }
+
+ public class coalesce_test_B
+ {
+ public string B = "B";
+ }
+
public class test_child : test_parent
{
public int i_child = 402;
Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK11");
Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK12");
Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK13");
+ Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK14");
Context.Continue(@"__FILE__:__LINE__");
});
});
int break_line_13 = 13; Label.Breakpoint("BREAK13");
- Label.Checkpoint("function_evaluation_test", "finish", (Object context) => {
+ Label.Checkpoint("function_evaluation_test", "coalesce_test", (Object context) => {
Context Context = (Context)context;
Context.WasBreakpointHit(@"__FILE__:__LINE__", "BREAK13");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "111", "int", "stGetInt()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "666", "int", "stGetInt(333)");
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "getInt()", "Error:");
+ Context.Continue(@"__FILE__:__LINE__");
+ });
+
+ coalesce_test_A test_null = null;
+ coalesce_test_A A_class = new coalesce_test_A();
+ coalesce_test_B B_class = new coalesce_test_B();
+
+ string str_null = null;
+ string A_string = "A";
+ string B_string = "B";
+ string C_string = "C";
+
+ test_struct1_t test_struct = new test_struct1_t();
+ decimal test_decimal = 1;
+ int test_int = 1;
+
+ int break_line14 = 1; Label.Breakpoint("BREAK14");
+ Label.Checkpoint("coalesce_test", "finish", (Object context) => {
+ Context Context = (Context)context;
+ Context.WasBreakpointHit(@"__FILE__:__LINE__", "BREAK14");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"first\\\"", "string", "\\\"first\\\".ToString()??\\\"second\\\".ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.coalesce_test_A}", "MITestEvaluate.coalesce_test_A", "A_class??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.coalesce_test_A}", "MITestEvaluate.coalesce_test_A", "test_null??A_class");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.coalesce_test_A", "test_null??test_null");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.coalesce_test_A}", "MITestEvaluate.coalesce_test_A", "test_null??test_null??A_class");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.coalesce_test_A}", "MITestEvaluate.coalesce_test_A", "A_class??test_null??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.coalesce_test_A}", "MITestEvaluate.coalesce_test_A", "test_null??A_class??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.coalesce_test_A", "test_null??test_null??test_null");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"B\\\"", "string", "str_null??B_string.ToString()??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"C\\\"", "string", "str_null??str_null??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"A\\\"", "string", "A_string.ToString()??str_null??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"A\\\"", "string", "A_string.ToString()??str_null??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"B\\\"", "string", "str_null??B_string.ToString()??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"A\\\"", "string", "A_string.ToString()??B_string.ToString()??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"A\\\"", "string", "A_string.ToString()??B_string.ToString()??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.coalesce_test_A", "test_null??test_null??test_null");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "A_string.ToString()??1", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "A_class??1", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1??A_class", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "A_string.ToString()??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_int??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "A_class??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_int??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_int??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_null??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_int??test_int", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__","A_string.ToString()??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_struct??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__","A_class??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_struct??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_null??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_struct??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_struct??test_struct", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__","A_string.ToString()??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_decimal??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__","A_class??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_decimal??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_null??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_decimal??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_decimal??test_decimal", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__","\\\"first\\\".ToString()??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_decimal??\\\"first\\\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "\\\"first\\\".ToString()??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_int??\\\"first\\\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "\\\"first\\\".ToString()??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_struct??\\\"first\\\".ToString()", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_null??\\\"first\\\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "\\\"first\\\".ToString()??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test_null??str_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "A_class??B_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "B_class??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "B_class??str_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "str_null??B_class", "error CS0019");
Context.Continue(@"__FILE__:__LINE__");
});
}
}
+ public class coalesce_test_A
+ {
+ public string A = "A";
+ }
+ public class coalesce_test_B
+ {
+ public string B = "B";
+ }
+
public class MethodCallTest2
{
public static MethodCallTest1 member1 = new MethodCallTest1();
Context.AddBreakpoint(@"__FILE__:__LINE__", "BREAK11");
Context.AddBreakpoint(@"__FILE__:__LINE__", "BREAK12");
Context.AddBreakpoint(@"__FILE__:__LINE__", "BREAK13");
+ Context.AddBreakpoint(@"__FILE__:__LINE__", "BREAK14");
Context.SetBreakpoints(@"__FILE__:__LINE__");
Context.PrepareEnd(@"__FILE__:__LINE__");
Context.WasEntryPointHit(@"__FILE__:__LINE__");
int break_line13 = 13; Label.Breakpoint("BREAK13");
- Label.Checkpoint("function_evaluation_test", "finish", (Object context) => {
+ Label.Checkpoint("function_evaluation_test", "coalesce_test", (Object context) => {
Context Context = (Context)context;
Context.WasBreakpointHit(@"__FILE__:__LINE__", "BREAK13");
Int64 frameId = Context.DetectFrameId(@"__FILE__:__LINE__", "BREAK13");
Context.Continue(@"__FILE__:__LINE__");
});
+ coalesce_test_A test_null = null;
+ coalesce_test_A A_class = new coalesce_test_A();
+ coalesce_test_B B_class = new coalesce_test_B();
+
+ string str_null = null;
+ string A_string = "A";
+ string B_string = "B";
+ string C_string = "C";
+
+ test_struct1_t test_struct = new test_struct1_t();
+ decimal test_decimal = 1;
+ int test_int = 1;
+
+ int break_line14 = 1; Label.Breakpoint("BREAK14");
+ Label.Checkpoint("coalesce_test", "finish", (Object context) => {
+ Context Context = (Context)context;
+ Context.WasBreakpointHit(@"__FILE__:__LINE__", "BREAK14");
+ Int64 frameId = Context.DetectFrameId(@"__FILE__:__LINE__", "BREAK14");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"first\"", "string", "\"first\".ToString()??\"second\".ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.coalesce_test_A}", "VSCodeTestEvaluate.coalesce_test_A", "A_class??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.coalesce_test_A}", "VSCodeTestEvaluate.coalesce_test_A", "test_null??A_class");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.coalesce_test_A", "test_null??test_null");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.coalesce_test_A}", "VSCodeTestEvaluate.coalesce_test_A", "test_null??test_null??A_class");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.coalesce_test_A}", "VSCodeTestEvaluate.coalesce_test_A", "A_class??test_null??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.coalesce_test_A}", "VSCodeTestEvaluate.coalesce_test_A", "test_null??A_class??test_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.coalesce_test_A", "test_null??test_null??test_null");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"B\"", "string", "str_null??B_string.ToString()??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"C\"", "string", "str_null??str_null??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"A\"", "string", "A_string.ToString()??str_null??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"A\"", "string", "A_string.ToString()??str_null??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"B\"", "string", "str_null??B_string.ToString()??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"A\"", "string", "A_string.ToString()??B_string.ToString()??str_null");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"A\"", "string", "A_string.ToString()??B_string.ToString()??C_string.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.coalesce_test_A", "test_null??test_null??test_null");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_string.ToString()??1", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_class??1", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1??A_class", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_string.ToString()??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_int??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_class??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_int??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_int??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_null??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_int??test_int", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_string.ToString()??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_struct??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_class??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_struct??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_null??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_struct??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_struct??test_struct", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_string.ToString()??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_decimal??A_string.ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_class??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_decimal??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_null??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_decimal??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_decimal??test_decimal", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "\"first\".ToString()??test_decimal", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_decimal??\"first\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "\"first\".ToString()??test_int", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_int??\"first\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "\"first\".ToString()??test_struct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_struct??\"first\".ToString()", "error CS0019");
+
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_null??\"first\".ToString()", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "\"first\".ToString()??test_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test_null??str_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "A_class??B_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "B_class??A_class", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "B_class??str_null", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "str_null??B_class", "error CS0019");
+
+ Context.Continue(@"__FILE__:__LINE__");
+ });
+
Label.Checkpoint("finish", "", (Object context) => {
Context Context = (Context)context;
Context.WasExit(@"__FILE__:__LINE__");