Fix work with managed code in unmapped addresses.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Fri, 19 Jan 2024 14:20:18 +0000 (17:20 +0300)
committerGleb Balykov/Advanced System SW Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com>
Thu, 25 Jan 2024 09:54:41 +0000 (12:54 +0300)
* Fix stepping for `using` statement.
* Fix stepping for `finally` block.
* Fix stack trace for `finally` block.

Related to https://github.com/Samsung/netcoredbg/issues/154

src/debugger/breakpoint_break.cpp
src/debugger/frames.cpp
src/debugger/stepper_async.cpp
src/debugger/steppers.cpp
src/debugger/steppers.h
src/metadata/modules.cpp
test-suite/MITestNoJMCNoFilterStepping/Program.cs
test-suite/MITestStepping/Program.cs
test-suite/VSCodeTestNoJMCNoFilterStepping/Program.cs
test-suite/VSCodeTestStepping/Program.cs

index 121e39c037d6b6536af6d83912b5e14e60d37380..00e4de360065e38a6764a80e2845a9f08c8fb767 100644 (file)
@@ -41,6 +41,9 @@ HRESULT BreakBreakpoint::GetFullyQualifiedIlOffset(ICorDebugThread *pThread, Ful
     ULONG32 ilOffset;\r
     CorDebugMappingResult mappingResult;\r
     IfFailRet(pILFrame->GetIP(&ilOffset, &mappingResult));\r
+    if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||\r
+        mappingResult == MAPPING_NO_INFO)\r
+        return E_FAIL;\r
 \r
     fullyQualifiedIlOffset.modAddress = modAddress;\r
     fullyQualifiedIlOffset.methodToken = methodToken;\r
index ca0164dfb71ca5365bb58b3e7d37be0112285f54..0f1e4eb735d28533afffc72e0e4e801a2d9be565 100644 (file)
@@ -332,6 +332,16 @@ HRESULT WalkFrames(ICorDebugThread *pThread, WalkFramesCallback cb)
                 return Status;
 #endif // INTEROP_DEBUGGING
 
+            ToRelease<ICorDebugILFrame> pILFrame;
+            IfFailRet(iCorFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame));
+
+            ULONG32 nOffset;
+            CorDebugMappingResult mappingResult;
+            IfFailRet(pILFrame->GetIP(&nOffset, &mappingResult));
+            if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||
+                mappingResult == MAPPING_NO_INFO)
+                continue;
+
             IfFailRet(cb(FrameCLRManaged, GetIP(&currentCtx), iCorFrame, nullptr));
             continue;
         }
index 580f5ce5f71a726c13d4a7b0709150686e5c2160..477425e3e012324703e15246bfeb1ddd16b67fbd 100644 (file)
@@ -268,6 +268,9 @@ HRESULT AsyncStepper::SetupStep(ICorDebugThread *pThread, IDebugger::StepType st
     ULONG32 ipOffset;\r
     CorDebugMappingResult mappingResult;\r
     IfFailRet(pILFrame->GetIP(&ipOffset, &mappingResult));\r
+    if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||\r
+        mappingResult == MAPPING_NO_INFO)\r
+        return E_FAIL;\r
 \r
     // If we are at end of async method with await blocks and doing step-in or step-over,\r
     // switch to step-out, so whole NotifyDebuggerOfWaitCompletion magic happens.\r
@@ -446,7 +449,9 @@ HRESULT AsyncStepper::ManagedCallbackBreakpoint(ICorDebugThread *pThread)
     ULONG32 ipOffset;\r
     CorDebugMappingResult mappingResult;\r
     if (FAILED(pFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame)) ||\r
