Skip to content

Commit bc1ca21

Browse files
committed
Merge branch 'vscode-debugger' into develop
2 parents f85d864 + bf185b4 commit bc1ca21

File tree

4 files changed

+110
-81
lines changed

4 files changed

+110
-81
lines changed

Meadow.CoverageReport/Debugging/ExecutionTraceAnalysis.cs

+14-12
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ public ExecutionTraceAnalysis(ExecutionTrace executionTrace)
128128
ParseStateVariableDeclarations();
129129

130130
// Parse our entire execution trace.
131-
ParseScopes(0, 0, 0, null);
131+
SourceMapEntry? lastEntry = null;
132+
ParseScopes(0, 0, 0, null, ref lastEntry);
132133
}
133134
#endregion
134135

@@ -776,15 +777,12 @@ private void ParseScopeTracepoint(int traceIndex, SourceMapEntry currentEntry, E
776777
/// <param name="callDepth">The depth of calls at this point in the scan. This refers to the EVM message depth at this point in execution.</param>
777778
/// <param name="parentScope">References the immediate parent scope which contains this scope. Can be null (for root).</param>
778779
/// <returns>Returns the next trace index to continue from for the calling scope.</returns>
779-
private int ParseScopes(int traceIndex, int scopeDepth, int callDepth, ExecutionTraceScope parentScope)
780+
private int ParseScopes(int traceIndex, int scopeDepth, int callDepth, ExecutionTraceScope parentScope, ref SourceMapEntry? lastEntry)
780781
{
781782
// Backup our scope start and create an entry in our dictionary (some properties of which we'll populate later)
782783
int scopeStartIndex = traceIndex;
783784
ExecutionTraceScope currentScope = new ExecutionTraceScope(scopeStartIndex, scopeDepth, callDepth, parentScope);
784785

785-
// The last map entry obtained in the loop.
786-
SourceMapEntry? lastEntry = null;
787-
788786
// Loop until the end of the trace
789787
while (traceIndex < ExecutionTrace.Tracepoints.Length)
790788
{
@@ -831,16 +829,23 @@ private int ParseScopes(int traceIndex, int scopeDepth, int callDepth, Execution
831829
significantStep = true;
832830
}
833831

834-
// If an exception occurred at this step, it's a significant step
835-
if (_exceptionLookup.ContainsKey(traceIndex))
832+
// If an exception occurred at this step, it's a significant step. If we
833+
// didn't already mark this as a significant step, it means this line is
834+
// represented in our last trace index. We remove the last trace index,
835+
// and mark this step as significant so it is added instead.
836+
if (!significantStep && _exceptionLookup.ContainsKey(traceIndex))
836837
{
838+
// Remove the last step from our significant step index, and set this
839+
// one as significant so it is used instead.
840+
SignificantStepIndices.RemoveAt(SignificantStepIndices.Count - 1);
837841
significantStep = true;
838842
}
839843

840-
// If this is a significant step, add it to our list
844+
// If this is a significant step, add it to our list, and set the last entry.
841845
if (significantStep)
842846
{
843847
SignificantStepIndices.Add(traceIndex);
848+
lastEntry = currentEntry;
844849
}
845850

846851
// Determine if we're in an external call
@@ -869,7 +874,7 @@ private int ParseScopes(int traceIndex, int scopeDepth, int callDepth, Execution
869874
int childScopeDepth = scopeDepth + 1;
870875

871876
// Parse our child scope and set our (potentially) advanced trace index
872-
traceIndex = ParseScopes(childStartIndex, childScopeDepth, childCallDepth, currentScope);
877+
traceIndex = ParseScopes(childStartIndex, childScopeDepth, childCallDepth, currentScope, ref lastEntry);
873878
}
874879
else if (exitingScope)
875880
{
@@ -884,9 +889,6 @@ private int ParseScopes(int traceIndex, int scopeDepth, int callDepth, Execution
884889
ParseScopeTracepoint(traceIndex, currentEntry, currentScope);
885890
}
886891

887-
// Set our last entry
888-
lastEntry = currentEntry;
889-
890892
// Increment our trace index
891893
traceIndex++;
892894
}

Meadow.DebugAdapterServer/MeadowDebugAdapterState.cs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public class MeadowDebugAdapterThreadState
1212
{
1313
#region Fields
1414
private int _significantStepIndexIndex;
15-
public int? LastExceptionTraceIndex;
1615
#endregion
1716

1817
#region Properties

Meadow.DebugAdapterServer/MeadowSolidityDebugAdapter.cs

+92-60
Original file line numberDiff line numberDiff line change
@@ -128,79 +128,109 @@ public async Task ProcessExecutionTraceAnalysis(ExecutionTraceAnalysis traceAnal
128128
_processTraceSemaphore.Release();
129129
}
130130

131-
private void ContinueExecution(MeadowDebugAdapterThreadState threadState, DesiredControlFlow controlFlow = DesiredControlFlow.Continue)
131+
private void ContinueExecution(MeadowDebugAdapterThreadState threadState, DesiredControlFlow controlFlowAction = DesiredControlFlow.Continue, int stepsPriorToAction = 0)
132132
{
133133
// Unlink our data for our thread id.
134134
ReferenceContainer.UnlinkThreadId(threadState.ThreadId);
135135

136-
// Verify we don't have an exception at this point that we haven't already handled, if we do, break out.
137-
if (threadState.LastExceptionTraceIndex != threadState.CurrentStepIndex && HandleExceptions(threadState))
136+
// Create a variable to track if we have finished stepping through the execution.
137+
bool finishedExecution = false;
138+
139+
// Determine the direction to take steps prior to any evaluation.
140+
if (stepsPriorToAction >= 0)
138141
{
139-
return;
142+
// Loop for each step to take forward.
143+
for (int i = 0; i < stepsPriorToAction; i++)
144+
{
145+
// Take a step forward, if we could not, we finished execution, so we can stop looping.
146+
if (!threadState.IncrementStep())
147+
{
148+
finishedExecution = true;
149+
break;
150+
}
151+
}
140152
}
141-
142-
// Determine how to continue execution.
143-
bool finishedExecution = false;
144-
switch (controlFlow)
153+
else
145154
{
146-
case DesiredControlFlow.StepOver:
147-
// TODO: Implement
148-
149-
case DesiredControlFlow.StepInto:
155+
// Loop for each step to take backward
156+
for (int i = 0; i > stepsPriorToAction; i--)
157+
{
158+
// Take a step backward, if we could not, we can stop early as we won't be able to step backwards anymore.
159+
if (!threadState.DecrementStep())
150160
{
151-
// Increment our step
152-
finishedExecution = !threadState.IncrementStep();
153-
154-
// Signal our breakpoint event has occurred for this thread.
155-
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Step) { ThreadId = threadState.ThreadId });
156161
break;
157162
}
163+
}
164+
}
158165

159-
case DesiredControlFlow.StepOut:
160-
// TODO: Implement
166+
// If we haven't finished execution,
167+
if (!finishedExecution)
168+
{
169+
switch (controlFlowAction)
170+
{
171+
case DesiredControlFlow.StepOver:
172+
// TODO: Implement
161173

162-
case DesiredControlFlow.StepBackwards:
163-
{
164-
// Decrement our step
165-
threadState.DecrementStep();
174+
case DesiredControlFlow.StepInto:
175+
{
176+
// Increment our step
177+
finishedExecution = !threadState.IncrementStep();
166178

167-
// Signal our breakpoint event has occurred for this thread.
168-
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Step) { ThreadId = threadState.ThreadId });
179+
// If we stepped successfully, we evaluate, and if an event is encountered, we stop.
180+
if (!finishedExecution && EvaluateCurrentStep(threadState))
181+
{
182+
return;
183+
}
169184

170-
// TODO: Check if we couldn't decrement step. Disable step backward if we can.
171-
break;
172-
}
185+
// Signal our breakpoint event has occurred for this thread.
186+
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Step) { ThreadId = threadState.ThreadId });
187+
break;
188+
}
173189

174-
case DesiredControlFlow.Continue:
175-
{
176-
// Process the execution trace analysis
177-
while (threadState.CurrentStepIndex.HasValue && !Exiting)
190+
case DesiredControlFlow.StepOut:
191+
// TODO: Implement
192+
193+
case DesiredControlFlow.StepBackwards:
178194
{
179-
// Obtain our breakpoints.
180-
bool hitBreakpoint = CheckBreakpointExists(threadState);
195+
// Decrement our step
196+
bool decrementedStep = threadState.DecrementStep();
181197

182-
// If we hit a breakpoint, we can signal our breakpoint and exit this execution method.
183-
if (hitBreakpoint)
198+
// If we stepped successfully, we evaluate, and if an event is encountered, we stop.
199+
if (decrementedStep && EvaluateCurrentStep(threadState))
184200
{
185-
// Signal our breakpoint event has occurred for this thread.
186-
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Breakpoint) { ThreadId = threadState.ThreadId });
187201
return;
188202
}
189203

190-
// Increment our position
191-
bool successfulStep = threadState.IncrementStep();
204+
// Signal our breakpoint event has occurred for this thread.
205+
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Step) { ThreadId = threadState.ThreadId });
192206

