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

Last change on this file since 573 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 11.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtSCriptTools module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia 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(QLatin1String(", "));
167 msg.append(completions.at(j));
168 }
169 msg.append(QLatin1Char('.'));
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}
203
204void QScriptDebuggerConsole::loadScriptedCommands(const QString &scriptsPath,
205 QScriptMessageHandlerInterface *messageHandler)
206{
207 Q_D(QScriptDebuggerConsole);
208 d->loadScriptedCommands(scriptsPath, messageHandler);
209}
210
211QScriptDebuggerConsoleCommandManager *QScriptDebuggerConsole::commandManager() const
212{
213 Q_D(const QScriptDebuggerConsole);
214 return d->commandManager;
215}
216
217bool QScriptDebuggerConsole::hasIncompleteInput() const
218{
219 Q_D(const QScriptDebuggerConsole);
220 return !d->input.isEmpty();
221}
222
223QString QScriptDebuggerConsole::incompleteInput() const
224{
225 Q_D(const QScriptDebuggerConsole);
226 return d->input;
227}
228
229void QScriptDebuggerConsole::setIncompleteInput(const QString &input)
230{
231 Q_D(QScriptDebuggerConsole);
232 d->input = input;
233}
234
235QString QScriptDebuggerConsole::commandPrefix() const
236{
237 Q_D(const QScriptDebuggerConsole);
238 return d->commandPrefix;
239}
240
241/*!
242 Consumes the given line of \a input. If the input starts with the
243 command prefix, it is regarded as a debugger command; otherwise the
244 input is evaluated as a plain script.
245*/
246QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsole::consumeInput(
247 const QString &input, QScriptMessageHandlerInterface *messageHandler,
248 QScriptDebuggerCommandSchedulerInterface *commandScheduler)
249{
250 Q_D(QScriptDebuggerConsole);
251 static const int maximumHistoryCount = 100;
252 QString cmd;
253 if (d->input.isEmpty() && input.isEmpty()) {
254 if (d->commandHistory.isEmpty())
255 return 0;
256 cmd = d->commandHistory.first();
257 } else {
258 cmd = input;
259 }
260 if (d->input.isEmpty() && cmd.startsWith(d->commandPrefix)) {
261 if (!input.isEmpty()) {
262 d->commandHistory.prepend(cmd);
263 if (d->commandHistory.size() > maximumHistoryCount)
264 d->commandHistory.removeLast();
265 }
266 cmd.remove(0, d->commandPrefix.length());
267 return d->createJob(cmd, messageHandler, commandScheduler);
268 }
269 d->input += cmd;
270 d->input += QLatin1Char('\n');
271 QScriptSyntaxCheckResult check = QScriptEngine::checkSyntax(d->input);
272 if (check.state() == QScriptSyntaxCheckResult::Intermediate)
273 return false;
274 d->input.chop(1); // remove the last \n
275 cmd = QString();
276 cmd.append(d->commandPrefix);
277 cmd.append(QString::fromLatin1("eval "));
278 cmd.append(d->input);
279 d->commandHistory.prepend(cmd);
280 if (d->commandHistory.size() > maximumHistoryCount)
281 d->commandHistory.removeLast();
282 d->input.clear();
283 cmd.remove(0, d->commandPrefix.length());
284 return d->createJob(cmd, messageHandler, commandScheduler);
285}
286
287int QScriptDebuggerConsole::currentFrameIndex() const
288{
289 Q_D(const QScriptDebuggerConsole);
290 return d->currentFrameIndex;
291}
292
293void QScriptDebuggerConsole::setCurrentFrameIndex(int index)
294{
295 Q_D(QScriptDebuggerConsole);
296 d->currentFrameIndex = index;
297}
298
299qint64 QScriptDebuggerConsole::currentScriptId() const
300{
301 Q_D(const QScriptDebuggerConsole);
302 return d->currentScriptId;
303}
304
305void QScriptDebuggerConsole::setCurrentScriptId(qint64 id)
306{
307 Q_D(QScriptDebuggerConsole);
308 d->currentScriptId = id;
309}
310
311int QScriptDebuggerConsole::currentLineNumber() const
312{
313 Q_D(const QScriptDebuggerConsole);
314 return d->currentLineNumber;
315}
316
317void QScriptDebuggerConsole::setCurrentLineNumber(int lineNumber)
318{
319 Q_D(QScriptDebuggerConsole);
320 d->currentLineNumber = lineNumber;
321}
322
323int QScriptDebuggerConsole::evaluateAction() const
324{
325 Q_D(const QScriptDebuggerConsole);
326 return d->evaluateAction;
327}
328
329void QScriptDebuggerConsole::setEvaluateAction(int action)
330{
331 Q_D(QScriptDebuggerConsole);
332 d->evaluateAction = action;
333}
334
335qint64 QScriptDebuggerConsole::sessionId() const
336{
337 Q_D(const QScriptDebuggerConsole);
338 return d->sessionId;
339}
340
341void QScriptDebuggerConsole::bumpSessionId()
342{
343 Q_D(QScriptDebuggerConsole);
344 ++d->sessionId;
345}
346
347void QScriptDebuggerConsole::showDebuggerInfoMessage(
348 QScriptMessageHandlerInterface *messageHandler)
349{
350 messageHandler->message(
351 QtDebugMsg,
352 QString::fromLatin1(
353 "Welcome to the Qt Script debugger.\n"
354 "Debugger commands start with a . (period).\n"
355 "Any other input will be evaluated by the script interpreter.\n"
356 "Type \".help\" for help.\n"));
357}
358
359/*!
360 \reimp
361*/
362int QScriptDebuggerConsole::historyCount() const
363{
364 Q_D(const QScriptDebuggerConsole);
365 return d->commandHistory.size();
366}
367
368/*!
369 \reimp
370*/
371QString QScriptDebuggerConsole::historyAt(int index) const
372{
373 Q_D(const QScriptDebuggerConsole);
374 return d->commandHistory.value(index);
375}
376
377/*!
378 \reimp
379*/
380void QScriptDebuggerConsole::changeHistoryAt(int index, const QString &newHistory)
381{
382 Q_D(QScriptDebuggerConsole);
383 d->commandHistory[index] = newHistory;
384}
385
386QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.