From: a-shaurtaev Date: Mon, 18 Oct 2021 12:41:44 +0000 (+0300) Subject: Add coalesce operator X-Git-Tag: submit/tizen/20220215.173642~25 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a228f99064e4846f21fa2154e5a727b5bb006e89;p=sdk%2Ftools%2Fnetcoredbg.git Add coalesce operator --- diff --git a/src/debugger/evalstackmachine.cpp b/src/debugger/evalstackmachine.cpp index b545561..44678c7 100644 --- a/src/debugger/evalstackmachine.cpp +++ b/src/debugger/evalstackmachine.cpp @@ -1642,8 +1642,49 @@ namespace HRESULT CoalesceExpression(std::list &evalStack, PVOID pArguments, std::string &output, EvalData &ed) { - // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags; - return E_NOTIMPL; + HRESULT Status; + ToRelease iCorRealValueRightOp; + ToRelease iCorRightOpValue; + CorElementType elemTypeRightOp; + IfFailRet(GetFrontStackEntryValue(&iCorRightOpValue, evalStack, ed, output)); + IfFailRet(GetRealValueWithType(iCorRightOpValue, &iCorRealValueRightOp, &elemTypeRightOp)); + auto rightOperand = std::move(evalStack.front()); + evalStack.pop_front(); + + ToRelease iCorRealValueLeftOp; + ToRelease 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 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 &evalStack, PVOID pArguments, std::string &output, EvalData &ed) diff --git a/src/managed/StackMachine.cs b/src/managed/StackMachine.cs index 93a851b..4bb451a 100644 --- a/src/managed/StackMachine.cs +++ b/src/managed/StackMachine.cs @@ -706,6 +706,7 @@ namespace NetCoreDbg case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.QualifiedName: + case SyntaxKind.CoalesceExpression: /* TODO case SyntaxKind.AliasQualifiedName: @@ -722,7 +723,6 @@ namespace NetCoreDbg case SyntaxKind.SizeOfExpression: /* case SyntaxKind.TypeOfExpression: - case SyntaxKind.CoalesceExpression: */ stackMachineProgram.Commands.Add(new NoOperandsCommand(node.Kind(), CurrentScopeFlags.Peek())); break; diff --git a/test-suite/MITestEvaluate/Program.cs b/test-suite/MITestEvaluate/Program.cs index 88c23ed..6fde622 100644 --- a/test-suite/MITestEvaluate/Program.cs +++ b/test-suite/MITestEvaluate/Program.cs @@ -475,6 +475,17 @@ namespace MITestEvaluate 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; @@ -687,6 +698,7 @@ namespace MITestEvaluate Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK11"); Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK12"); Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK13"); + Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK14"); Context.Continue(@"__FILE__:__LINE__"); }); @@ -1385,13 +1397,96 @@ namespace MITestEvaluate }); 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__"); }); diff --git a/test-suite/VSCodeTestEvaluate/Program.cs b/test-suite/VSCodeTestEvaluate/Program.cs index bdd3d57..24bba8a 100644 --- a/test-suite/VSCodeTestEvaluate/Program.cs +++ b/test-suite/VSCodeTestEvaluate/Program.cs @@ -645,6 +645,15 @@ namespace VSCodeTestEvaluate } } + 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(); @@ -805,6 +814,7 @@ namespace VSCodeTestEvaluate 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__"); @@ -1509,7 +1519,7 @@ namespace VSCodeTestEvaluate 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"); @@ -1521,6 +1531,91 @@ namespace VSCodeTestEvaluate 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__");