summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/script/scriptengine.cpp
diff options
context:
space:
mode:
authorhjk <qtc-committer@nokia.com>2010-07-09 17:07:59 +0200
committerhjk <qtc-committer@nokia.com>2010-07-14 17:49:16 +0200
commite760700f0fea2f9a25cdbbbc1af52a446be4b183 (patch)
tree7a5ac650129e16119e1f076c27262311e4f22982 /src/plugins/debugger/script/scriptengine.cpp
parent6089bc1b9e046b9b1b36dc64ed7920467909ebe8 (diff)
downloadqt-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.cpp153
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()) {