193-
// If we couldn't step, break out of our loop
194-
if (!successfulStep)
207+
// TODO: Check if we couldn't decrement step. Disable step backward if we can.
208+
break;
209+
}
210+
211+
case DesiredControlFlow.Continue:
212+
{
213+
// Process the execution trace analysis
214+
while (threadState.CurrentStepIndex.HasValue && !Exiting)
195215
{
196-
break;
216+
// If we encountered an event at this point, stop
217+
if (EvaluateCurrentStep(threadState))
218+
{
219+
return;
220+
}
221+
222+
// If we couldn't step forward, this trace has been fully processed.
223+
if (!threadState.IncrementStep())
224+
{
225+
break;
226+
}
197227
}
198-
}
199228

200-
// If we exited this way, our execution has concluded because we could not step any further (or there were never any steps).
201-
finishedExecution = true;
202-
break;
203-
}
229+
// If we exited this way, our execution has concluded because we could not step any further (or there were never any steps).
230+
finishedExecution = true;
231+
break;
232+
}
233+
}
204234
}
205235

206236
// If we finished execution, signal our thread
@@ -210,6 +240,12 @@ private void ContinueExecution(MeadowDebugAdapterThreadState threadState, Desire
210240
}
211241
}
212242

243+
private bool EvaluateCurrentStep(MeadowDebugAdapterThreadState threadState, bool exceptions = true, bool breakpoints = true)
244+
{
245+
// Evaluate exceptions and breakpoints at this point in execution.
246+
return (exceptions && HandleExceptions(threadState)) || (breakpoints && HandleBreakpoint(threadState));
247+
}
248+
213249
private bool HandleExceptions(MeadowDebugAdapterThreadState threadState)
214250
{
215251
// Try to obtain an exception at this point
@@ -221,9 +257,6 @@ private bool HandleExceptions(MeadowDebugAdapterThreadState threadState)
221257
// If we have an exception, throw it and return the appropriate status.
222258
if (traceException != null)
223259
{
224-
// Set our last exception index.
225-
threadState.LastExceptionTraceIndex = threadState.CurrentStepIndex.Value;
226-
227260
// Send our exception event.
228261
var stoppedEvent = new StoppedEvent(StoppedEvent.ReasonValue.Exception)
229262
{
@@ -235,14 +268,11 @@ private bool HandleExceptions(MeadowDebugAdapterThreadState threadState)
235268
}
236269
}
237270

238-
// If there was no exception, clear our last exception trace index
239-
threadState.LastExceptionTraceIndex = null;
240-
241271
// We did not find an exception here, return false
242272
return false;
243273
}
244274

