Browse Source

breakpoints

cl-refactor
arkpar 10 years ago
parent
commit
5ea84f247e
  1. 41
      mix/qml/CodeEditorView.qml
  2. 33
      mix/qml/Debugger.qml
  3. 12
      mix/qml/MainContent.qml
  4. 25
      mix/qml/WebCodeEditor.qml
  5. 4
      mix/qml/html/cm/codemirror.css
  6. 12020
      mix/qml/html/cm/codemirror.js
  7. 44
      mix/qml/html/codeeditor.js
  8. 51
      mix/qml/js/Debugger.js
  9. 4
      mix/qml/js/ProjectModel.js
  10. 24
      mix/qml/main.qml

41
mix/qml/CodeEditorView.qml

@ -7,6 +7,7 @@ Item {
id: codeEditorView
property string currentDocumentId: ""
signal documentEdit(string documentId)
signal breakpointsChanged(string documentId)
function getDocumentText(documentId) {
for (var i = 0; i < editorListModel.count; i++) {
@ -45,17 +46,49 @@ Item {
if (document.isContract)
codeModel.registerCodeChange(document.documentId, editor.getText());
});
editor.onBreakpointsChanged.connect(function() {
if (document.isContract)
breakpointsChanged(document.documentId);
});
editor.setText(data, document.syntaxMode);
}
function getEditor(documentId) {
for (var i = 0; i < editorListModel.count; i++)
if (editorListModel.get(i).documentId === documentId)
return editors.itemAt(i).item;
return null;
}
function highlightExecution(documentId, location) {
var editor = getEditor(documentId);
if (editor)
editor.highlightExecution(location);
}
function editingContract() {
for (var i = 0; i < editorListModel.count; i++)
if (editorListModel.get(i).documentId === documentId) {
var editor = editors.itemAt(i).item;
if (editor)
editor.highlightExecution(location);
if (editorListModel.get(i).documentId === currentDocumentId)
return editorListModel.get(i).isContract;
return false;
}
function getBreakpoints() {
var bpMap = {};
for (var i = 0; i < editorListModel.count; i++) {
var documentId = editorListModel.get(i).documentId;
var editor = editors.itemAt(i).item;
if (editor) {
bpMap[documentId] = editor.getBreakpoints();
}
}
return bpMap;
}
function toggleBreakpoint() {
var editor = getEditor(currentDocumentId);
if (editor)
editor.toggleBreakpoint();
}
Component.onCompleted: projectModel.codeEditor = codeEditorView;

33
mix/qml/Debugger.qml

@ -54,8 +54,9 @@ Rectangle {
forceActiveFocus();
}
ListModel {
id: breakpointModel;
function setBreakpoints(bp)
{
Debugger.setBreakpoints(bp);
}
Connections {
@ -67,7 +68,7 @@ Rectangle {
Connections {
target: codeModel
onCompilationComplete: update(null, false);
//onCompilationComplete: update(null, false);
}
Settings {
@ -190,6 +191,18 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
spacing: 3
StepActionImage
{
id: runBackAction;
enabledStateImg: "qrc:/qml/img/jumpoutback.png"
disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png"
onClicked: Debugger.runBack()
width: 30
height: 30
buttonShortcut: "Ctrl+Shift+F5"
buttonTooltip: qsTr("Run Back")
}
StepActionImage
{
id: jumpOutBackAction;
@ -261,6 +274,20 @@ Rectangle {
buttonShortcut: "Shift+F11"
buttonTooltip: qsTr("Step Out Forward")
}
StepActionImage
{
id: runForwardAction
enabledStateImg: "qrc:/qml/img/jumpoutforward.png"
disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png"
onClicked: Debugger.runForward()
width: 30
height: 30
buttonShortcut: "Ctrl+F5"
buttonTooltip: qsTr("Run Forward")
}
}
}

12
mix/qml/MainContent.qml

@ -26,6 +26,7 @@ Rectangle {
property alias projectViewVisible: projectList.visible
property alias runOnProjectLoad: mainSettings.runOnProjectLoad
property alias rightPane: rightView
property alias codeEditor: codeEditor
property bool webViewHorizontal: codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally
property bool firstCompile: true
@ -47,6 +48,12 @@ Rectangle {
}
}
Connections {
target: codeEditor
onBreakpointsChanged: {
rightPane.setBreakpoints(codeEditor.getBreakpoints());
}
}
function startQuickDebugging()
{
@ -83,6 +90,11 @@ Rectangle {
codeWebSplitter.orientation = (codeWebSplitter.orientation === Qt.Vertical ? Qt.Horizontal : Qt.Vertical);
}
//TODO: move this to debugger.js after refactoring, introduce events
function toggleBreakpoint() {
codeEditor.toggleBreakpoint();
}
CodeEditorExtensionManager {
headerView: headerPaneTabs;
}

25
mix/qml/WebCodeEditor.qml

@ -2,15 +2,17 @@ import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0
//import CodeEditorExtensionManager 1.0
import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
Item {
signal editorTextChanged
signal editorTextChanged;
signal breakpointsChanged;
property string currentText: ""
property string currentMode: ""
property bool initialized: false
property var currentBreakpoints: [];
function setText(text, mode) {
currentText = text;
@ -41,6 +43,14 @@ Item {
editorBrowser.runJavaScript("highlightExecution(" + location.start + "," + location.end + ")");
}
function getBreakpoints() {
return currentBreakpoints;
}
function toggleBreakpoint() {
editorBrowser.runJavaScript("toggleBreakpoint()");
}
Connections {
target: appContext
onClipboardChanged: syncClipboard()
@ -84,6 +94,17 @@ Item {
});
}
});
editorBrowser.runJavaScript("getBreakpointsChanged()", function(result) {
if (result === true) {
editorBrowser.runJavaScript("getBreakpoints()" , function(bp) {
if (currentBreakpoints !== bp) {
currentBreakpoints = bp;
breakpointsChanged();
}
});
}
});
}
}
}

4
mix/qml/html/cm/codemirror.css

@ -8,6 +8,10 @@
font-size:12px
}
/* BREAKPOINTS */
.breakpoints {width: .8em;}
.breakpoint { color: #822; }
/* PADDING */
.CodeMirror-lines {

12020
mix/qml/html/cm/codemirror.js

File diff suppressed because it is too large

44
mix/qml/html/codeeditor.js

@ -4,6 +4,7 @@ var editor = CodeMirror(document.body, {
//styleActiveLine: true,
matchBrackets: true,
autofocus: true,
gutters: ["CodeMirror-linenumbers", "breakpoints"]
});
@ -13,6 +14,7 @@ editor.setOption("indentWithTabs", true);
editor.setOption("fullScreen", true);
editor.changeRegistered = false;
editor.breakpointsChangeRegistered = false;
editor.on("change", function(eMirror, object) {
editor.changeRegistered = true;
@ -33,6 +35,28 @@ editor.setOption("extraKeys", {
}});
}
makeMarker = function() {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = "●";
return marker;
};
toggleBreakpointLine = function(n) {
var info = editor.lineInfo(n);
editor.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
editor.breakpointsChangeRegistered = true;
}
editor.on("gutterClick", function(cm, n) {
toggleBreakpointLine(n);
});
toggleBreakpoint = function() {
var line = editor.getCursor().line;
toggleBreakpointLine(line);
}
getTextChanged = function() {
return editor.changeRegistered;
};
@ -42,6 +66,25 @@ getText = function() {
return editor.getValue();
};
getBreakpointsChanged = function() {
return editor.changeRegistered || editor.breakpointsChangeRegistered; //TODO: track new lines
};
getBreakpoints = function() {
var locations = [];
editor.breakpointsChangeRegistered = false;
var doc = editor.doc;
doc.iter(function(line) {
if (line.gutterMarkers && line.gutterMarkers["breakpoints"]) {
var l = doc.getLineNumber(line);
locations.push({
start: editor.indexFromPos({ line: l, ch: 0}),
end: editor.indexFromPos({ line: l + 1, ch: 0})
});;
}
});
return locations;
};
setTextBase64 = function(text) {
editor.setValue(window.atob(text));
@ -66,5 +109,4 @@ highlightExecution = function(start, end) {
if (executionMark)
executionMark.clear();
executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" });
//executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { css: "color: #fe3" });
}

51
mix/qml/js/Debugger.js

@ -7,6 +7,7 @@ var debugData = null;
var codeMap = null;
var locations = [];
var locationMap = {};
var breakpoints = {};
function init(data)
{
@ -17,6 +18,7 @@ function init(data)
jumpOverBackAction.enabled(false);
jumpOverForwardAction.enabled(false);
//breakpoints = {};
if (data === null) {
statesList.model.clear();
statesSlider.maximumValue = 0;
@ -50,8 +52,8 @@ function initLocations()
if (debugData.states.length === 0)
return;
var prevLocation = { start: -1, end: -1, documentId: "", state: 0 };
var nullLocation = { start: -1, end: -1, documentId: "", state: 0};
var nullLocation = { start: -1, end: -1, documentId: "", state: 0 };
var prevLocation = nullLocation;
for (var i = 0; i < debugData.states.length - 1; i++) {
var code = debugData.states[i].code;
@ -63,6 +65,13 @@ function initLocations()
}
locationMap[i] = locations.length - 1;
}
locations.push({ start: -1, end: -1, documentId: code.documentId, state: i });
locationMap[debugData.states.length - 1] = locations.length - 1;
}
function setBreakpoints(bp)
{
breakpoints = bp;
}
function srcMode()
@ -72,7 +81,9 @@ function srcMode()
function initSlider()
{
if (srcMode()) {
if (!debugData)
statesSlider.maximumValue = 0;
else if (srcMode()) {
statesSlider.maximumValue = locations.length - 1;
} else {
statesSlider.maximumValue = debugData.states.length - 1;
@ -114,7 +125,7 @@ function display(stateIndex)
if (stateIndex < 0)
stateIndex = 0;
if (stateIndex >= debugData.states.length)
stateIndex = debugData.state.length - 1;
stateIndex = debugData.states.length - 1;
if (debugData.states[stateIndex].codeIndex !== debugData.states[currentDisplayedState].codeIndex)
setupInstructions(stateIndex);
if (debugData.states[stateIndex].dataIndex !== debugData.states[currentDisplayedState].dataIndex)
@ -158,6 +169,8 @@ function selectState(stateIndex)
jumpOverBackAction.enabled(stateIndex > 0);
jumpOutBackAction.enabled(state.levels.length > 1);
jumpOutForwardAction.enabled(state.levels.length > 1);
runForwardAction.enabled(stateIndex < debugData.states.length - 1)
runBackAction.enabled(stateIndex > 0);
var callStackData = [];
for (var l = 0; l < state.levels.length; l++) {
@ -211,6 +224,18 @@ function isReturnInstruction(index)
function breakpointHit(i)
{
var bpLocations = breakpoints[debugData.states[i].code.documentId];
if (bpLocations) {
var location = debugData.states[i].code.locations[i];
if (location && location.start >=0 && location.end >= location.start) {
for (var b = 0; b < bpLocations.length; b++) {
var bpLocation = bpLocations[b];
if ((bpLocation.start >= location.start && bpLocation.start <= location.end) || (bpLocation.end >= location.start && bpLocation.end <= location.end) ||
(location.start >= bpLocation.start && location.start <= bpLocation.end) || (location.end >= bpLocation.start && location.end <= bpLocation.end))
return true;
}
}
}
return false;
}
@ -240,6 +265,24 @@ function stepIntoForward()
moveSelection(1);
}
function runBack()
{
var i = currentSelectedState - 1;
while (i > 0 && !breakpointHit(i)) {
--i;
}
selectState(i);
}
function runForward()
{
var i = currentSelectedState + 1;
while (i < debugData.states.length - 1 && !breakpointHit(i)) {
++i;
}
selectState(i);
}
function stepOutBack()
{
var i = currentSelectedState - 1;

4
mix/qml/js/ProjectModel.js

@ -64,7 +64,7 @@ function saveProject() {
function loadProject(path) {
closeProject();
console.log("loading project at " + path);
console.log("Loading project at " + path);
var projectFile = path + projectFileName;
var json = fileIo.readFile(projectFile);
var projectData = JSON.parse(json);
@ -185,7 +185,7 @@ function doCloseProject() {
function doCreateProject(title, path) {
closeProject();
console.log("creating project " + title + " at " + path);
console.log("Creating project " + title + " at " + path);
if (path[path.length - 1] !== "/")
path += "/";
var dirPath = path + title + "/";

24
mix/qml/main.qml

@ -37,7 +37,6 @@ ApplicationWindow {
}
Menu {
title: qsTr("Deploy")
MenuItem { action: debugRunAction }
MenuItem { action: mineAction }
MenuSeparator {}
MenuItem { action: editStatesAction }
@ -46,6 +45,12 @@ ApplicationWindow {
MenuSeparator {}
MenuItem { action: toggleRunOnLoadAction }
}
Menu {
title: qsTr("Debug")
MenuItem { action: debugRunAction }
MenuSeparator {}
MenuItem { action: toggleAssemblyDebuggingAction }
}
Menu {
title: qsTr("Windows")
MenuItem { action: openNextDocumentAction }
@ -129,6 +134,15 @@ ApplicationWindow {
enabled: codeModel.hasContract && !clientModel.running
}
Action {
id: toggleAssemblyDebuggingAction
text: qsTr("Show VM Code")
shortcut: "Ctrl+Alt+V"
onTriggered: mainContent.rightPane.assemblyMode = !mainContent.rightPane.assemblyMode;
checked: mainContent.rightPane.assemblyMode;
enabled: true
}
Action {
id: toggleWebPreviewAction
text: qsTr("Show Web View")
@ -303,6 +317,14 @@ ApplicationWindow {
onTriggered: projectModel.openPrevDocument();
}
Action {
id: toggleBreakpointAction
text: qsTr("Toggle Breakpoint")
shortcut: "F9"
enabled: mainContent.codeEditor.editingContract();
onTriggered: mainContent.toggleBreakpoint();
}
Action {
id: deployViaRpcAction
text: qsTr("Deploy to Network")

Loading…
Cancel
Save