From b265fb8249406c99a7761377c1101325b53fae9d Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 29 Jan 2015 18:32:19 +0100 Subject: [PATCH 1/5] nice app icon --- mix/AppContext.cpp | 3 +++ mix/res.qrc | 1 + mix/res/mix_256x256x32.png | Bin 0 -> 20502 bytes 3 files changed, 4 insertions(+) create mode 100644 mix/res/mix_256x256x32.png diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index cae6dde57..ad9c78e9b 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "CodeModel.h" #include "FileIo.h" #include "ClientModel.h" @@ -75,6 +76,8 @@ void AppContext::load() qmlRegisterType("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); qmlRegisterType("HttpServer", 1, 0, "HttpServer"); m_applicationEngine->load(QUrl("qrc:/qml/main.qml")); + QQuickWindow *window = qobject_cast(m_applicationEngine->rootObjects().at(0)); + window->setIcon(QIcon(":/res/mix_256x256x32.png")); appLoaded(); } diff --git a/mix/res.qrc b/mix/res.qrc index f009ab923..fdb6bf590 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -50,5 +50,6 @@ stdc/namereg.sol stdc/std.sol qml/TransactionLog.qml + res/mix_256x256x32.png diff --git a/mix/res/mix_256x256x32.png b/mix/res/mix_256x256x32.png new file mode 100644 index 0000000000000000000000000000000000000000..9a60fe4df89a3692cea8eb4de61be6632a3a9149 GIT binary patch literal 20502 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℘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 Rks$96Vx))CrE25C{}0+U2POaj literal 0 HcmV?d00001 From c820b2597ec7ab3bb45238978a838a0d1d0af04b Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 30 Jan 2015 17:55:39 +0100 Subject: [PATCH 2/5] debugging into calls --- mix/AssemblyDebuggerControl.cpp | 7 -- mix/AssemblyDebuggerControl.h | 4 -- mix/ClientModel.cpp | 40 +++++++----- mix/ClientModel.h | 10 +-- mix/CodeModel.cpp | 2 +- mix/DebuggingStateWrapper.cpp | 54 +++++++--------- mix/DebuggingStateWrapper.h | 84 +++++++++++++++--------- mix/MixClient.cpp | 48 ++++++++++---- mix/MixClient.h | 9 +-- mix/qml/Debugger.qml | 14 +++- mix/qml/js/Debugger.js | 110 +++++++++++++++----------------- 11 files changed, 205 insertions(+), 177 deletions(-) diff --git a/mix/AssemblyDebuggerControl.cpp b/mix/AssemblyDebuggerControl.cpp index f52245450..e065513a8 100644 --- a/mix/AssemblyDebuggerControl.cpp +++ b/mix/AssemblyDebuggerControl.cpp @@ -29,7 +29,6 @@ using namespace dev::mix; AssemblyDebuggerControl::AssemblyDebuggerControl(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightView) { - connect(_context->clientModel(), &ClientModel::showDebuggerWindow, this, &AssemblyDebuggerControl::showDebugger, Qt::QueuedConnection); } QString AssemblyDebuggerControl::contentUrl() const @@ -45,9 +44,3 @@ QString AssemblyDebuggerControl::title() const void AssemblyDebuggerControl::start() const { } - -void AssemblyDebuggerControl::showDebugger() -{ - QObject* debugPanel = m_view->findChild("debugPanel", Qt::FindChildrenRecursively); - QMetaObject::invokeMethod(debugPanel, "update", Q_ARG(QVariant, true)); -} diff --git a/mix/AssemblyDebuggerControl.h b/mix/AssemblyDebuggerControl.h index 1240b3807..701cbc5fd 100644 --- a/mix/AssemblyDebuggerControl.h +++ b/mix/AssemblyDebuggerControl.h @@ -42,10 +42,6 @@ public: void start() const override; QString title() const override; QString contentUrl() const override; - -private slots: - /// Update UI with machine states result. Displayed in the right side tab. - void showDebugger(); }; } diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 251447c79..914edf52d 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -72,7 +72,10 @@ ClientModel::ClientModel(AppContext* _context): qRegisterMetaType>("QList"); qRegisterMetaType>("QList"); qRegisterMetaType("QVariableDeclaration*"); - qRegisterMetaType("AssemblyDebuggerData"); + qRegisterMetaType("QMachineState"); + qRegisterMetaType("QInstruction"); + qRegisterMetaType("QCode"); + qRegisterMetaType("QCallData"); qRegisterMetaType("TransactionLogEntry"); connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); @@ -251,24 +254,27 @@ void ClientModel::showDebugger() void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) { //we need to wrap states in a QObject before sending to QML. - QList wStates; - for (unsigned i = 0; i < _t.machineStates.size(); i++) - { - QPointer s(new DebuggingStateWrapper(_t.executionCode, _t.executionData.toBytes())); - s->setState(_t.machineStates[i]); - wStates.append(s); - } + QDebugData* debugData = new QDebugData(); + QQmlEngine::setObjectOwnership(debugData, QQmlEngine::JavaScriptOwnership); + QList codes; + for (bytes const& code: _t.executionCode) + codes.push_back(QMachineState::getHumanReadableCode(debugData, code)); + + QList data; + for (bytes const& d: _t.transactionData) + data.push_back(QMachineState::getDebugCallData(debugData, d)); + + QVariantList states; + for (MachineState const& s: _t.machineStates) + states.append(QVariant::fromValue(new QMachineState(debugData, s, codes[s.codeIndex], data[s.dataIndex]))); + + debugData->setStates(std::move(states)); - QList returnParameters; + //QList returnParameters; //returnParameters = encoder.decode(f->returnParameters(), debuggingContent.returnValue); //collect states for last transaction - AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(_t.executionCode); - m_context->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - m_context->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - m_context->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); - m_context->appEngine()->rootContext()->setContextProperty("contractCallReturnParameters", QVariant::fromValue(new QVariableDefinitionList(returnParameters))); - showDebuggerWindow(); + debugDataReady(debugData); } @@ -339,9 +345,9 @@ void ClientModel::onNewTransaction() else { //call - if (tr.transactionData.size() >= 4) + if (tr.transactionData.size() > 0 && tr.transactionData.front().size() >= 4) { - functionHash = FixedHash<4>(tr.transactionData.data(), FixedHash<4>::ConstructFromPointer); + functionHash = FixedHash<4>(tr.transactionData.front().data(), FixedHash<4>::ConstructFromPointer); function = QString::fromStdString(toJS(functionHash)); call = true; } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 016673ba6..729d6acf6 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -25,14 +25,9 @@ #include #include -#include "DebuggingStateWrapper.h" +#include #include "MixClient.h" -using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; - -Q_DECLARE_METATYPE(AssemblyDebuggerData) -Q_DECLARE_METATYPE(dev::mix::ExecutionResult) - namespace dev { namespace mix @@ -42,6 +37,7 @@ class AppContext; class Web3Server; class RpcConnector; class QEther; +class QDebugData; /// Backend transaction config class struct TransactionSettings @@ -156,7 +152,7 @@ signals: /// Execution state changed void runStateChanged(); /// Show debugger window request - void showDebuggerWindow(); + void debugDataReady(QObject* _debugData); /// ethereum.js RPC response ready /// @param _message RPC response in Json format void apiResponse(QString const& _message); diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 39edd6d6f..b811bc172 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -133,7 +133,7 @@ void CodeModel::runCompilationJob(int _jobId, QString const& _code) if (_jobId != m_backgroundJobId) return; //obsolete job - solidity::CompilerStack cs; + solidity::CompilerStack cs(true); std::unique_ptr result; std::string source = _code.toStdString(); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 1eacac120..c99ce9681 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,10 +36,9 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code) +QCode* QMachineState::getHumanReadableCode(QObject* _owner, const bytes& _code) { - QList codeStr; - QMap codeMapping; + QVariantList codeStr; for (unsigned i = 0; i <= _code.size(); ++i) { byte b = i < _code.size() ? _code[i] : 0; @@ -47,7 +47,6 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod QString s = QString::fromStdString(instructionInfo((Instruction)b).name); std::ostringstream out; out << std::hex << std::setw(4) << std::setfill('0') << i; - codeMapping[i] = codeStr.size(); int line = i; if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) { @@ -55,8 +54,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } - QPointer humanCode(new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line)); - codeStr.append(humanCode); + codeStr.append(QVariant::fromValue(new QInstruction(_owner, QString::fromStdString(out.str()) + " " + s, line))); } catch (...) { @@ -65,25 +63,25 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod break; // probably hit data segment } } - return std::make_tuple(codeStr, QPointer(new QQMLMap(codeMapping))); + return new QCode(_owner, std::move(codeStr)); } -QBigInt* DebuggingStateWrapper::gasCost() +QBigInt* QMachineState::gasCost() { return new QBigInt(m_state.gasCost); } -QBigInt* DebuggingStateWrapper::gas() +QBigInt* QMachineState::gas() { return new QBigInt(m_state.gas); } -QBigInt* DebuggingStateWrapper::newMemSize() +QBigInt* QMachineState::newMemSize() { return new QBigInt(m_state.newMemSize); } -QStringList DebuggingStateWrapper::debugStack() +QStringList QMachineState::debugStack() { QStringList stack; for (std::vector::reverse_iterator i = m_state.stack.rbegin(); i != m_state.stack.rend(); ++i) @@ -91,7 +89,7 @@ QStringList DebuggingStateWrapper::debugStack() return fillList(stack, ""); } -QStringList DebuggingStateWrapper::debugStorage() +QStringList QMachineState::debugStorage() { QStringList storage; for (auto const& i: m_state.storage) @@ -103,7 +101,7 @@ QStringList DebuggingStateWrapper::debugStorage() return fillList(storage, "@ -"); } -QVariantList DebuggingStateWrapper::debugMemory() +QVariantList QMachineState::debugMemory() { std::vector> dump = memDumpToList(m_state.memory, 16); QStringList filled; @@ -113,17 +111,17 @@ QVariantList DebuggingStateWrapper::debugMemory() return fillList(qVariantDump(dump), QVariant(filled)); } -QVariantList DebuggingStateWrapper::debugCallData() +QCallData* QMachineState::getDebugCallData(QObject* _owner, bytes const& _data) { - std::vector> dump = memDumpToList(m_data, 16); + std::vector> dump = memDumpToList(_data, 16); QStringList filled; filled.append(" "); filled.append(" "); filled.append(" "); - return fillList(qVariantDump(dump), QVariant(filled)); + return new QCallData(_owner, fillList(qVariantDump(dump), QVariant(filled))); } -std::vector> DebuggingStateWrapper::memDumpToList(bytes const& _bytes, unsigned _width) +std::vector> QMachineState::memDumpToList(bytes const& _bytes, unsigned _width) { std::vector> dump; for (unsigned i = 0; i < _bytes.size(); i += _width) @@ -155,7 +153,7 @@ std::vector> DebuggingStateWrapper::memDumpToList(bytes return dump; } -QVariantList DebuggingStateWrapper::qVariantDump(std::vector> const& _dump) +QVariantList QMachineState::qVariantDump(std::vector> const& _dump) { QVariantList ret; for (std::vector const& line: _dump) @@ -168,7 +166,7 @@ QVariantList DebuggingStateWrapper::qVariantDump(std::vector m_state.gas) return QApplication::tr("OUT-OF-GAS"); diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 0541f0afa..d7591ea4e 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -39,45 +39,61 @@ namespace mix /** * @brief Contains the line nb of the assembly code and the corresponding index in the code bytes array. */ -class HumanReadableCode: public QObject +class QInstruction: public QObject { Q_OBJECT - Q_PROPERTY(QString line READ line CONSTANT) - Q_PROPERTY(int processIndex READ processIndex CONSTANT) + Q_PROPERTY(QString line MEMBER m_line CONSTANT) + Q_PROPERTY(int processIndex MEMBER m_processIndex CONSTANT) public: - HumanReadableCode(QString _line, int _processIndex): QObject(), m_line(_line), m_processIndex(_processIndex) {} - /// Get the assembly code line. - QString line() { return m_line; } - /// Get corresponding index. - int processIndex() { return m_processIndex; } + QInstruction(QObject* _owner, QString _line, int _processIndex): QObject(_owner), m_line(_line), m_processIndex(_processIndex) {} private: QString m_line; int m_processIndex; }; +class QCode: public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantList instructions MEMBER m_instructions CONSTANT) -/** - * @brief Publish QMap type to QML. - */ -class QQMLMap: public QObject +public: + QCode(QObject* _owner, QVariantList&& _instrunctions): QObject(_owner), m_instructions(_instrunctions) {} + +private: + QVariantList m_instructions; +}; + +class QCallData: public QObject { Q_OBJECT + Q_PROPERTY(QVariantList items MEMBER m_items CONSTANT) public: - QQMLMap(QMap _map): QObject(), m_map(_map) { } - /// Get the value associated with _key store in n_map. - Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + QCallData(QObject* _owner, QVariantList&& _items): QObject(_owner), m_items(_items) {} private: - QMap m_map; + QVariantList m_items; +}; + +class QDebugData: public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantList states MEMBER m_states CONSTANT) + +public: + QDebugData() { } + void setStates(QVariantList&& _states) { m_states = _states; } + +private: + QVariantList m_states; }; /** * @brief Wrap DebuggingState in QObject */ -class DebuggingStateWrapper: public QObject +class QMachineState: public QObject { Q_OBJECT Q_PROPERTY(int step READ step CONSTANT) @@ -88,18 +104,25 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList debugStack READ debugStack CONSTANT) Q_PROPERTY(QStringList debugStorage READ debugStorage CONSTANT) Q_PROPERTY(QVariantList debugMemory READ debugMemory CONSTANT) - Q_PROPERTY(QVariantList debugCallData READ debugCallData CONSTANT) - Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT) + Q_PROPERTY(QObject* code MEMBER m_code CONSTANT) + Q_PROPERTY(QObject* callData MEMBER m_callData CONSTANT) Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT) Q_PROPERTY(QBigInt* newMemSize READ newMemSize CONSTANT) Q_PROPERTY(QStringList levels READ levels CONSTANT) + Q_PROPERTY(unsigned codeIndex READ codeIndex CONSTANT) + Q_PROPERTY(unsigned dataIndex READ dataIndex CONSTANT) public: - DebuggingStateWrapper(bytes _code, bytes _data): QObject(), m_code(_code), m_data(_data) {} + QMachineState(QObject* _owner, MachineState const& _state, QCode* _code, QCallData* _callData): + QObject(_owner), m_state(_state), m_code(_code), m_callData(_callData) {} /// Get the step of this machine states. int step() { return (int)m_state.steps; } /// Get the proccessed code index. int curPC() { return (int)m_state.curPC; } + /// Get the code id + unsigned codeIndex() { return m_state.codeIndex; } + /// Get the call data id + unsigned dataIndex() { return m_state.dataIndex; } /// Get gas cost. QBigInt* gasCost(); /// Get gas used. @@ -111,8 +134,6 @@ public: /// Get memory. QVariantList debugMemory(); /// Get call data. - QVariantList debugCallData(); - /// Get info to be displayed in the header. QString headerInfo(); /// get end of debug information. QString endOfDebug(); @@ -126,20 +147,21 @@ public: MachineState state() { return m_state; } /// Set the current processed machine state. void setState(MachineState _state) { m_state = _state; } - /// Convert all machine state in human readable code. - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& _code); + /// Convert all machine states in human readable code. + static QCode* getHumanReadableCode(QObject* _owner, bytes const& _code); + /// Convert call data into human readable form + static QCallData* getDebugCallData(QObject* _owner, bytes const& _data); private: MachineState m_state; - bytes m_code; - bytes m_data; - QStringList fillList(QStringList& _list, QString const& _emptyValue); - QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); - QVariantList qVariantDump(std::vector> const& _dump); + QCode* m_code; + QCallData* m_callData; + static QStringList fillList(QStringList& _list, QString const& _emptyValue); + static QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); + static QVariantList qVariantDump(std::vector> const& _dump); /// Nicely renders the given bytes to a string, store the content in an array. /// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line. - std::vector> memDumpToList(bytes const& _bytes, unsigned _width); - + static std::vector> memDumpToList(bytes const& _bytes, unsigned _width); }; } diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 81df48fe9..86da3fc0f 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -63,21 +63,46 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) bytes rlp = _t.rlp(); Executive execution(_state, LastHashes(), 0); execution.setup(&rlp); - bytes code; - bytesConstRef data; - bool firstIteration = true; std::vector machineStates; std::vector levels; + std::vector codes; + std::map codeIndexes; + std::vector data; + std::map dataIndexes; + bytes const* lastCode = nullptr; + bytesConstRef const* lastData = nullptr; + unsigned codeIndex = 0; + unsigned dataIndex = 0; auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, void* voidVM, void const* voidExt) { VM& vm = *(VM*)voidVM; ExtVM const& ext = *(ExtVM const*)voidExt; + if (lastCode == nullptr || lastCode != &ext.code) + { + auto const& iter = codeIndexes.find(&ext.code); + if (iter != codeIndexes.end()) + codeIndex = iter->second; + else + { + codeIndex = codes.size(); + codes.push_back(ext.code); + codeIndexes[&ext.code] = codeIndex; + } + lastCode = &ext.code; + } - if (firstIteration) + if (lastData == nullptr || lastData != &ext.data) { - code = ext.code; - data = ext.data; - firstIteration = false; + auto const& iter = dataIndexes.find(&ext.data); + if (iter != dataIndexes.end()) + dataIndex = iter->second; + else + { + dataIndex = data.size(); + data.push_back(ext.data.toBytes()); + dataIndexes[&ext.data] = dataIndex; + } + lastData = &ext.data; } if (levels.size() < ext.depth) @@ -85,8 +110,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) else levels.resize(ext.depth); - machineStates.push_back(MachineState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), - vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); + machineStates.emplace_back(MachineState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), + vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels, codeIndex, dataIndex})); }; execution.go(onOp); @@ -95,9 +120,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) ExecutionResult d; d.returnValue = execution.out().toVector(); d.machineStates = machineStates; - d.executionCode = code; - d.executionData = data; - d.transactionData = _t.data(); + d.executionCode = std::move(codes); + d.transactionData = std::move(data); d.address = _t.receiveAddress(); d.sender = _t.sender(); d.value = _t.value(); diff --git a/mix/MixClient.h b/mix/MixClient.h index 54dff0f3a..86a0860e6 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -38,7 +38,7 @@ namespace mix struct MachineState { uint64_t steps; - dev::Address cur; + dev::Address address; dev::u256 curPC; dev::eth::Instruction inst; dev::bigint newMemSize; @@ -48,6 +48,8 @@ struct MachineState dev::bigint gasCost; std::map storage; std::vector levels; + unsigned codeIndex; + unsigned dataIndex; }; /** @@ -58,9 +60,8 @@ struct ExecutionResult ExecutionResult(): receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} std::vector machineStates; - bytes transactionData; - bytes executionCode; - bytesConstRef executionData; + std::vector transactionData; + std::vector executionCode; bytes returnValue; dev::Address address; dev::Address sender; diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 592e7eb26..11b6b6bf0 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -27,11 +27,11 @@ Rectangle { forceActiveFocus(); } - function update(giveFocus) + function update(data, giveFocus) { if (statusPane.result.successful) { - Debugger.init(); + Debugger.init(data); debugScrollArea.visible = true; compilationErrorArea.visible = false; machineStates.visible = true; @@ -50,9 +50,16 @@ Rectangle { forceActiveFocus(); } + Connections { + target: clientModel + onDebugDataReady: { + update(_debugData, true); + } + } + Connections { target: codeModel - onCompilationComplete: update(false) + onCompilationComplete: update(null, false); } Rectangle @@ -277,6 +284,7 @@ Rectangle { delegate: renderDelegate highlight: highlightBar highlightFollowsCurrentItem: false + model: ListModel {} } Component { diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index 9078befdb..9f561b173 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -1,35 +1,53 @@ -//humanReadableExecutionCode => contain human readable code. -//debugStates => contain all debug states. -//bytesCodeMapping => mapping between humanReadableExecutionCode and bytesCode. +//debugData => contain all debug states. //statesList => ListView var currentSelectedState = null; var jumpStartingPoint = null; -function init() +var debugData = null; +var codeMap = null; + +function init(data) { - if (typeof(debugStates) === "undefined") + jumpOutBackAction.enabled(false); + jumpIntoBackAction.enabled(false); + jumpIntoForwardAction.enabled(false); + jumpOutForwardAction.enabled(false); + + if (data === null) { + statesList.model.clear(); + statesSlider.maximumValue = 0; + statesSlider.value = 0; + currentSelectedState = null; + jumpStartingPoint = null; + debugData = null; return; + } - statesSlider.maximumValue = debugStates.length - 1; + debugData = data; + statesSlider.maximumValue = data.states.length - 1; statesSlider.value = 0; - statesList.model = humanReadableExecutionCode; currentSelectedState = 0; + setupInstructions(currentSelectedState); select(currentSelectedState); +} - jumpOutBackAction.enabled(false); - jumpIntoBackAction.enabled(false); - jumpIntoForwardAction.enabled(false); - jumpOutForwardAction.enabled(false); +function setupInstructions(stateIndex) { + + var instructions = debugData.states[stateIndex].code.instructions; + codeMap = {}; + statesList.model.clear(); + for (var i = 0; i < instructions.length; i++) { + statesList.model.append(instructions[i]); + codeMap[instructions[i].processIndex] = i; + } } function moveSelection(incr) { - if (typeof(debugStates) === "undefined") - return; - + var prevState = currentSelectedState; if (currentSelectedState + incr >= 0) { - if (currentSelectedState + incr < debugStates.length) + if (currentSelectedState + incr < debugData.states.length) select(currentSelectedState + incr); statesSlider.value = currentSelectedState; } @@ -37,16 +55,15 @@ function moveSelection(incr) function select(stateIndex) { - if (typeof(debugStates) === "undefined") - return; - + if (debugData.states[stateIndex].codeIndex !== debugData.states[currentSelectedState].codeIndex) + setupInstructions(stateIndex); + currentSelectedState = stateIndex; var codeLine = codeStr(stateIndex); - var state = debugStates[stateIndex]; + var state = debugData.states[stateIndex]; highlightSelection(codeLine); - currentSelectedState = stateIndex; completeCtxInformation(state); - if (state.instruction === "JUMP") + if (state.instruction === "CALL" || state.instruction === "CREATE") jumpIntoForwardAction.enabled(true); else jumpIntoForwardAction.enabled(false); @@ -59,11 +76,8 @@ function select(stateIndex) function codeStr(stateIndex) { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[stateIndex]; - return bytesCodeMapping.getValue(state.curPC); + var state = debugData.states[stateIndex]; + return codeMap[state.curPC]; } function highlightSelection(index) @@ -73,13 +87,10 @@ function highlightSelection(index) function completeCtxInformation(state) { - if (typeof(debugStates) === "undefined") - return; - currentStep.update(state.step); mem.update(state.newMemSize.value() + " " + qsTr("words")); stepCost.update(state.gasCost.value()); - gasSpent.update(debugStates[0].gas.subtract(state.gas).value()); + gasSpent.update(debugData.states[0].gas.subtract(state.gas).value()); stack.listModel = state.debugStack; storage.listModel = state.debugStorage; @@ -87,17 +98,8 @@ function completeCtxInformation(state) callDataDump.listModel = state.debugCallData; } -function displayReturnValue() -{ - headerReturnList.model = contractCallReturnParameters; - headerReturnList.update(); -} - function stepOutBack() { - if (typeof(debugStates) === "undefined") - return; - if (jumpStartingPoint != null) { select(jumpStartingPoint); @@ -114,15 +116,12 @@ function stepIntoBack() function stepOverBack() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMPDEST") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { for (var k = currentSelectedState; k > 0; k--) { - var line = bytesCodeMapping.getValue(debugStates[k].curPC); + var line = codeMap[debugData.states[k].curPC]; if (line === statesList.currentIndex - 2) { select(k); @@ -136,15 +135,12 @@ function stepOverBack() function stepOverForward() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMP") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { - for (var k = currentSelectedState; k < debugStates.length; k++) + for (var k = currentSelectedState; k < debugData.states.length; k++) { - var line = bytesCodeMapping.getValue(debugStates[k].curPC); + var line = codeMap[debugData.states[k].curPC]; if (line === statesList.currentIndex + 2) { select(k); @@ -158,11 +154,8 @@ function stepOverForward() function stepIntoForward() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMP") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { jumpStartingPoint = currentSelectedState; moveSelection(1); @@ -184,6 +177,5 @@ function stepOutForward() function jumpTo(value) { - currentSelectedState = value; - select(currentSelectedState); + select(value); } From f1a35dcaf071c14dac8e87f6a0183f8fac9a5825 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 01:02:41 +0100 Subject: [PATCH 3/5] bebugger bugfixes --- mix/DebuggingStateWrapper.cpp | 130 +++++++++++-------------------- mix/DebuggingStateWrapper.h | 6 -- mix/MixApplication.cpp | 2 +- mix/qml/Debugger.qml | 30 +++---- mix/qml/ItemDelegateDataDump.qml | 15 ---- mix/qml/StepActionImage.qml | 2 + mix/qml/html/codeeditor.js | 3 +- mix/qml/js/Debugger.js | 116 +++++++++++++-------------- 8 files changed, 120 insertions(+), 184 deletions(-) diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index c99ce9681..5a1812610 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -20,7 +20,7 @@ * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). */ -#include +#include #include #include #include @@ -36,6 +36,39 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; +namespace +{ + static QVariantList memDumpToList(bytes const& _bytes, unsigned _width) + { + QVariantList dumpList; + for (unsigned i = 0; i < _bytes.size(); i += _width) + { + std::stringstream ret; + + for (unsigned j = i; j < i + _width; ++j) + if (j < _bytes.size()) + if (_bytes[j] >= 32 && _bytes[j] < 127) + ret << (char)_bytes[j]; + else + ret << '?'; + else + ret << ' '; + QString strPart = QString::fromStdString(ret.str()); + + ret.clear(); + ret.str(std::string()); + + for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j) + ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " "; + QString hexPart = QString::fromStdString(ret.str()); + + QStringList line = { strPart, hexPart }; + dumpList.push_back(line); + } + return dumpList; + } +} + QCode* QMachineState::getHumanReadableCode(QObject* _owner, const bytes& _code) { QVariantList codeStr; @@ -86,7 +119,7 @@ QStringList QMachineState::debugStack() QStringList stack; for (std::vector::reverse_iterator i = m_state.stack.rbegin(); i != m_state.stack.rend(); ++i) stack.append(QString::fromStdString(prettyU256(*i))); - return fillList(stack, ""); + return stack; } QStringList QMachineState::debugStorage() @@ -95,95 +128,20 @@ QStringList QMachineState::debugStorage() for (auto const& i: m_state.storage) { std::stringstream s; - s << "@" << prettyU256(i.first) << " " << prettyU256(i.second); + s << "@" << prettyU256(i.first) << "\t" << prettyU256(i.second); storage.append(QString::fromStdString(s.str())); } - return fillList(storage, "@ -"); + return storage; } QVariantList QMachineState::debugMemory() { - std::vector> dump = memDumpToList(m_state.memory, 16); - QStringList filled; - filled.append(" "); - filled.append(" "); - filled.append(" "); - return fillList(qVariantDump(dump), QVariant(filled)); + return memDumpToList(m_state.memory, 16); } QCallData* QMachineState::getDebugCallData(QObject* _owner, bytes const& _data) { - std::vector> dump = memDumpToList(_data, 16); - QStringList filled; - filled.append(" "); - filled.append(" "); - filled.append(" "); - return new QCallData(_owner, fillList(qVariantDump(dump), QVariant(filled))); -} - -std::vector> QMachineState::memDumpToList(bytes const& _bytes, unsigned _width) -{ - std::vector> dump; - for (unsigned i = 0; i < _bytes.size(); i += _width) - { - std::stringstream ret; - std::vector dumpLine; - ret << std::hex << std::setw(4) << std::setfill('0') << i << " "; - dumpLine.push_back(ret.str()); - ret.str(std::string()); - ret.clear(); - - for (unsigned j = i; j < i + _width; ++j) - if (j < _bytes.size()) - if (_bytes[j] >= 32 && _bytes[j] < 127) - ret << (char)_bytes[j]; - else - ret << '?'; - else - ret << ' '; - dumpLine.push_back(ret.str()); - ret.str(std::string()); - ret.clear(); - - for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j) - ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " "; - dumpLine.push_back(ret.str()); - dump.push_back(dumpLine); - } - return dump; -} - -QVariantList QMachineState::qVariantDump(std::vector> const& _dump) -{ - QVariantList ret; - for (std::vector const& line: _dump) - { - QStringList qLine; - for (std::string const& cell: line) - qLine.push_back(QString::fromStdString(cell)); - ret.append(QVariant(qLine)); - } - return ret; -} - -QStringList QMachineState::fillList(QStringList& _list, QString const& _emptyValue) -{ - if (_list.size() < 20) - { - for (int k = _list.size(); k < 20 - _list.size(); k++) - _list.append(_emptyValue); - } - return _list; -} - -QVariantList QMachineState::fillList(QVariantList _list, QVariant const& _emptyValue) -{ - if (_list.size() < 20) - { - for (int k = _list.size(); k < 20 - _list.size(); k++) - _list.append(_emptyValue); - } - return _list; + return new QCallData(_owner, memDumpToList(_data, 16)); } QStringList QMachineState::levels() @@ -208,7 +166,7 @@ QString QMachineState::instruction() QString QMachineState::endOfDebug() { if (m_state.gasCost > m_state.gas) - return QApplication::tr("OUT-OF-GAS"); + return QObject::tr("OUT-OF-GAS"); else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) { unsigned from = (unsigned)m_state.stack.back(); @@ -217,12 +175,12 @@ QString QMachineState::endOfDebug() bytes out(size, 0); for (; o < size && from + o < m_state.memory.size(); ++o) out[o] = m_state.memory[from + o]; - return QApplication::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); + return QObject::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return QApplication::tr("STOP"); + return QObject::tr("STOP"); else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return QApplication::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return QObject::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else - return QApplication::tr("EXCEPTION"); + return QObject::tr("EXCEPTION"); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index d7591ea4e..8e83628f7 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -156,12 +156,6 @@ private: MachineState m_state; QCode* m_code; QCallData* m_callData; - static QStringList fillList(QStringList& _list, QString const& _emptyValue); - static QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); - static QVariantList qVariantDump(std::vector> const& _dump); - /// Nicely renders the given bytes to a string, store the content in an array. - /// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line. - static std::vector> memDumpToList(bytes const& _bytes, unsigned _width); }; } diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index 991859778..deff7c011 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -36,7 +36,7 @@ using namespace dev::mix; MixApplication::MixApplication(int _argc, char* _argv[]): QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()), m_appContext(new AppContext(m_engine.get())) { - setOrganizationName(tr("Ethreum")); + setOrganizationName(tr("Ethereum")); setOrganizationDomain(tr("ethereum.org")); setApplicationName(tr("Mix")); setApplicationVersion("0.1"); diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 11b6b6bf0..975a083ab 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -13,13 +13,6 @@ Rectangle { anchors.fill: parent; color: "#ededed" clip: true - Keys.onPressed: - { - if (event.key === Qt.Key_F10) - Debugger.moveSelection(1); - else if (event.key === Qt.Key_F9) - Debugger.moveSelection(-1); - } onVisibleChanged: { @@ -166,6 +159,7 @@ Rectangle { onClicked: Debugger.stepOutBack() width: 28 height: 30 + buttonShortcut: "Ctrl+Shift+F11" buttonTooltip: qsTr("Step Out Back") } @@ -177,6 +171,7 @@ Rectangle { onClicked: Debugger.stepIntoBack() width: 28 height: 30 + buttonShortcut: "Ctrl+F11" buttonTooltip: qsTr("Step Into Back") } @@ -188,6 +183,7 @@ Rectangle { onClicked: Debugger.stepOverBack() width: 28 height: 30 + buttonShortcut: "Ctrl+F10" buttonTooltip: qsTr("Step Over Back") } @@ -199,6 +195,7 @@ Rectangle { onClicked: Debugger.stepOverForward() width: 28 height: 30 + buttonShortcut: "F10" buttonTooltip: qsTr("Step Over Forward") } @@ -210,6 +207,7 @@ Rectangle { onClicked: Debugger.stepIntoForward() width: 28 height: 30 + buttonShortcut: "F11" buttonTooltip: qsTr("Step Into Forward") } @@ -221,6 +219,7 @@ Rectangle { onClicked: Debugger.stepOutForward() width: 28 height: 30 + buttonShortcut: "Shift+F11" buttonTooltip: qsTr("Step Out Forward") } } @@ -283,7 +282,7 @@ Rectangle { id: statesList delegate: renderDelegate highlight: highlightBar - highlightFollowsCurrentItem: false + //highlightFollowsCurrentItem: false model: ListModel {} } @@ -295,9 +294,9 @@ Rectangle { width: statesList.currentItem.width; y: statesList.currentItem.y color: "#4A90E2" - Behavior on y { - PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50} - } + //Behavior on y { + // PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50} + //} } } @@ -314,6 +313,7 @@ Rectangle { width: 15 color: "#b2b3ae" text: line.split(' ')[0] + font.family: "monospace" font.pointSize: 9 id: id wrapMode: Text.NoWrap @@ -321,6 +321,7 @@ Rectangle { Text { wrapMode: Text.NoWrap color: parent.ListView.isCurrentItem ? "white" : "black" + font.family: "monospace" text: line.replace(line.split(' ')[0], '') anchors.left: id.right font.pointSize: 9 @@ -481,8 +482,10 @@ Rectangle { font.family: "monospace" anchors.leftMargin: 5 color: "#4a4a4a" - text: modelData.split(' ')[0].substring(0, 10); + text: modelData.split('\t')[0]; font.pointSize: 9 + width: parent.width - 5 + elide: Text.ElideRight } } Rectangle @@ -502,7 +505,8 @@ Rectangle { font.family: "monospace" anchors.verticalCenter: parent.verticalCenter color: "#4a4a4a" - text: modelData.split(' ')[1].substring(0, 10); + text: modelData.split('\t')[1]; + elide: Text.ElideRight font.pointSize: 9 } } diff --git a/mix/qml/ItemDelegateDataDump.qml b/mix/qml/ItemDelegateDataDump.qml index 1c0ea183e..a57a61b03 100644 --- a/mix/qml/ItemDelegateDataDump.qml +++ b/mix/qml/ItemDelegateDataDump.qml @@ -49,21 +49,6 @@ Rectangle { font.pointSize: 8 } } - - Rectangle - { - Layout.fillWidth: true - Layout.minimumWidth: 50 - Layout.minimumHeight: parent.height - Text { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - font.family: "monospace" - color: "#4a4a4a" - text: modelData[2] - font.pointSize: 8 - } - } } Rectangle { diff --git a/mix/qml/StepActionImage.qml b/mix/qml/StepActionImage.qml index 64440aa83..a4ff23e54 100644 --- a/mix/qml/StepActionImage.qml +++ b/mix/qml/StepActionImage.qml @@ -9,6 +9,7 @@ Rectangle { property string disableStateImg property string enabledStateImg property string buttonTooltip + property string buttonShortcut signal clicked function enabled(state) @@ -33,6 +34,7 @@ Rectangle { Action { tooltip: buttonTooltip id: buttonAction + shortcut: buttonShortcut onTriggered: { buttonActionContainer.clicked(); } diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 325741158..2cebc121e 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -4,10 +4,11 @@ var editor = CodeMirror(document.body, { //styleActiveLine: true, matchBrackets: true, autofocus: true, - indentWithTabs: true, }); editor.setOption("theme", "solarized dark"); +editor.setOption("indentUnit", 4); +editor.setOption("indentWithTabs", true); editor.setOption("fullScreen", true); editor.changeRegistered = false; diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index 9f561b173..169f84db8 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -2,7 +2,6 @@ //statesList => ListView var currentSelectedState = null; -var jumpStartingPoint = null; var debugData = null; var codeMap = null; @@ -12,13 +11,14 @@ function init(data) jumpIntoBackAction.enabled(false); jumpIntoForwardAction.enabled(false); jumpOutForwardAction.enabled(false); + jumpOverBackAction.enabled(false); + jumpOverForwardAction.enabled(false); if (data === null) { statesList.model.clear(); statesSlider.maximumValue = 0; statesSlider.value = 0; currentSelectedState = null; - jumpStartingPoint = null; debugData = null; return; } @@ -40,6 +40,7 @@ function setupInstructions(stateIndex) { statesList.model.append(instructions[i]); codeMap[instructions[i].processIndex] = i; } + callDataDump.listModel = debugData.states[stateIndex].callData.items; } function moveSelection(incr) @@ -49,12 +50,15 @@ function moveSelection(incr) { if (currentSelectedState + incr < debugData.states.length) select(currentSelectedState + incr); - statesSlider.value = currentSelectedState; } } function select(stateIndex) { + if (stateIndex < 0) + stateIndex = 0; + if (stateIndex >= debugData.states.length) + stateIndex = debugData.state.length - 1; if (debugData.states[stateIndex].codeIndex !== debugData.states[currentSelectedState].codeIndex) setupInstructions(stateIndex); currentSelectedState = stateIndex; @@ -63,15 +67,13 @@ function select(stateIndex) highlightSelection(codeLine); completeCtxInformation(state); - if (state.instruction === "CALL" || state.instruction === "CREATE") - jumpIntoForwardAction.enabled(true); - else - jumpIntoForwardAction.enabled(false); - - if (state.instruction === "JUMPDEST") - jumpIntoBackAction.enabled(true); - else - jumpIntoBackAction.enabled(false); + statesSlider.value = currentSelectedState; + jumpIntoForwardAction.enabled(stateIndex < debugData.states.length - 1) + jumpIntoBackAction.enabled(stateIndex > 0); + jumpOverForwardAction.enabled(stateIndex < debugData.states.length - 1); + jumpOverBackAction.enabled(stateIndex > 0); + jumpOutBackAction.enabled(state.levels.length > 1); + jumpOutForwardAction.enabled(state.levels.length > 1); } function codeStr(stateIndex) @@ -83,6 +85,7 @@ function codeStr(stateIndex) function highlightSelection(index) { statesList.currentIndex = index; + statesList.positionViewAtIndex(index, ListView.Center); } function completeCtxInformation(state) @@ -95,18 +98,18 @@ function completeCtxInformation(state) stack.listModel = state.debugStack; storage.listModel = state.debugStorage; memoryDump.listModel = state.debugMemory; - callDataDump.listModel = state.debugCallData; } -function stepOutBack() +function isCallInstruction(index) { - if (jumpStartingPoint != null) - { - select(jumpStartingPoint); - jumpStartingPoint = null; - jumpOutBackAction.enabled(false); - jumpOutForwardAction.enabled(false); - } + var state = debugData.states[index]; + return state.instruction === "CALL" || state.instruction === "CREATE"; +} + +function isReturnInstruction(index) +{ + var state = debugData.states[index]; + return state.instruction === "RETURN" } function stepIntoBack() @@ -116,63 +119,52 @@ function stepIntoBack() function stepOverBack() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - for (var k = currentSelectedState; k > 0; k--) - { - var line = codeMap[debugData.states[k].curPC]; - if (line === statesList.currentIndex - 2) - { - select(k); - break; - } - } - } + if (currentSelectedState > 0 && isReturnInstruction(currentSelectedState - 1)) + stepOutBack(); else moveSelection(-1); } function stepOverForward() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - for (var k = currentSelectedState; k < debugData.states.length; k++) - { - var line = codeMap[debugData.states[k].curPC]; - if (line === statesList.currentIndex + 2) - { - select(k); - break; - } - } - } + if (isCallInstruction(currentSelectedState)) + stepOutForward(); else moveSelection(1); } function stepIntoForward() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - jumpStartingPoint = currentSelectedState; - moveSelection(1); - jumpOutBackAction.enabled(true); - jumpOutForwardAction.enabled(true); - } + moveSelection(1); +} + +function stepOutBack() +{ + var i = currentSelectedState - 1; + var depth = 0; + while (--i >= 0) + if (isCallInstruction(i)) + if (depth == 0) + break; + else depth--; + else if (isReturnInstruction(i)) + depth++; + select(i); } function stepOutForward() { - if (jumpStartingPoint != null) - { - stepOutBack(); - stepOverForward(); - jumpOutBackAction.enabled(false); - jumpOutForwardAction.enabled(false); - } + var i = currentSelectedState; + var depth = 0; + while (++i < debugData.states.length) + if (isReturnInstruction(i)) + if (depth == 0) + break; + else + depth--; + else if (isCallInstruction(i)) + depth++; + select(i + 1); } function jumpTo(value) From 47c4c0ecf665cf89a87a0a199456becea8bec291 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 01:08:24 +0100 Subject: [PATCH 4/5] enabled search in editor with Ctrl+F --- mix/qml/html/cm/dialog.css | 32 ++++++ mix/qml/html/cm/dialog.js | 155 ++++++++++++++++++++++++++ mix/qml/html/cm/search.js | 164 +++++++++++++++++++++++++++ mix/qml/html/cm/searchcursor.js | 189 ++++++++++++++++++++++++++++++++ mix/qml/html/codeeditor.html | 4 + mix/web.qrc | 4 + 6 files changed, 548 insertions(+) create mode 100644 mix/qml/html/cm/dialog.css create mode 100644 mix/qml/html/cm/dialog.js create mode 100644 mix/qml/html/cm/search.js create mode 100644 mix/qml/html/cm/searchcursor.js diff --git a/mix/qml/html/cm/dialog.css b/mix/qml/html/cm/dialog.css new file mode 100644 index 000000000..2e7c0fc9b --- /dev/null +++ b/mix/qml/html/cm/dialog.css @@ -0,0 +1,32 @@ +.CodeMirror-dialog { + position: absolute; + left: 0; right: 0; + background: white; + z-index: 15; + padding: .1em .8em; + overflow: hidden; + color: #333; +} + +.CodeMirror-dialog-top { + border-bottom: 1px solid #eee; + top: 0; +} + +.CodeMirror-dialog-bottom { + border-top: 1px solid #eee; + bottom: 0; +} + +.CodeMirror-dialog input { + border: none; + outline: none; + background: transparent; + width: 20em; + color: inherit; + font-family: monospace; +} + +.CodeMirror-dialog button { + font-size: 70%; +} diff --git a/mix/qml/html/cm/dialog.js b/mix/qml/html/cm/dialog.js new file mode 100644 index 000000000..e0e8ad4eb --- /dev/null +++ b/mix/qml/html/cm/dialog.js @@ -0,0 +1,155 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Open simple dialogs on top of an editor. Relies on dialog.css. + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + function dialogDiv(cm, template, bottom) { + var wrap = cm.getWrapperElement(); + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; + else + dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + + function closeNotification(cm, newVal) { + if (cm.state.currentNotificationClose) + cm.state.currentNotificationClose(); + cm.state.currentNotificationClose = newVal; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + if (!options) options = {}; + + closeNotification(this, null); + + var dialog = dialogDiv(this, template, options.bottom); + var closed = false, me = this; + function close(newVal) { + if (typeof newVal == 'string') { + inp.value = newVal; + } else { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + + if (options.onClose) options.onClose(dialog); + } + } + + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + if (options.value) { + inp.value = options.value; + inp.select(); + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); + CodeMirror.e_stop(e); + close(); + } + if (e.keyCode == 13) callback(inp.value, e); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + + inp.focus(); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } + return close; + }); + + CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { + closeNotification(this, null); + var dialog = dialogDiv(this, template, options && options.bottom); + var buttons = dialog.getElementsByTagName("button"); + var closed = false, me = this, blurring = 1; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + } + buttons[0].focus(); + for (var i = 0; i < buttons.length; ++i) { + var b = buttons[i]; + (function(callback) { + CodeMirror.on(b, "click", function(e) { + CodeMirror.e_preventDefault(e); + close(); + if (callback) callback(me); + }); + })(callbacks[i]); + CodeMirror.on(b, "blur", function() { + --blurring; + setTimeout(function() { if (blurring <= 0) close(); }, 200); + }); + CodeMirror.on(b, "focus", function() { ++blurring; }); + } + }); + + /* + * openNotification + * Opens a notification, that can be closed with an optional timer + * (default 5000ms timer) and always closes on click. + * + * If a notification is opened while another is opened, it will close the + * currently opened one and open the new one immediately. + */ + CodeMirror.defineExtension("openNotification", function(template, options) { + closeNotification(this, close); + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; + + function close() { + if (closed) return; + closed = true; + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); + } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + + return close; + }); +}); diff --git a/mix/qml/html/cm/search.js b/mix/qml/html/cm/search.js new file mode 100644 index 000000000..0251067a7 --- /dev/null +++ b/mix/qml/html/cm/search.js @@ -0,0 +1,164 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Define search commands. Depends on dialog.js or another +// implementation of the openDialog method. + +// Replace works a little oddly -- it will do the replace on the next +// Ctrl-G (or whatever is bound to findNext) press. You prevent a +// replace by making sure the match is no longer selected when hitting +// Ctrl-G. + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + function searchOverlay(query, caseInsensitive) { + if (typeof query == "string") + query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); + else if (!query.global) + query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); + + return {token: function(stream) { + query.lastIndex = stream.pos; + var match = query.exec(stream.string); + if (match && match.index == stream.pos) { + stream.pos += match[0].length; + return "searching"; + } else if (match) { + stream.pos = match.index; + } else { + stream.skipToEnd(); + } + }}; + } + + function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.overlay = null; + } + function getSearchState(cm) { + return cm.state.search || (cm.state.search = new SearchState()); + } + function queryCaseInsensitive(query) { + return typeof query == "string" && query == query.toLowerCase(); + } + function getSearchCursor(cm, query, pos) { + // Heuristic: if the query string is all lowercase, do a case insensitive search. + return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); + } + function dialog(cm, text, shortText, deflt, f) { + if (cm.openDialog) cm.openDialog(text, f, {value: deflt}); + else f(prompt(shortText, deflt)); + } + function confirmDialog(cm, text, shortText, fs) { + if (cm.openConfirm) cm.openConfirm(text, fs); + else if (confirm(shortText)) fs[0](); + } + function parseQuery(query) { + var isRE = query.match(/^\/(.*)\/([a-z]*)$/); + if (isRE) { + try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } + catch(e) {} // Not a regular expression after all, do a string search + } + if (typeof query == "string" ? query == "" : query.test("")) + query = /x^/; + return query; + } + var queryDialog = + 'Search: (Use /re/ syntax for regexp search)'; + function doSearch(cm, rev) { + var state = getSearchState(cm); + if (state.query) return findNext(cm, rev); + dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) { + cm.operation(function() { + if (!query || state.query) return; + state.query = parseQuery(query); + cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); + state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); + cm.addOverlay(state.overlay); + if (cm.showMatchesOnScrollbar) { + if (state.annotate) { state.annotate.clear(); state.annotate = null; } + state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); + } + state.posFrom = state.posTo = cm.getCursor(); + findNext(cm, rev); + }); + }); + } + function findNext(cm, rev) {cm.operation(function() { + var state = getSearchState(cm); + var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); + if (!cursor.find(rev)) { + cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); + if (!cursor.find(rev)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); + state.posFrom = cursor.from(); state.posTo = cursor.to(); + });} + function clearSearch(cm) {cm.operation(function() { + var state = getSearchState(cm); + if (!state.query) return; + state.query = null; + cm.removeOverlay(state.overlay); + if (state.annotate) { state.annotate.clear(); state.annotate = null; } + });} + + var replaceQueryDialog = + 'Replace: (Use /re/ syntax for regexp search)'; + var replacementQueryDialog = 'With: '; + var doReplaceConfirm = "Replace? "; + function replace(cm, all) { + if (cm.getOption("readOnly")) return; + dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) { + if (!query) return; + query = parseQuery(query); + dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) { + if (all) { + cm.operation(function() { + for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { + if (typeof query != "string") { + var match = cm.getRange(cursor.from(), cursor.to()).match(query); + cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); + } else cursor.replace(text); + } + }); + } else { + clearSearch(cm); + var cursor = getSearchCursor(cm, query, cm.getCursor()); + var advance = function() { + var start = cursor.from(), match; + if (!(match = cursor.findNext())) { + cursor = getSearchCursor(cm, query); + if (!(match = cursor.findNext()) || + (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); + confirmDialog(cm, doReplaceConfirm, "Replace?", + [function() {doReplace(match);}, advance]); + }; + var doReplace = function(match) { + cursor.replace(typeof query == "string" ? text : + text.replace(/\$(\d)/g, function(_, i) {return match[i];})); + advance(); + }; + advance(); + } + }); + }); + } + + CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; + CodeMirror.commands.findNext = doSearch; + CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; + CodeMirror.commands.clearSearch = clearSearch; + CodeMirror.commands.replace = replace; + CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; +}); diff --git a/mix/qml/html/cm/searchcursor.js b/mix/qml/html/cm/searchcursor.js new file mode 100644 index 000000000..55c108b5a --- /dev/null +++ b/mix/qml/html/cm/searchcursor.js @@ -0,0 +1,189 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + var Pos = CodeMirror.Pos; + + function SearchCursor(doc, query, pos, caseFold) { + this.atOccurrence = false; this.doc = doc; + if (caseFold == null && typeof query == "string") caseFold = false; + + pos = pos ? doc.clipPos(pos) : Pos(0, 0); + this.pos = {from: pos, to: pos}; + + // The matches method is filled in based on the type of query. + // It takes a position and a direction, and returns an object + // describing the next occurrence of the query, or null if no + // more matches were found. + if (typeof query != "string") { // Regexp match + if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g"); + this.matches = function(reverse, pos) { + if (reverse) { + query.lastIndex = 0; + var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start; + for (;;) { + query.lastIndex = cutOff; + var newMatch = query.exec(line); + if (!newMatch) break; + match = newMatch; + start = match.index; + cutOff = match.index + (match[0].length || 1); + if (cutOff == line.length) break; + } + var matchLen = (match && match[0].length) || 0; + if (!matchLen) { + if (start == 0 && line.length == 0) {match = undefined;} + else if (start != doc.getLine(pos.line).length) { + matchLen++; + } + } + } else { + query.lastIndex = pos.ch; + var line = doc.getLine(pos.line), match = query.exec(line); + var matchLen = (match && match[0].length) || 0; + var start = match && match.index; + if (start + matchLen != line.length && !matchLen) matchLen = 1; + } + if (match && matchLen) + return {from: Pos(pos.line, start), + to: Pos(pos.line, start + matchLen), + match: match}; + }; + } else { // String query + var origQuery = query; + if (caseFold) query = query.toLowerCase(); + var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;}; + var target = query.split("\n"); + // Different methods for single-line and multi-line queries + if (target.length == 1) { + if (!query.length) { + // Empty string would match anything and never progress, so + // we define it to match nothing instead. + this.matches = function() {}; + } else { + this.matches = function(reverse, pos) { + if (reverse) { + var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig); + var match = line.lastIndexOf(query); + if (match > -1) { + match = adjustPos(orig, line, match); + return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; + } + } else { + var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig); + var match = line.indexOf(query); + if (match > -1) { + match = adjustPos(orig, line, match) + pos.ch; + return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; + } + } + }; + } + } else { + var origTarget = origQuery.split("\n"); + this.matches = function(reverse, pos) { + var last = target.length - 1; + if (reverse) { + if (pos.line - (target.length - 1) < doc.firstLine()) return; + if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return; + var to = Pos(pos.line, origTarget[last].length); + for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln) + if (target[i] != fold(doc.getLine(ln))) return; + var line = doc.getLine(ln), cut = line.length - origTarget[0].length; + if (fold(line.slice(cut)) != target[0]) return; + return {from: Pos(ln, cut), to: to}; + } else { + if (pos.line + (target.length - 1) > doc.lastLine()) return; + var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length; + if (fold(line.slice(cut)) != target[0]) return; + var from = Pos(pos.line, cut); + for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln) + if (target[i] != fold(doc.getLine(ln))) return; + if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return; + return {from: from, to: Pos(ln, origTarget[last].length)}; + } + }; + } + } + } + + SearchCursor.prototype = { + findNext: function() {return this.find(false);}, + findPrevious: function() {return this.find(true);}, + + find: function(reverse) { + var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to); + function savePosAndFail(line) { + var pos = Pos(line, 0); + self.pos = {from: pos, to: pos}; + self.atOccurrence = false; + return false; + } + + for (;;) { + if (this.pos = this.matches(reverse, pos)) { + this.atOccurrence = true; + return this.pos.match || true; + } + if (reverse) { + if (!pos.line) return savePosAndFail(0); + pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length); + } + else { + var maxLine = this.doc.lineCount(); + if (pos.line == maxLine - 1) return savePosAndFail(maxLine); + pos = Pos(pos.line + 1, 0); + } + } + }, + + from: function() {if (this.atOccurrence) return this.pos.from;}, + to: function() {if (this.atOccurrence) return this.pos.to;}, + + replace: function(newText) { + if (!this.atOccurrence) return; + var lines = CodeMirror.splitLines(newText); + this.doc.replaceRange(lines, this.pos.from, this.pos.to); + this.pos.to = Pos(this.pos.from.line + lines.length - 1, + lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)); + } + }; + + // Maps a position in a case-folded line back to a position in the original line + // (compensating for codepoints increasing in number during folding) + function adjustPos(orig, folded, pos) { + if (orig.length == folded.length) return pos; + for (var pos1 = Math.min(pos, orig.length);;) { + var len1 = orig.slice(0, pos1).toLowerCase().length; + if (len1 < pos) ++pos1; + else if (len1 > pos) --pos1; + else return pos1; + } + } + + CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this.doc, query, pos, caseFold); + }); + CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this, query, pos, caseFold); + }); + + CodeMirror.defineExtension("selectMatches", function(query, caseFold) { + var ranges = [], next; + var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold); + while (next = cur.findNext()) { + if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break; + ranges.push({anchor: cur.from(), head: cur.to()}); + } + if (ranges.length) + this.setSelections(ranges, 0); + }); +}); diff --git a/mix/qml/html/codeeditor.html b/mix/qml/html/codeeditor.html index ea278983f..994656cb7 100644 --- a/mix/qml/html/codeeditor.html +++ b/mix/qml/html/codeeditor.html @@ -3,6 +3,7 @@ + @@ -12,5 +13,8 @@ + + + diff --git a/mix/web.qrc b/mix/web.qrc index 073df5f8b..e71e5b7c5 100644 --- a/mix/web.qrc +++ b/mix/web.qrc @@ -17,5 +17,9 @@ qml/html/cm/htmlmixed.js qml/html/cm/css.js qml/html/cm/solidity.js + qml/html/cm/dialog.css + qml/html/cm/dialog.js + qml/html/cm/search.js + qml/html/cm/searchcursor.js From 2137b75c239303a590aa51c28fd7630a5c2b5618 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 01:34:34 +0100 Subject: [PATCH 5/5] added some commets --- mix/DebuggingStateWrapper.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 8e83628f7..ac25dd57a 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -53,6 +53,9 @@ private: int m_processIndex; }; +/** + * @brief Shared container for lines + */ class QCode: public QObject { Q_OBJECT @@ -65,6 +68,9 @@ private: QVariantList m_instructions; }; +/** + * @brief Shared container for call data + */ class QCallData: public QObject { Q_OBJECT @@ -77,6 +83,9 @@ private: QVariantList m_items; }; +/** + * @brief Shared container for machine states + */ class QDebugData: public QObject { Q_OBJECT @@ -91,7 +100,7 @@ private: }; /** - * @brief Wrap DebuggingState in QObject + * @brief Wrap MachineState in QObject */ class QMachineState: public QObject {