source: trunk/src/scripttools/debugging/qscriptdebuggerconsole.cpp@ 160

Last change on this file since 160 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtSCriptTools module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptdebuggerconsole_p.h"
43#include "qscriptdebuggerconsolecommandjob_p.h"
44#include "qscriptdebuggerconsolecommandmanager_p.h"
45#include "qscriptdebuggerscriptedconsolecommand_p.h"
46#include "qscriptmessagehandlerinterface_p.h"
47
48#include <QtCore/qdir.h>
49#include <QtCore/qfileinfo.h>
50#include <QtCore/qstring.h>
51#include <QtCore/qstringlist.h>
52#include <QtCore/qdebug.h>
53#include <QtScript/qscriptengine.h>
54
55QT_BEGIN_NAMESPACE
56
57/*!
58 \since 4.5
59 \class QScriptDebuggerConsole
60 \internal
61
62 \brief The QScriptDebuggerConsole class provides the core functionality of a debugger console.
63*/
64
65class QScriptDebuggerConsolePrivate
66{
67 Q_DECLARE_PUBLIC(QScriptDebuggerConsole)
68public:
69 QScriptDebuggerConsolePrivate(QScriptDebuggerConsole*);
70 ~QScriptDebuggerConsolePrivate();
71
72 void loadScriptedCommands(const QString &scriptsPath,
73 QScriptMessageHandlerInterface *messageHandler);
74 QScriptDebuggerConsoleCommandJob *createJob(
75 const QString &command,
76 QScriptMessageHandlerInterface *messageHandler,
77 QScriptDebuggerCommandSchedulerInterface *commandScheduler);
78
79 QScriptDebuggerConsoleCommandManager *commandManager;
80 QString commandPrefix;
81 QString input;
82 QStringList commandHistory;
83 int currentFrameIndex;
84 qint64 currentScriptId;
85 int currentLineNumber;
86 int evaluateAction;
87 qint64 sessionId;
88
89 QScriptDebuggerConsole *q_ptr;
90};
91
92QScriptDebuggerConsolePrivate::QScriptDebuggerConsolePrivate(QScriptDebuggerConsole* parent)
93 : q_ptr(parent)
94{
95 sessionId = 0;
96 currentFrameIndex = 0;
97 currentScriptId = -1;
98 currentLineNumber = -1;
99 evaluateAction = 0;
100 commandPrefix = QLatin1String(".");
101 commandManager = new QScriptDebuggerConsoleCommandManager();
102}
103
104QScriptDebuggerConsolePrivate::~QScriptDebuggerConsolePrivate()
105{
106 delete commandManager;
107}
108
109/*!
110 Loads command definitions from scripts located in the given \a scriptsPath.
111*/
112void QScriptDebuggerConsolePrivate::loadScriptedCommands(
113 const QString &scriptsPath,
114 QScriptMessageHandlerInterface *messageHandler)
115{
116 QDir dir(scriptsPath);
117 QFileInfoList entries = dir.entryInfoList(QStringList()
118 << QLatin1String("*.qs"));
119 for (int i = 0; i < entries.size(); ++i) {
120 const QFileInfo &fi = entries.at(i);
121 QString fileName = fi.fileName();
122 QFile file(scriptsPath + QLatin1Char('/') + fileName);
123 if (!file.open(QIODevice::ReadOnly))
124 continue;
125 QTextStream stream(&file);
126 QString program = stream.readAll();
127 QScriptDebuggerScriptedConsoleCommand *command;
128 command = QScriptDebuggerScriptedConsoleCommand::parse(
129 program, fileName, messageHandler);
130 if (!command)
131 continue;
132 commandManager->addCommand(command);
133 }
134}
135
136
137/*!
138 Creates a job that will execute the given debugger \a command.
139 Returns the new job, or 0 if the command is undefined.
140*/
141QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsolePrivate::createJob(
142 const QString &command, QScriptMessageHandlerInterface *messageHandler,
143 QScriptDebuggerCommandSchedulerInterface *commandScheduler)
144{
145 QString name;
146 int i = command.indexOf(QLatin1Char(' '));
147 if (i == -1) {
148 name = command;
149 i = name.size();
150 } else {
151 name = command.left(i);
152 }
153 if (name.isEmpty())
154 return 0;
155 QScriptDebuggerConsoleCommand *cmd = commandManager->findCommand(name);
156 if (!cmd) {
157 // try to auto-complete
158 QStringList completions = commandManager->completions(name);
159 if (!completions.isEmpty()) {
160 if (completions.size() > 1) {
161 QString msg;
162 msg.append(QString::fromLatin1("Ambiguous command \"%0\": ")
163 .arg(name));
164 for (int j = 0; j < completions.size(); ++j) {
165 if (j > 0)
166 msg.append(QString::fromLatin1(", "));
167 msg.append(completions.at(j));
168 }
169 msg.append(QString::fromLatin1("."));
170 messageHandler->message(QtWarningMsg, msg);
171 return 0;
172 }
173 cmd = commandManager->findCommand(completions.at(0));
174 Q_ASSERT(cmd != 0);
175 }
176 if (!cmd) {
177 messageHandler->message(
178 QtWarningMsg,
179 QString::fromLatin1("Undefined command \"%0\". Try \"help\".")
180 .arg(name));
181 return 0;
182 }
183 }
184 QStringList args;
185 QString tmp = command.mid(i+1);
186 if (cmd->argumentTypes().contains(QString::fromLatin1("script"))) {
187 if (!tmp.isEmpty())
188 args.append(tmp);
189 } else {
190 args = tmp.split(QLatin1Char(' '), QString::SkipEmptyParts);
191 }
192 return cmd->createJob(args, q_func(), messageHandler, commandScheduler);
193}
194
195QScriptDebuggerConsole::QScriptDebuggerConsole()
196 : d_ptr(new QScriptDebuggerConsolePrivate(this))
197{
198}
199
200QScriptDebuggerConsole::~QScriptDebuggerConsole()
201{
202 delete d_ptr;
203}
204
205void QScriptDebuggerConsole::loadScriptedCommands(const QString &scriptsPath,
206 QScriptMessageHandlerInterface *messageHandler)
207{
208 Q_D(QScriptDebuggerConsole);
209 d->loadScriptedCommands(scriptsPath, messageHandler);
210}
211
212QScriptDebuggerConsoleCommandManager *QScriptDebuggerConsole::commandManager() const
213{
214 Q_D(const QScriptDebuggerConsole);
215 return d->commandManager;
216}
217
218bool QScriptDebuggerConsole::hasIncompleteInput() const
219{
220 Q_D(const QScriptDebuggerConsole);
221 return !d->input.isEmpty();
222}
223
224QString QScriptDebuggerConsole::incompleteInput() const
225{
226 Q_D(const QScriptDebuggerConsole);
227 return d->input;
228}
229
230void QScriptDebuggerConsole::setIncompleteInput(const QString &input)
231{
232 Q_D(QScriptDebuggerConsole);
233 d->input = input;
234}
235
236QString QScriptDebuggerConsole::commandPrefix() const
237{
238 Q_D(const QScriptDebuggerConsole);
239 return d->commandPrefix;
240}
241
242/*!
243 Consumes the given line of \a input. If the input starts with the
244 command prefix, it is regarded as a debugger command; otherwise the
245 input is evaluated as a plain script.
246*/
247QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsole::consumeInput(
248 const QString &input, QScriptMessageHandlerInterface *messageHandler,
249 QScriptDebuggerCommandSchedulerInterface *commandScheduler)
250{
251 Q_D(QScriptDebuggerConsole);
252 static const int maximumHistoryCount = 100;
253 QString cmd;
254 if (d->input.isEmpty() && input.isEmpty()) {
255 if (d->commandHistory.isEmpty())
256 return 0;
257 cmd = d->commandHistory.first();
258 } else {
259 cmd = input;
260 }
261 if (d->input.isEmpty() && cmd.startsWith(d->commandPrefix)) {
262 if (!input.isEmpty()) {
263 d->commandHistory.prepend(cmd);
264 if (d->commandHistory.size() > maximumHistoryCount)
265 d->commandHistory.removeLast();
266 }
267 cmd.remove(0, d->commandPrefix.length());
268 return d->createJob(cmd, messageHandler, commandScheduler);
269 }
270 d->input += cmd;
271 d->input += QLatin1Char('\n');
272 QScriptSyntaxCheckResult check = QScriptEngine::checkSyntax(d->input);
273 if (check.state() == QScriptSyntaxCheckResult::Intermediate)
274 return false;
275 d->input.chop(1); // remove the last \n
276 cmd = QString();
277 cmd.append(d->commandPrefix);
278 cmd.append(QString::fromLatin1("eval "));
279 cmd.append(d->input);
280 d->commandHistory.prepend(cmd);
281 if (d->commandHistory.size() > maximumHistoryCount)
282 d->commandHistory.removeLast();
283 d->input.clear();
284 cmd.remove(0, d->commandPrefix.length());
285 return d->createJob(cmd, messageHandler, commandScheduler);
286}
287
288int QScriptDebuggerConsole::currentFrameIndex() const
289{
290 Q_D(const QScriptDebuggerConsole);
291 return d->currentFrameIndex;
292}
293
294void QScriptDebuggerConsole::setCurrentFrameIndex(int index)
295{
296 Q_D(QScriptDebuggerConsole);
297 d->currentFrameIndex = index;
298}
299
300qint64 QScriptDebuggerConsole::currentScriptId() const
301{
302 Q_D(const QScriptDebuggerConsole);
303 return d->currentScriptId;
304}
305
306void QScriptDebuggerConsole::setCurrentScriptId(qint64 id)
307{
308 Q_D(QScriptDebuggerConsole);
309 d->currentScriptId = id;
310}
311
312int QScriptDebuggerConsole::currentLineNumber() const
313{
314 Q_D(const QScriptDebuggerConsole);
315 return d->currentLineNumber;
316}
317
318void QScriptDebuggerConsole::setCurrentLineNumber(int lineNumber)
319{
320 Q_D(QScriptDebuggerConsole);
321 d->currentLineNumber = lineNumber;
322}
323
324int QScriptDebuggerConsole::evaluateAction() const
325{
326 Q_D(const QScriptDebuggerConsole);
327 return d->evaluateAction;
328}
329
330void QScriptDebuggerConsole::setEvaluateAction(int action)
331{
332 Q_D(QScriptDebuggerConsole);
333 d->evaluateAction = action;
334}
335
336qint64 QScriptDebuggerConsole::sessionId() const
337{
338 Q_D(const QScriptDebuggerConsole);
339 return d->sessionId;
340}
341
342void QScriptDebuggerConsole::bumpSessionId()
343{
344 Q_D(QScriptDebuggerConsole);
345 ++d->sessionId;
346}
347
348void QScriptDebuggerConsole::showDebuggerInfoMessage(
349 QScriptMessageHandlerInterface *messageHandler)
350{
351 messageHandler->message(
352 QtDebugMsg,
353 QString::fromLatin1(
354 "Welcome to the Qt Script debugger.\n"
355 "Debugger commands start with a . (period).\n"
356 "Any other input will be evaluated by the script interpreter.\n"
357 "Type \".help\" for help.\n"));
358}
359
360/*!
361 \reimp
362*/
363int QScriptDebuggerConsole::historyCount() const
364{
365 Q_D(const QScriptDebuggerConsole);
366 return d->commandHistory.size();
367}
368
369/*!
370 \reimp
371*/
372QString QScriptDebuggerConsole::historyAt(int index) const
373{
374 Q_D(const QScriptDebuggerConsole);
375 return d->commandHistory.value(index);
376}
377
378/*!
379 \reimp
380*/
381void QScriptDebuggerConsole::changeHistoryAt(int index, const QString &newHistory)
382{
383 Q_D(QScriptDebuggerConsole);
384 d->commandHistory[index] = newHistory;
385}
386
387QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.