-        FAILED(pILFrame->GetIP(&ipOffset, &mappingResult)))\r
+        FAILED(pILFrame->GetIP(&ipOffset, &mappingResult)) ||\r
+        mappingResult == MAPPING_UNMAPPED_ADDRESS ||\r
+        mappingResult == MAPPING_NO_INFO)\r
     {\r
         LOGE("Failed receive current IP offset for async step");\r
         return S_FALSE;\r
index 6395c8e7d0c746a7a7a37bb273331e575db39a17..832026e0208f7a22c244acfe27a7d70c49b77c52 100644 (file)
@@ -71,11 +71,20 @@ HRESULT Steppers::SetupStep(ICorDebugThread *pThread, IDebugger::StepType stepTy
 {\r
     HRESULT Status;\r
     m_filteredPrevStep = false;\r
+    m_initialStepType = stepType;\r
 \r
     ToRelease<ICorDebugProcess> pProcess;\r
     IfFailRet(pThread->GetProcess(&pProcess));\r
     DisableAllSteppers(pProcess);\r
 \r
+    ToRelease<ICorDebugFrame> pFrame;\r
+    IfFailRet(pThread->GetActiveFrame(&pFrame));\r
+    if (pFrame == nullptr)\r
+        return E_FAIL;\r
+\r
+    ULONG32 ilOffset;\r
+    IfFailRet(m_sharedModules->GetFrameILAndSequencePoint(pFrame, ilOffset, m_StepStartSP));\r
+\r
     IfFailRet(m_asyncStepper->SetupStep(pThread, stepType));\r
     if (Status == S_OK) // S_FALSE = setup simple stepper\r
         return S_OK;\r
@@ -175,8 +184,34 @@ HRESULT Steppers::ManagedCallbackStepComplete(ICorDebugThread *pThread, CorDebug
     bool noUserCodeFound = false; // Must be initialized with `false`, since GetFrameILAndNextUserCodeILOffset call could be failed before delegate call.\r
     if (SUCCEEDED(Status = m_sharedModules->GetFrameILAndNextUserCodeILOffset(iCorFrame, ipOffset, ilNextUserCodeOffset, &noUserCodeFound)))\r
     {\r
+        if (reason == CorDebugStepReason::STEP_NORMAL)\r
+        {\r
+            if (ipOffset != ilNextUserCodeOffset)\r
+            {\r
+                // Step completed on some compiler generated (not user) code inside user code (for example, `finally` block related code)\r
+                IfFailRet(m_simpleStepper->SetupStep(pThread, m_initialStepType));\r
+                return S_OK;\r
+            }\r
+            else\r
+            {\r
+                // Step completed on same location in source as it was started, this happens when some user code block have several\r
+                // SequencePoints for same line (for example, `using` related code could mix user/compiler generated code for same line).\r
+                ULONG32 ilOffset;\r
+                Modules::SequencePoint sp;\r
+                IfFailRet(m_sharedModules->GetFrameILAndSequencePoint(iCorFrame, ilOffset, sp));\r
+                if (sp.startLine == m_StepStartSP.startLine &&\r
+                    sp.startColumn == m_StepStartSP.startColumn &&\r
+                    sp.endLine == m_StepStartSP.endLine &&\r
+                    sp.endColumn == m_StepStartSP.endColumn &&\r
+                    sp.document == m_StepStartSP.document)\r
+                {\r
+                    IfFailRet(m_simpleStepper->SetupStep(pThread, m_initialStepType));\r
+                    return S_OK;\r
+                }\r
+            }\r
+        }\r
         // Current IL offset less than IL offset of next close user code line (for example, step-in into async method)\r
-        if (reason == CorDebugStepReason::STEP_CALL && ipOffset < ilNextUserCodeOffset)\r
+        else if (reason == CorDebugStepReason::STEP_CALL && ipOffset < ilNextUserCodeOffset)\r
         {\r
             IfFailRet(m_simpleStepper->SetupStep(pThread, IDebugger::StepType::STEP_OVER));\r
             return S_OK;\r
@@ -190,7 +225,7 @@ HRESULT Steppers::ManagedCallbackStepComplete(ICorDebugThread *pThread, CorDebug
     }\r
     else if (noUserCodeFound)\r
     {\r
-        IfFailRet(m_simpleStepper->SetupStep(pThread, IDebugger::StepType::STEP_IN));\r
+        IfFailRet(m_simpleStepper->SetupStep(pThread, m_initialStepType));\r
         // In case step-in will return from method and no user code was called in user module, step-in again.\r
         m_filteredPrevStep = true;\r
         return S_OK;\r
index adc0eef042d667e54511ebd7c9f484f064c05f10..68d1a9cbdb131ce95dc07ff692dd948ee42f9012 100644 (file)
@@ -25,6 +25,7 @@ public:
         m_simpleStepper(new SimpleStepper(sharedModules)),\r
         m_asyncStepper(new AsyncStepper(m_simpleStepper, sharedModules, sharedEvalHelpers)),\r
         m_sharedModules(sharedModules),\r
+        m_initialStepType(IDebugger::StepType::STEP_OVER),\r
         m_justMyCode(true),\r
         m_stepFiltering(true),\r
         m_filteredPrevStep(false)\r
@@ -54,6 +55,8 @@ private:
     std::shared_ptr<SimpleStepper> m_simpleStepper;\r
     std::unique_ptr<AsyncStepper> m_asyncStepper;\r
     std::shared_ptr<Modules> m_sharedModules;\r
+    IDebugger::StepType m_initialStepType;\r
+    Modules::SequencePoint m_StepStartSP;\r
     bool m_justMyCode;\r
     // https://docs.microsoft.com/en-us/visualstudio/debugger/navigating-through-code-with-the-debugger?view=vs-2019#BKMK_Step_into_properties_and_operators_in_managed_code\r
     // The debugger steps over properties and operators in managed code by default. In most cases, this provides a better debugging experience.\r
index bd8f227569b92bae34eb0ae83fcb915cf322c6ed..7ec0e2ea1e5bfce4c763422d764e42302c4d8d8a 100644 (file)
@@ -329,6 +329,9 @@ HRESULT Modules::GetFrameILAndSequencePoint(
 
     CorDebugMappingResult mappingResult;
     IfFailRet(pILFrame->GetIP(&ilOffset, &mappingResult));
+    if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||
+        mappingResult == MAPPING_NO_INFO)
+        return E_FAIL;
 
     ToRelease<ICorDebugModule> pModule;
     IfFailRet(pFunc->GetModule(&pModule));
@@ -376,6 +379,9 @@ HRESULT Modules::GetFrameILAndNextUserCodeILOffset(
 
     CorDebugMappingResult mappingResult;
     IfFailRet(pILFrame->GetIP(&ilOffset, &mappingResult));
+    if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||
+        mappingResult == MAPPING_NO_INFO)
+        return E_FAIL;
 
     ToRelease<ICorDebugModule> pModule;
     IfFailRet(pFunc->GetModule(&pModule));
@@ -411,6 +417,9 @@ HRESULT Modules::GetStepRangeFromCurrentIP(ICorDebugThread *pThread, COR_DEBUG_S
     ULONG32 nOffset;
     CorDebugMappingResult mappingResult;
     IfFailRet(pILFrame->GetIP(&nOffset, &mappingResult));
+    if (mappingResult == MAPPING_UNMAPPED_ADDRESS ||
+        mappingResult == MAPPING_NO_INFO)
+        return E_FAIL;
 
     CORDB_ADDRESS modAddress;
     IfFailRet(pModule->GetBaseAddress(&modAddress));
index 34bc1f73287040b10a5e83484499a617843ddcfd..127cc9ae5ab143e607f37cc9792374524a5871c8 100644 (file)
@@ -261,6 +261,31 @@ namespace MITestNoJMCNoFilterStepping
         }\r
     }\r
 \r
+    class TestStepWithCompilerGenCode : IDisposable\r
+    {\r
+        public void Dispose()\r
+        {                                                                   Label.Breakpoint("test_step_comp_Dispose_1");\r
+            ;                                                               Label.Breakpoint("test_step_comp_Dispose_2");\r
+        Label.Breakpoint("test_step_comp_Dispose_3");}\r
+\r
+        public static void M()\r
+        {                                                                   Label.Breakpoint("test_step_comp_M_1");\r
+            Label.Breakpoint("test_step_comp_M_2");using (var c = new TestStepWithCompilerGenCode())\r
+            {                                                               Label.Breakpoint("test_step_comp_M_3");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_4");\r
+            Label.Breakpoint("test_step_comp_M_5");}\r
+            using var c2 = new TestStepWithCompilerGenCode();               Label.Breakpoint("test_step_comp_M_6");\r
+            try\r
+            {                                                               Label.Breakpoint("test_step_comp_M_7");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_8");\r
+            Label.Breakpoint("test_step_comp_M_9");}\r
+            finally\r
+            {                                                               Label.Breakpoint("test_step_comp_M_10");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_11");\r
+            Label.Breakpoint("test_step_comp_M_12");}\r
+        Label.Breakpoint("test_step_comp_M_13");}\r
+    }\r
+\r
     class Program\r
     {\r
         static void Main(string[] args)\r
@@ -493,7 +518,7 @@ namespace MITestNoJMCNoFilterStepping
             C.M3(C.M6(), C.M6());                                           Label.Breakpoint("test_step_arguments_6");\r
             Console.WriteLine("Test steps for arguments end.");             Label.Breakpoint("test_step_arguments_end");\r
 \r
-            Label.Checkpoint("test_step_arguments", "finish", (Object context) => {\r
+            Label.Checkpoint("test_step_arguments", "test_step_comp", (Object context) => {\r
                 Context Context = (Context)context;\r
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_1");\r
                 Context.StepOver(@"__FILE__:__LINE__");\r
@@ -618,6 +643,96 @@ namespace MITestNoJMCNoFilterStepping
                 Context.StepIn(@"__FILE__:__LINE__");\r
 \r
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_end");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            // Test step-in/step-over for compiler generated code inside user code.\r
+\r
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_1");\r
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_2");\r
+            Console.WriteLine("Test steps end.");                           Label.Breakpoint("test_step_comp_end");\r
+\r
+            Label.Checkpoint("test_step_comp", "finish", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_end");\r
                 Context.StepOut(@"__FILE__:__LINE__");\r
             });\r
 \r
index 67ee7e1c9219964540387637c8822ea3345884ed..9c20328c61ce7e5c251e8506578d47fa4bb3834b 100644 (file)
@@ -292,6 +292,31 @@ namespace MITestStepping
         }
     }
 
+    class TestStepWithCompilerGenCode : IDisposable
+    {
+        public void Dispose()
+        {                                                                   Label.Breakpoint("test_step_comp_Dispose_1");
+            ;                                                               Label.Breakpoint("test_step_comp_Dispose_2");
+        Label.Breakpoint("test_step_comp_Dispose_3");}
+
+        public static void M()
+        {                                                                   Label.Breakpoint("test_step_comp_M_1");
+            Label.Breakpoint("test_step_comp_M_2");using (var c = new TestStepWithCompilerGenCode())
+            {                                                               Label.Breakpoint("test_step_comp_M_3");
+                ;                                                           Label.Breakpoint("test_step_comp_M_4");
+            Label.Breakpoint("test_step_comp_M_5");}
+            using var c2 = new TestStepWithCompilerGenCode();               Label.Breakpoint("test_step_comp_M_6");
+            try
+            {                                                               Label.Breakpoint("test_step_comp_M_7");
+                ;                                                           Label.Breakpoint("test_step_comp_M_8");
+            Label.Breakpoint("test_step_comp_M_9");}
+            finally
+            {                                                               Label.Breakpoint("test_step_comp_M_10");
+                ;                                                           Label.Breakpoint("test_step_comp_M_11");
+            Label.Breakpoint("test_step_comp_M_12");}
+        Label.Breakpoint("test_step_comp_M_13");}
+    }
+
     class Program
     {
         static void Main(string[] args)
@@ -504,7 +529,7 @@ namespace MITestStepping
             C.M3(C.M6(), C.M6());                                           Label.Breakpoint("test_step_arguments_6");
             Console.WriteLine("Test steps for arguments end.");             Label.Breakpoint("test_step_arguments_end");
 
-            Label.Checkpoint("test_step_arguments", "finish", (Object context) => {
+            Label.Checkpoint("test_step_arguments", "test_step_comp", (Object context) => {
                 Context Context = (Context)context;
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_1");
                 Context.StepOver(@"__FILE__:__LINE__");
@@ -597,6 +622,96 @@ namespace MITestStepping
                 Context.StepIn(@"__FILE__:__LINE__");
 
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_end");
+                Context.StepOver(@"__FILE__:__LINE__");
+            });
+
+            // Test step-in/step-over for compiler generated code inside user code.
+
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_1");
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_2");
+            Console.WriteLine("Test steps end.");                           Label.Breakpoint("test_step_comp_end");
+
+            Label.Checkpoint("test_step_comp", "finish", (Object context) => {
+                Context Context = (Context)context;
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");
+                Context.StepOver(@"__FILE__:__LINE__");
+
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");
+                Context.StepOver(@"__FILE__:__LINE__");
+
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_end");
                 Context.StepOut(@"__FILE__:__LINE__");
             });
 
index 9c953e957713f4055c2d08f9e025bd20508879f1..cf62858fd781e1ef6dc9188a96deed9ea906e2ec 100644 (file)
@@ -318,6 +318,31 @@ namespace VSCodeTestNoJMCNoFilterStepping
         }\r
     }\r
 \r
+    class TestStepWithCompilerGenCode : IDisposable\r
+    {\r
+        public void Dispose()\r
+        {                                                                   Label.Breakpoint("test_step_comp_Dispose_1");\r
+            ;                                                               Label.Breakpoint("test_step_comp_Dispose_2");\r
+        Label.Breakpoint("test_step_comp_Dispose_3");}\r
+\r
+        public static void M()\r
+        {                                                                   Label.Breakpoint("test_step_comp_M_1");\r
+            Label.Breakpoint("test_step_comp_M_2");using (var c = new TestStepWithCompilerGenCode())\r
+            {                                                               Label.Breakpoint("test_step_comp_M_3");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_4");\r
+            Label.Breakpoint("test_step_comp_M_5");}\r
+            using var c2 = new TestStepWithCompilerGenCode();               Label.Breakpoint("test_step_comp_M_6");\r
+            try\r
+            {                                                               Label.Breakpoint("test_step_comp_M_7");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_8");\r
+            Label.Breakpoint("test_step_comp_M_9");}\r
+            finally\r
+            {                                                               Label.Breakpoint("test_step_comp_M_10");\r
+                ;                                                           Label.Breakpoint("test_step_comp_M_11");\r
+            Label.Breakpoint("test_step_comp_M_12");}\r
+        Label.Breakpoint("test_step_comp_M_13");}\r
+    }\r
+\r
     class Program\r
     {\r
         static void Main(string[] args)\r
@@ -551,7 +576,7 @@ namespace VSCodeTestNoJMCNoFilterStepping
             C.M3(C.M6(), C.M6());                                           Label.Breakpoint("test_step_arguments_6");\r
             Console.WriteLine("Test steps for arguments end.");             Label.Breakpoint("test_step_arguments_end");\r
 \r
-            Label.Checkpoint("test_step_arguments", "finish", (Object context) => {\r
+            Label.Checkpoint("test_step_arguments", "test_step_comp", (Object context) => {\r
                 Context Context = (Context)context;\r
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_1");\r
                 Context.StepOver(@"__FILE__:__LINE__");\r
@@ -676,6 +701,96 @@ namespace VSCodeTestNoJMCNoFilterStepping
                 Context.StepIn(@"__FILE__:__LINE__");\r
 \r
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_end");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            // Test step-in/step-over for compiler generated code inside user code.\r
+\r
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_1");\r
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_2");\r
+            Console.WriteLine("Test steps end.");                           Label.Breakpoint("test_step_comp_end");\r
+\r
+            Label.Checkpoint("test_step_comp", "finish", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");\r
+                Context.StepIn(@"__FILE__:__LINE__");\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");\r
+                Context.StepOver(@"__FILE__:__LINE__");\r
+\r
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_end");\r
                 Context.StepOut(@"__FILE__:__LINE__");\r
             });\r
 \r
index 098cc649c09796cbe87ea7ada91b7fb94e128406..a93095461afd2a5cde7a67f84993fc5b877ac2a1 100644 (file)
@@ -303,6 +303,31 @@ namespace VSCodeTestStepping
         }
     }
 
+    class TestStepWithCompilerGenCode : IDisposable
+    {
+        public void Dispose()
+        {                                                                   Label.Breakpoint("test_step_comp_Dispose_1");
+            ;                                                               Label.Breakpoint("test_step_comp_Dispose_2");
+        Label.Breakpoint("test_step_comp_Dispose_3");}
+
+        public static void M()
+        {                                                                   Label.Breakpoint("test_step_comp_M_1");
+            Label.Breakpoint("test_step_comp_M_2");using (var c = new TestStepWithCompilerGenCode())
+            {                                                               Label.Breakpoint("test_step_comp_M_3");
+                ;                                                           Label.Breakpoint("test_step_comp_M_4");
+            Label.Breakpoint("test_step_comp_M_5");}
+            using var c2 = new TestStepWithCompilerGenCode();               Label.Breakpoint("test_step_comp_M_6");
+            try
+            {                                                               Label.Breakpoint("test_step_comp_M_7");
+                ;                                                           Label.Breakpoint("test_step_comp_M_8");
+            Label.Breakpoint("test_step_comp_M_9");}
+            finally
+            {                                                               Label.Breakpoint("test_step_comp_M_10");
+                ;                                                           Label.Breakpoint("test_step_comp_M_11");
+            Label.Breakpoint("test_step_comp_M_12");}
+        Label.Breakpoint("test_step_comp_M_13");}
+    }
+
     class Program
     {
         static void Main(string[] args)
@@ -517,7 +542,7 @@ namespace VSCodeTestStepping
             C.M3(C.M6(), C.M6());                                           Label.Breakpoint("test_step_arguments_6");
             Console.WriteLine("Test steps for arguments end.");             Label.Breakpoint("test_step_arguments_end");
 
-            Label.Checkpoint("test_step_arguments", "finish", (Object context) => {
+            Label.Checkpoint("test_step_arguments", "test_step_comp", (Object context) => {
                 Context Context = (Context)context;
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_1");
                 Context.StepOver(@"__FILE__:__LINE__");
@@ -610,6 +635,96 @@ namespace VSCodeTestStepping
                 Context.StepIn(@"__FILE__:__LINE__");
 
                 Context.WasStep(@"__FILE__:__LINE__", "test_step_arguments_end");
+                Context.StepOver(@"__FILE__:__LINE__");
+            });
+
+            // Test step-in/step-over for compiler generated code inside user code.
+
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_1");
+            TestStepWithCompilerGenCode.M();                                Label.Breakpoint("test_step_comp_2");
+            Console.WriteLine("Test steps end.");                           Label.Breakpoint("test_step_comp_end");
+
+            Label.Checkpoint("test_step_comp", "finish", (Object context) => {
+                Context Context = (Context)context;
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepOver(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_1");
+                Context.StepOver(@"__FILE__:__LINE__");
+
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_4");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_5");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_6");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_7");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_8");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_9");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_10");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_11");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_12");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_1");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_2");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_Dispose_3");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_M_13");
+                Context.StepIn(@"__FILE__:__LINE__");
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_2");
+                Context.StepOver(@"__FILE__:__LINE__");
+
+                Context.WasStep(@"__FILE__:__LINE__", "test_step_comp_end");
                 Context.StepOut(@"__FILE__:__LINE__");
             });