|
|
|
@ -15,13 +15,20 @@ class BreakpointManager { |
|
|
|
|
* @param {Object} _debugger - type of EthDebugger |
|
|
|
|
* @return {Function} _locationToRowConverter - function implemented by editor which return a column/line position for a char source location |
|
|
|
|
*/ |
|
|
|
|
constructor (_debugger, _locationToRowConverter, _jumpToCallback) { |
|
|
|
|
constructor ({traceManager, callTree, solidityProxy, locationToRowConverter}) { |
|
|
|
|
this.event = new EventManager() |
|
|
|
|
this.debugger = _debugger |
|
|
|
|
this.traceManager = traceManager |
|
|
|
|
this.callTree = callTree |
|
|
|
|
this.solidityProxy = solidityProxy |
|
|
|
|
this.breakpoints = {} |
|
|
|
|
this.locationToRowConverter = _locationToRowConverter |
|
|
|
|
this.locationToRowConverter = locationToRowConverter |
|
|
|
|
this.previousLine |
|
|
|
|
this.jumpToCallback = _jumpToCallback || (() => {}) // eslint-disable-line
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setManagers({traceManager, callTree, solidityProxy}) { |
|
|
|
|
this.traceManager = traceManager |
|
|
|
|
this.callTree = callTree |
|
|
|
|
this.solidityProxy = solidityProxy |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -30,7 +37,10 @@ class BreakpointManager { |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
async jumpNextBreakpoint (fromStep, defaultToLimit) { |
|
|
|
|
this.jump(fromStep || 0, 1, defaultToLimit) |
|
|
|
|
if (!this.locationToRowConverter) { |
|
|
|
|
return console.log('row converter not provided') |
|
|
|
|
} |
|
|
|
|
this.jump(fromStep || 0, 1, defaultToLimit, this.traceManager.trace) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -39,64 +49,61 @@ class BreakpointManager { |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
async jumpPreviousBreakpoint (fromStep, defaultToLimit) { |
|
|
|
|
this.jump(fromStep || 0, -1, defaultToLimit) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* start looking for the previous or next breakpoint |
|
|
|
|
* @param {Int} direction - 1 or -1 direction of the search |
|
|
|
|
* @param {Bool} defaultToLimit - if true jump to the limit (end if direction is 1, beginning if direction is -1) of the trace if no more breakpoint found |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
async jump (fromStep, direction, defaultToLimit) { |
|
|
|
|
if (!this.locationToRowConverter) { |
|
|
|
|
console.log('row converter not provided') |
|
|
|
|
return |
|
|
|
|
return console.log('row converter not provided') |
|
|
|
|
} |
|
|
|
|
this.jump(fromStep || 0, -1, defaultToLimit, this.traceManager.trace) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function depthChange (step, trace) { |
|
|
|
|
depthChange (step, trace) { |
|
|
|
|
return trace[step].depth !== trace[step - 1].depth |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function hitLine (currentStep, sourceLocation, previousSourceLocation, self) { |
|
|
|
|
hitLine(currentStep, sourceLocation, previousSourceLocation, trace) { |
|
|
|
|
// isJumpDestInstruction -> returning from a internal function call
|
|
|
|
|
// depthChange -> returning from an external call
|
|
|
|
|
// sourceLocation.start <= previousSourceLocation.start && ... -> previous src is contained in the current one
|
|
|
|
|
if ((helper.isJumpDestInstruction(self.debugger.traceManager.trace[currentStep]) && previousSourceLocation.jump === 'o') || |
|
|
|
|
depthChange(currentStep, self.debugger.traceManager.trace) || |
|
|
|
|
if ((helper.isJumpDestInstruction(trace[currentStep]) && previousSourceLocation.jump === 'o') || |
|
|
|
|
this.depthChange(currentStep, trace) || |
|
|
|
|
(sourceLocation.start <= previousSourceLocation.start && |
|
|
|
|
sourceLocation.start + sourceLocation.length >= previousSourceLocation.start + previousSourceLocation.length)) { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
self.jumpToCallback(currentStep) |
|
|
|
|
self.event.trigger('breakpointHit', [sourceLocation, currentStep]) |
|
|
|
|
this.event.trigger('breakpointStep', [currentStep]) |
|
|
|
|
this.event.trigger('breakpointHit', [sourceLocation, currentStep]) |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* start looking for the previous or next breakpoint |
|
|
|
|
* @param {Int} direction - 1 or -1 direction of the search |
|
|
|
|
* @param {Bool} defaultToLimit - if true jump to the limit (end if direction is 1, beginning if direction is -1) of the trace if no more breakpoint found |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
async jump (fromStep, direction, defaultToLimit, trace) { |
|
|
|
|
let sourceLocation |
|
|
|
|
let previousSourceLocation |
|
|
|
|
let currentStep = fromStep + direction |
|
|
|
|
let lineHadBreakpoint = false |
|
|
|
|
while (currentStep > 0 && currentStep < this.debugger.traceManager.trace.length) { |
|
|
|
|
while (currentStep > 0 && currentStep < trace.length) { |
|
|
|
|
try { |
|
|
|
|
previousSourceLocation = sourceLocation |
|
|
|
|
sourceLocation = await this.debugger.callTree.extractValidSourceLocation(currentStep) |
|
|
|
|
sourceLocation = await this.callTree.extractValidSourceLocation(currentStep) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log('cannot jump to breakpoint ' + e) |
|
|
|
|
return |
|
|
|
|
return console.log('cannot jump to breakpoint ' + e) |
|
|
|
|
} |
|
|
|
|
let lineColumn = await this.locationToRowConverter(sourceLocation) |
|
|
|
|
if (this.previousLine !== lineColumn.start.line) { |
|
|
|
|
if (direction === -1 && lineHadBreakpoint) { // TODO : improve this when we will build the correct structure before hand
|
|
|
|
|
lineHadBreakpoint = false |
|
|
|
|
if (hitLine(currentStep + 1, previousSourceLocation, sourceLocation, this)) { |
|
|
|
|
if (this.hitLine(currentStep + 1, previousSourceLocation, sourceLocation, trace)) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.previousLine = lineColumn.start.line |
|
|
|
|
if (this.hasBreakpointAtLine(sourceLocation.file, lineColumn.start.line)) { |
|
|
|
|
lineHadBreakpoint = true |
|
|
|
|
if (direction === 1 && hitLine(currentStep, sourceLocation, previousSourceLocation, this)) { |
|
|
|
|
if (direction === 1 && this.hitLine(currentStep, sourceLocation, previousSourceLocation, trace)) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -108,9 +115,9 @@ class BreakpointManager { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if (direction === -1) { |
|
|
|
|
this.jumpToCallback(0) |
|
|
|
|
this.event.trigger('breakpointStep', [0]) |
|
|
|
|
} else if (direction === 1) { |
|
|
|
|
this.jumpToCallback(this.debugger.traceManager.trace.length - 1) |
|
|
|
|
this.event.trigger('breakpointStep', [trace.length - 1]) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -122,7 +129,7 @@ class BreakpointManager { |
|
|
|
|
* @return {Bool} return true if the given @arg fileIndex @arg line refers to a breakpoint |
|
|
|
|
*/ |
|
|
|
|
hasBreakpointAtLine (fileIndex, line) { |
|
|
|
|
const filename = this.debugger.solidityProxy.fileNameFromIndex(fileIndex) |
|
|
|
|
const filename = this.solidityProxy.fileNameFromIndex(fileIndex) |
|
|
|
|
if (!(filename && this.breakpoints[filename])) { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|