diff options
Diffstat (limited to 'src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp')
-rw-r--r-- | src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp new file mode 100644 index 0000000..37634c8 --- /dev/null +++ b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp @@ -0,0 +1,430 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSCriptTools module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qscriptdebuggerscriptedconsolecommand_p.h" +#include "qscriptdebuggerconsolecommand_p_p.h" +#include "qscriptdebuggerconsolecommandjob_p.h" +#include "qscriptdebuggerconsolecommandjob_p_p.h" +#include "qscriptmessagehandlerinterface_p.h" +#include "qscriptdebuggerconsoleglobalobject_p.h" +#include "qscriptdebuggerresponse_p.h" +#include "qscriptdebuggercommandschedulerinterface_p.h" + +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> +#include <QtScript/qscriptengine.h> +#include <QtScript/qscriptvalue.h> +#include <QtScript/qscriptvalueiterator.h> +#include <QtScript/qscriptcontextinfo.h> +#include <QtCore/qdebug.h> + +Q_DECLARE_METATYPE(QScriptDebuggerResponse) + +QT_BEGIN_NAMESPACE + +/*! + \since 4.5 + \class QScriptDebuggerScriptedConsoleCommand + \internal + + \brief The QScriptDebuggerScriptedConsoleCommand class encapsulates a command defined in a script. +*/ + +class QScriptDebuggerScriptedConsoleCommandPrivate + : public QScriptDebuggerConsoleCommandPrivate +{ + Q_DECLARE_PUBLIC(QScriptDebuggerScriptedConsoleCommand) +public: + QScriptDebuggerScriptedConsoleCommandPrivate(); + ~QScriptDebuggerScriptedConsoleCommandPrivate(); + + QString name; + QString group; + QString shortDescription; + QString longDescription; + QStringList aliases; + QStringList seeAlso; + QStringList argumentTypes; + QStringList subCommands; + QScriptValue globalObject; + QScriptValue execFunction; + QScriptValue responseFunction; +}; + +QScriptDebuggerScriptedConsoleCommandPrivate::QScriptDebuggerScriptedConsoleCommandPrivate() +{ +} + +QScriptDebuggerScriptedConsoleCommandPrivate::~QScriptDebuggerScriptedConsoleCommandPrivate() +{ +} + +QScriptDebuggerScriptedConsoleCommand::QScriptDebuggerScriptedConsoleCommand( + const QString &name, const QString &group, + const QString &shortDescription, const QString &longDescription, + const QStringList &aliases, const QStringList &seeAlso, + const QStringList &argumentTypes, const QStringList &subCommands, + const QScriptValue &globalObject, + const QScriptValue &execFunction, const QScriptValue &responseFunction) + : QScriptDebuggerConsoleCommand(*new QScriptDebuggerScriptedConsoleCommandPrivate) +{ + Q_D(QScriptDebuggerScriptedConsoleCommand); + d->name = name; + d->group = group; + d->shortDescription = shortDescription; + d->longDescription = longDescription; + d->aliases = aliases; + d->seeAlso = seeAlso; + d->argumentTypes = argumentTypes; + d->subCommands = subCommands; + d->globalObject = globalObject; + d->execFunction = execFunction; + d->responseFunction = responseFunction; +} + +QScriptDebuggerScriptedConsoleCommand::~QScriptDebuggerScriptedConsoleCommand() +{ +} + +class QScriptDebuggerScriptedConsoleCommandJobPrivate; +class QScriptDebuggerScriptedConsoleCommandJob + : public QScriptDebuggerConsoleCommandJob, + public QScriptDebuggerCommandSchedulerInterface +{ +public: + QScriptDebuggerScriptedConsoleCommandJob( + QScriptDebuggerScriptedConsoleCommandPrivate *command, + const QStringList &arguments, + QScriptDebuggerConsole *console, + QScriptMessageHandlerInterface *messageHandler, + QScriptDebuggerCommandSchedulerInterface *commandScheduler); + ~QScriptDebuggerScriptedConsoleCommandJob(); + + int scheduleCommand( + const QScriptDebuggerCommand &command, + QScriptDebuggerResponseHandlerInterface *responseHandler); + + void start(); + void handleResponse(const QScriptDebuggerResponse &response, + int commandId); + +private: + Q_DECLARE_PRIVATE(QScriptDebuggerScriptedConsoleCommandJob) + Q_DISABLE_COPY(QScriptDebuggerScriptedConsoleCommandJob) +}; + +class QScriptDebuggerScriptedConsoleCommandJobPrivate + : public QScriptDebuggerConsoleCommandJobPrivate +{ +public: + QScriptDebuggerScriptedConsoleCommandJobPrivate() : command(0), commandCount(0) {} + ~QScriptDebuggerScriptedConsoleCommandJobPrivate() {} + + QScriptDebuggerScriptedConsoleCommandPrivate *command; + QStringList arguments; + int commandCount; +}; + +QScriptDebuggerScriptedConsoleCommandJob::QScriptDebuggerScriptedConsoleCommandJob( + QScriptDebuggerScriptedConsoleCommandPrivate *command, + const QStringList &arguments, + QScriptDebuggerConsole *console, + QScriptMessageHandlerInterface *messageHandler, + QScriptDebuggerCommandSchedulerInterface *commandScheduler) + : QScriptDebuggerConsoleCommandJob(*new QScriptDebuggerScriptedConsoleCommandJobPrivate, + console, messageHandler, commandScheduler) +{ + Q_D(QScriptDebuggerScriptedConsoleCommandJob); + d->command = command; + d->arguments = arguments; +} + +QScriptDebuggerScriptedConsoleCommandJob::~QScriptDebuggerScriptedConsoleCommandJob() +{ +} + +int QScriptDebuggerScriptedConsoleCommandJob::scheduleCommand( + const QScriptDebuggerCommand &command, + QScriptDebuggerResponseHandlerInterface *responseHandler) +{ + Q_D(QScriptDebuggerScriptedConsoleCommandJob); + ++d->commandCount; + return commandScheduler()->scheduleCommand(command, responseHandler); +} + +void QScriptDebuggerScriptedConsoleCommandJob::start() +{ + Q_D(QScriptDebuggerScriptedConsoleCommandJob); + QScriptEngine *engine = d->command->globalObject.engine(); + engine->setGlobalObject(d->command->globalObject); + QScriptValueList args; + for (int i = 0; i < d->arguments.size(); ++i) + args.append(QScriptValue(engine, d->arguments.at(i))); + QScriptDebuggerConsoleGlobalObject *global; + global = qobject_cast<QScriptDebuggerConsoleGlobalObject*>(engine->globalObject().toQObject()); + Q_ASSERT(global != 0); + global->setScheduler(this); + global->setResponseHandler(this); + global->setMessageHandler(d->messageHandler); + global->setConsole(d->console); + d->commandCount = 0; + QScriptValue ret = d->command->execFunction.call(QScriptValue(), args); + global->setScheduler(0); + global->setResponseHandler(0); + global->setMessageHandler(0); + global->setConsole(0); + if (ret.isError()) { + qWarning("*** internal error: %s", qPrintable(ret.toString())); + } + if (d->commandCount == 0) + finish(); +} + +void QScriptDebuggerScriptedConsoleCommandJob::handleResponse( + const QScriptDebuggerResponse &response, + int commandId) +{ + Q_D(QScriptDebuggerScriptedConsoleCommandJob); + // ### generalize + QScriptEngine *engine = d->command->globalObject.engine(); + engine->setGlobalObject(d->command->globalObject); + QScriptValueList args; + args.append(engine->toScriptValue(response)); + args.append(QScriptValue(engine, commandId)); + QScriptDebuggerConsoleGlobalObject *global; + global = qobject_cast<QScriptDebuggerConsoleGlobalObject*>(d->command->globalObject.toQObject()); + Q_ASSERT(global != 0); + global->setScheduler(this); + global->setResponseHandler(this); + global->setMessageHandler(d->messageHandler); + global->setConsole(d->console); + d->commandCount = 0; + QScriptValue ret = d->command->responseFunction.call(QScriptValue(), args); + global->setScheduler(0); + global->setResponseHandler(0); + global->setMessageHandler(0); + global->setConsole(0); + if (ret.isError()) { + qWarning("*** internal error: %s", qPrintable(ret.toString())); + } + if (d->commandCount == 0) + finish(); +} + +/*! + \internal +*/ +QString QScriptDebuggerScriptedConsoleCommand::name() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->name; +} + +/*! + \internal +*/ +QString QScriptDebuggerScriptedConsoleCommand::group() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->group; +} + +/*! + \internal +*/ +QString QScriptDebuggerScriptedConsoleCommand::shortDescription() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->shortDescription; +} + +/*! + \internal +*/ +QString QScriptDebuggerScriptedConsoleCommand::longDescription() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->longDescription; +} + +/*! + \internal +*/ +QStringList QScriptDebuggerScriptedConsoleCommand::aliases() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->aliases; +} + +/*! + \internal +*/ +QStringList QScriptDebuggerScriptedConsoleCommand::seeAlso() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->seeAlso; +} + +/*! + \internal +*/ +QStringList QScriptDebuggerScriptedConsoleCommand::argumentTypes() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->argumentTypes; +} + +/*! + \internal +*/ +QStringList QScriptDebuggerScriptedConsoleCommand::subCommands() const +{ + Q_D(const QScriptDebuggerScriptedConsoleCommand); + return d->subCommands; +} + +/*! + \internal +*/ +QScriptDebuggerConsoleCommandJob *QScriptDebuggerScriptedConsoleCommand::createJob( + const QStringList &arguments, + QScriptDebuggerConsole *console, + QScriptMessageHandlerInterface *messageHandler, + QScriptDebuggerCommandSchedulerInterface *commandScheduler) +{ + Q_D(QScriptDebuggerScriptedConsoleCommand); + return new QScriptDebuggerScriptedConsoleCommandJob( + d, arguments, console, messageHandler, commandScheduler); +} + +/*! + Parses a command defined by the given \a program. + Returns an object that encapsulates the command, or 0 if parsing failed. +*/ +QScriptDebuggerScriptedConsoleCommand *QScriptDebuggerScriptedConsoleCommand::parse( + const QString &program, const QString &fileName, + QScriptEngine *engine, QScriptMessageHandlerInterface *messageHandler) +{ + // create a custom global object + QScriptDebuggerConsoleGlobalObject *cppGlobal = new QScriptDebuggerConsoleGlobalObject(); + QScriptValue global = engine->newQObject(cppGlobal, + QScriptEngine::ScriptOwnership, + QScriptEngine::ExcludeSuperClassContents); + { + QScriptValueIterator it(engine->globalObject()); + while (it.hasNext()) { + it.next(); + global.setProperty(it.scriptName(), it.value(), it.flags()); + } + } + engine->setGlobalObject(global); + + cppGlobal->setMessageHandler(messageHandler); + QScriptValue ret = engine->evaluate(program, fileName); + cppGlobal->setMessageHandler(0); + if (engine->hasUncaughtException()) { + messageHandler->message(QtCriticalMsg, ret.toString(), fileName, + engine->uncaughtExceptionLineNumber()); + return 0; + } + + QScriptValue name = global.property(QLatin1String("name")); + if (!name.isString()) { + messageHandler->message(QtCriticalMsg, QLatin1String("command definition lacks a name"), fileName); + return 0; + } + QString nameStr = name.toString(); + + QScriptValue group = global.property(QLatin1String("group")); + if (!group.isString()) { + messageHandler->message(QtCriticalMsg, QString::fromLatin1("definition of command \"%0\" lacks a group name") + .arg(nameStr), fileName); + return 0; + } + QString groupStr = group.toString(); + + QScriptValue shortDesc = global.property(QLatin1String("shortDescription")); + if (!shortDesc.isString()) { + messageHandler->message(QtCriticalMsg, QString::fromLatin1("definition of command \"%0\" lacks shortDescription") + .arg(nameStr), fileName); + return 0; + } + QString shortDescStr = shortDesc.toString(); + + QScriptValue longDesc = global.property(QLatin1String("longDescription")); + if (!longDesc.isString()) { + messageHandler->message(QtCriticalMsg, QString::fromLatin1("definition of command \"%0\" lacks longDescription") + .arg(nameStr), fileName); + return 0; + } + QString longDescStr = longDesc.toString(); + + QStringList aliases; + qScriptValueToSequence(global.property(QLatin1String("aliases")), aliases); + + QStringList seeAlso; + qScriptValueToSequence(global.property(QLatin1String("seeAlso")), seeAlso); + + QStringList argTypes; + qScriptValueToSequence(global.property(QLatin1String("argumentTypes")), argTypes); + + QStringList subCommands; + qScriptValueToSequence(global.property(QLatin1String("subCommands")), subCommands); + + QScriptValue execFunction = global.property(QLatin1String("execute")); + if (!execFunction.isFunction()) { + messageHandler->message(QtCriticalMsg, QString::fromLatin1("definition of command \"%0\" lacks execute() function") + .arg(nameStr), fileName); + return 0; + } + + QScriptValue responseFunction = global.property(QLatin1String("handleResponse")); + + QScriptDebuggerScriptedConsoleCommand *result = new QScriptDebuggerScriptedConsoleCommand( + nameStr, groupStr, + shortDescStr, longDescStr, + aliases, seeAlso, + argTypes, subCommands, + global, execFunction, responseFunction); + return result; +} + +QT_END_NAMESPACE |