diff options
author | hjk <qtc-committer@nokia.com> | 2010-07-09 17:07:59 +0200 |
---|---|---|
committer | hjk <qtc-committer@nokia.com> | 2010-07-14 17:49:16 +0200 |
commit | e760700f0fea2f9a25cdbbbc1af52a446be4b183 (patch) | |
tree | 7a5ac650129e16119e1f076c27262311e4f22982 /src/plugins/debugger/script/scriptengine.cpp | |
parent | 6089bc1b9e046b9b1b36dc64ed7920467909ebe8 (diff) | |
download | qt-creator-e760700f0fea2f9a25cdbbbc1af52a446be4b183.tar.gz |
debugger: overhaul "state machine"
This mainly allows for more precise shutdown and tightens the set
of allowed transitions.
Diffstat (limited to 'src/plugins/debugger/script/scriptengine.cpp')
-rw-r--r-- | src/plugins/debugger/script/scriptengine.cpp | 153 |
1 files changed, 88 insertions, 65 deletions
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index cbc9f9d96a..1de6c32618 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -65,7 +65,7 @@ #include <QtScript/QScriptValue> #include <QtScript/QScriptValueIterator> -#define DEBUG_SCRIPT 1 +//#define DEBUG_SCRIPT 1 #if DEBUG_SCRIPT # define SDEBUG(s) qDebug() << s #else @@ -101,34 +101,44 @@ public: int baseLineNumber); void scriptUnload(qint64 id); + void showMessage(const QString &msg); + private: void maybeBreakNow(bool byFunction); ScriptEngine *q; + int m_depth; + int m_contextDepth; }; ScriptAgent::ScriptAgent(ScriptEngine *debugger, QScriptEngine *script) - : QScriptEngineAgent(script), q(debugger) + : QScriptEngineAgent(script), q(debugger), m_depth(0), m_contextDepth(0) {} +void ScriptAgent::showMessage(const QString &msg) +{ + SDEBUG(msg); + q->showMessage(msg, LogMisc); +} + void ScriptAgent::contextPop() { - SDEBUG("ScriptAgent::contextPop: "); + //showMessage(_("ContextPop: %1").arg(m_contextDepth)); + --m_contextDepth; } void ScriptAgent::contextPush() { - SDEBUG("ScriptAgent::contextPush: "); + ++m_contextDepth; + //showMessage(_("ContextPush: %1 ").arg(m_contextDepth)); } void ScriptAgent::exceptionCatch(qint64 scriptId, const QScriptValue & exception) { Q_UNUSED(scriptId) Q_UNUSED(exception) - const QString msg = QString::fromLatin1("An exception was caught on %1: '%2'"). - arg(scriptId).arg(exception.toString()); - SDEBUG(msg); - q->showMessage(msg, LogMisc); + showMessage(_("An exception was caught on %1: '%2'"). + arg(scriptId).arg(exception.toString())); } void ScriptAgent::exceptionThrow(qint64 scriptId, const QScriptValue &exception, @@ -137,16 +147,15 @@ void ScriptAgent::exceptionThrow(qint64 scriptId, const QScriptValue &exception, Q_UNUSED(scriptId) Q_UNUSED(exception) Q_UNUSED(hasHandler) - const QString msg = QString::fromLatin1("An exception occurred on %1: '%2'"). - arg(scriptId).arg(exception.toString()); - SDEBUG(msg); - q->showMessage(msg, LogMisc); + showMessage(_("An exception occurred on %1: '%2'"). + arg(scriptId).arg(exception.toString())); } void ScriptAgent::functionEntry(qint64 scriptId) { Q_UNUSED(scriptId) - q->showMessage(QString::fromLatin1("Function entry occurred on %1").arg(scriptId), LogMisc); + ++m_depth; + //showMessage(_("Function entry occurred on %1, depth: %2").arg(scriptId)); q->checkForBreakCondition(true); } @@ -154,17 +163,17 @@ void ScriptAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue) { Q_UNUSED(scriptId) Q_UNUSED(returnValue) - const QString msg = QString::fromLatin1("Function exit occurred on %1: '%2'").arg(scriptId).arg(returnValue.toString()); - SDEBUG(msg); - q->showMessage(msg, LogMisc); + --m_depth; + //showMessage(_("Function exit occurred on %1: '%2'"). + // arg(scriptId).arg(returnValue.toString())); } void ScriptAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber) { - SDEBUG("ScriptAgent::position: " << lineNumber); Q_UNUSED(scriptId) Q_UNUSED(lineNumber) Q_UNUSED(columnNumber) + //showMessage(_("Position: %1").arg(lineNumber)); q->checkForBreakCondition(false); } @@ -175,14 +184,13 @@ void ScriptAgent::scriptLoad(qint64 scriptId, const QString &program, Q_UNUSED(program) Q_UNUSED(fileName) Q_UNUSED(baseLineNumber) - q->showMessage(QString::fromLatin1("Loaded: %1 id: %2") - .arg(fileName).arg(scriptId), LogMisc); + showMessage(_("Loaded: %1 id: %2").arg(fileName).arg(scriptId)); } void ScriptAgent::scriptUnload(qint64 scriptId) { Q_UNUSED(scriptId) - SDEBUG("ScriptAgent::scriptUnload: " << scriptId); + showMessage(_("Unload script id %1 ").arg(scriptId)); } @@ -207,37 +215,36 @@ void ScriptEngine::executeDebuggerCommand(const QString &command) XSDEBUG("FIXME: ScriptEngine::executeDebuggerCommand()"); } -void ScriptEngine::shutdown() +void ScriptEngine::shutdownInferior() { - exitDebugger(); -} - -void ScriptEngine::exitDebugger() -{ - if (state() == DebuggerNotReady) - return; - SDEBUG("ScriptEngine::exitDebugger()"); + QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); + SDEBUG("ScriptEngine::shutdownInferior()"); + m_scriptEngine->setAgent(0); + //m_scriptAgent.reset(0); m_stopped = false; m_stopOnNextLine = false; if (m_scriptEngine->isEvaluating()) m_scriptEngine->abortEvaluation(); - setState(InferiorShuttingDown); - setState(InferiorShutDown); + notifyInferiorShutdownOk(); +} - setState(EngineShuttingDown); +void ScriptEngine::shutdownEngine() +{ + QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); m_scriptEngine->setAgent(0); - setState(DebuggerNotReady); + notifyEngineShutdownOk(); } void ScriptEngine::setupEngine() { - QTC_ASSERT(state() == EngineSettingUp, qDebug() << state()); + QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); showMessage(_("STARTING SCRIPT DEBUGGER"), LogMisc); if (m_scriptEngine.isNull()) m_scriptEngine = Core::ICore::instance()->scriptManager()->scriptEngine(); - if (!m_scriptAgent) - m_scriptAgent.reset(new ScriptAgent(this, m_scriptEngine.data())); + QTC_ASSERT(!m_scriptAgent, /**/); + m_scriptAgent.reset(new ScriptAgent(this, m_scriptEngine.data())); m_scriptEngine->setAgent(m_scriptAgent.data()); + //m_scriptEngine->setAgent(new ScriptAgent(this, m_scriptEngine.data())); /* Keep the gui alive (have the engine call processEvents() while the script * is run in the foreground). */ m_scriptEngine->setProcessEventsInterval(1 /*ms*/); @@ -251,12 +258,12 @@ void ScriptEngine::setupEngine() void ScriptEngine::setupInferior() { - QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state()); + QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); m_scriptFileName = QFileInfo(startParameters().executable).absoluteFilePath(); showMessage(_("SCRIPT FILE: ") + m_scriptFileName); QFile scriptFile(m_scriptFileName); if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) { - showMessage(QString::fromLatin1("Cannot open %1: %2"). + showMessage(_("Cannot open %1: %2"). arg(m_scriptFileName, scriptFile.errorString()), LogError); notifyEngineSetupFailed(); return; @@ -270,6 +277,8 @@ void ScriptEngine::setupInferior() void ScriptEngine::continueInferior() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); SDEBUG("ScriptEngine::continueInferior()"); m_stopped = false; m_stopOnNextLine = false; @@ -280,7 +289,7 @@ static const char *qtExtensionsC[] = { "qt.sql", "qt.opengl", "qt.webkit", "qt.xmlpatterns", "qt.uitools" }; -bool ScriptEngine::importExtensions() +void ScriptEngine::importExtensions() { SDEBUG("ScriptEngine::importExtensions()"); QStringList extensions; @@ -288,11 +297,11 @@ bool ScriptEngine::importExtensions() for (int e = 0; e < extCount; e++) extensions.append(QLatin1String(qtExtensionsC[e])); if (m_scriptEngine->importedExtensions().contains(extensions.front())) - return true; + return; // true; QDir dir(QLatin1String("/home/apoenitz/dev/qtscriptgenerator")); if (!dir.cd(QLatin1String("plugins"))) { fprintf(stderr, "plugins folder does not exist -- did you build the bindings?\n"); - return false; + return; // false; } QStringList paths = qApp->libraryPaths(); paths << dir.absolutePath(); @@ -319,45 +328,43 @@ bool ScriptEngine::importExtensions() qPrintable(failExtensions.join(QLatin1String(", "))), qPrintable(dir.absolutePath())); } } - return failExtensions.isEmpty(); + return; // failExtensions.isEmpty(); } void ScriptEngine::runEngine() { - QTC_ASSERT(state() == InferiorSetupOk, qDebug() << state()); - setState(InferiorRunningRequested); + QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); + SDEBUG("ScriptEngine::runEngine()"); + notifyEngineRunAndInferiorRunOk(); showStatusMessage(tr("Running requested..."), 5000); showMessage(QLatin1String("Running: ") + m_scriptFileName, LogMisc); - SDEBUG("ScriptEngine::runEngine()"); importExtensions(); - setState(InferiorRunning); const QScriptValue result = m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName); - setState(InferiorStopping); - setState(InferiorStopped); QString msg; if (m_scriptEngine->hasUncaughtException()) { - msg = QString::fromLatin1("An exception occurred during execution at line: %1\n%2\n") + msg = _("An exception occurred during execution at line: %1\n%2\n") .arg(m_scriptEngine->uncaughtExceptionLineNumber()) .arg(m_scriptEngine->uncaughtException().toString()); msg += m_scriptEngine->uncaughtExceptionBacktrace() .join(QString(QLatin1Char('\n'))); } else { - msg = QString::fromLatin1("Evaluation returns '%1'") - .arg(result.toString()); + msg = _("Evaluation returns '%1'").arg(result.toString()); } showMessage(msg, LogMisc); - exitDebugger(); + showMessage(_("This was the outermost function.")); + notifyInferiorExited(); } void ScriptEngine::interruptInferior() { - m_stopped = false; m_stopOnNextLine = true; XSDEBUG("ScriptEngine::interruptInferior()"); } void ScriptEngine::executeStep() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); //SDEBUG("ScriptEngine::stepExec()"); m_stopped = false; m_stopOnNextLine = true; @@ -365,6 +372,8 @@ void ScriptEngine::executeStep() void ScriptEngine::executeStepI() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); //SDEBUG("ScriptEngine::stepIExec()"); m_stopped = false; m_stopOnNextLine = true; @@ -372,6 +381,8 @@ void ScriptEngine::executeStepI() void ScriptEngine::executeStepOut() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); //SDEBUG("ScriptEngine::stepOutExec()"); m_stopped = false; m_stopOnNextLine = true; @@ -379,6 +390,8 @@ void ScriptEngine::executeStepOut() void ScriptEngine::executeNext() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); //SDEBUG("ScriptEngine::nextExec()"); m_stopped = false; m_stopOnNextLine = true; @@ -386,6 +399,8 @@ void ScriptEngine::executeNext() void ScriptEngine::executeNextI() { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); //SDEBUG("ScriptEngine::nextIExec()"); m_stopped = false; m_stopOnNextLine = true; @@ -393,6 +408,8 @@ void ScriptEngine::executeNextI() void ScriptEngine::executeRunToLine(const QString &fileName, int lineNumber) { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); Q_UNUSED(fileName) Q_UNUSED(lineNumber) SDEBUG("FIXME: ScriptEngine::runToLineExec()"); @@ -400,12 +417,16 @@ void ScriptEngine::executeRunToLine(const QString &fileName, int lineNumber) void ScriptEngine::executeRunToFunction(const QString &functionName) { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); Q_UNUSED(functionName) XSDEBUG("FIXME: ScriptEngine::runToFunctionExec()"); } void ScriptEngine::executeJumpToLine(const QString &fileName, int lineNumber) { + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + notifyInferiorRunRequested(); Q_UNUSED(fileName) Q_UNUSED(lineNumber) XSDEBUG("FIXME: ScriptEngine::jumpToLineExec()"); @@ -481,7 +502,7 @@ void ScriptEngine::setToolTipExpression(const QPoint &mousePos, Q_UNUSED(editor) Q_UNUSED(cursorPos) - if (state() != InferiorStopped) { + if (state() != InferiorStopOk) { //SDEBUG("SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED"); return; } @@ -537,7 +558,7 @@ void ScriptEngine::setToolTipExpression(const QPoint &mousePos, } #if 0 - //if (m_manager->status() != InferiorStopped) + //if (m_manager->status() != InferiorStopOk) // return; // FIXME: 'exp' can contain illegal characters @@ -591,6 +612,11 @@ static BreakpointData *findBreakPointByFileName(BreakHandler *handler, bool ScriptEngine::checkForBreakCondition(bool byFunction) { + // FIXME: Should that ever happen after setAgent(0) in shutdownInferior()? + // In practice, it does, so chicken out. + if (targetState() == DebuggerFinished) + return false; + const QScriptContext *context = m_scriptEngine->currentContext(); const QScriptContextInfo info(context); @@ -599,7 +625,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) const QString fileName = info.fileName(); const int lineNumber = byFunction ? info.functionStartLineNumber() : info.lineNumber(); - SDEBUG("checkForBreakCondition" << byFunction << functionName + SDEBUG(Q_FUNC_INFO << byFunction << functionName << lineNumber << fileName); if (m_stopOnNextLine) { // Interrupt inferior @@ -627,8 +653,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) data->pending = false; data->updateMarker(); } - setState(InferiorStopping); - setState(InferiorStopped); + notifyInferiorSpontaneousStop(); SDEBUG("Stopped at " << lineNumber << fileName); showStatusMessage(tr("Stopped at %1:%2.").arg(fileName).arg(lineNumber), 5000); @@ -644,7 +669,7 @@ void ScriptEngine::updateLocals() { QScriptContext *context = m_scriptEngine->currentContext(); watchHandler()->beginCycle(); - //SDEBUG("UPDATE LOCALS"); + SDEBUG(Q_FUNC_INFO); // // Build stack @@ -674,24 +699,22 @@ void ScriptEngine::updateLocals() WatchData data; data.iname = "local"; - data.name = QString::fromLatin1(data.iname); + data.name = _(data.iname); data.scriptValue = context->activationObject(); watchHandler()->beginCycle(); updateSubItem(data); watchHandler()->endCycle(); - // FIXME: Use an extra thread. This here is evil + // FIXME: Use an extra thread. This here is evil. m_stopped = true; showStatusMessage(tr("Stopped."), 5000); while (m_stopped) { //SDEBUG("LOOPING"); QApplication::processEvents(); } - setState(InferiorRunningRequested); - setState(InferiorRunning); // Clear any exceptions occurred during locals evaluation. m_scriptEngine->clearExceptions(); m_scriptEngine->setAgent(m_scriptAgent.data()); - SDEBUG("Continuing"); + notifyInferiorRunOk(); } void ScriptEngine::updateWatchData(const WatchData &data) @@ -713,7 +736,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0) { WatchData data = data0; QList<WatchData> children; - SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString()); + //SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString()); QTC_ASSERT(data.isValid(), return); if (data.isTypeNeeded() || data.isValueNeeded()) { |