245-
private bool CheckBreakpointExists(MeadowDebugAdapterThreadState threadState)
275+
private bool HandleBreakpoint(MeadowDebugAdapterThreadState threadState)
246276
{
247277
// Verify we have a valid step at this point.
248278
if (!threadState.CurrentStepIndex.HasValue)
@@ -264,6 +294,8 @@ private bool CheckBreakpointExists(MeadowDebugAdapterThreadState threadState)
264294
bool containsBreakpoint = success && breakpointLines.Any(x => x == sourceLine.LineNumber);
265295
if (containsBreakpoint)
266296
{
297+
// Signal our breakpoint event has occurred for this thread.
298+
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Breakpoint) { ThreadId = threadState.ThreadId });
267299
return true;
268300
}
269301
}
@@ -422,11 +454,11 @@ protected override void HandleContinueRequestAsync(IRequestResponder<ContinueArg
422454
bool success = ThreadStates.TryGetValue(responder.Arguments.ThreadId, out var threadState);
423455
if (success)
424456
{
425-
// Advance our step from our current position
426-
threadState.IncrementStep();
427-
428-
// Continue executing
429-
ContinueExecution(threadState, DesiredControlFlow.Continue);
457+
// Continue executing, taking one step before continuing, as evaluation occurs before steps occur, and we want
458+
// to ensure we advanced position from our last and don't re-evaluate the same trace point. We only do this on
459+
// startup since we want the initial trace point to be evaluated. After that, we want to force advancement by
460+
// at least one step before continuation/re-evaluation.
461+
ContinueExecution(threadState, DesiredControlFlow.Continue, 1);
430462
}
431463
}
432464

Meadow.JsonRpc.Client/JsonRpcClient.cs

+4-8
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,8 @@ public async Task<Hash> SendTransaction(TransactionParams transactionParams)
405405

406406
var (error, result) = await InvokeRpcMethod(request, throwOnError: false);
407407

408-
if (JsonRpcExecutionAnalysis != null)
409-
{
410-
await JsonRpcExecutionAnalysis(_thisInterface);
411-
}
408+
// Invoke our execution analysis hook.
409+
await (JsonRpcExecutionAnalysis?.Invoke(_thisInterface) ?? Task.CompletedTask);
412410

413411
if (error != null)
414412
{
@@ -441,10 +439,8 @@ public async Task<byte[]> Call(CallParams callParams, DefaultBlockParameter bloc
441439

442440
var (error, result) = await InvokeRpcMethod(request, throwOnError: false);
443441

444-
if (JsonRpcExecutionAnalysis != null)
445-
{
446-
await JsonRpcExecutionAnalysis(_thisInterface);
447-
}
442+
// Invoke our execution analysis hook.
443+
await (JsonRpcExecutionAnalysis?.Invoke(_thisInterface) ?? Task.CompletedTask);
448444

449445
if (error != null)
450446
{

0 commit comments

Comments
 (0)