/****************************************************************************
**
** Copyright (C) 2010 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(qScriptValueFromValue(engine, 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