1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2018 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtSCriptTools module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qscriptdebuggerconsole_p.h" |
41 | #include "qscriptdebuggerconsolecommandjob_p.h" |
42 | #include "qscriptdebuggerconsolecommandmanager_p.h" |
43 | #include "qscriptdebuggerscriptedconsolecommand_p.h" |
44 | #include "qscriptmessagehandlerinterface_p.h" |
45 | #include "qscriptbreakpointdata_p.h" |
46 | #include "qscriptdebuggerresponse_p.h" |
47 | #include "qscriptdebuggervalueproperty_p.h" |
48 | #include "qscriptscriptdata_p.h" |
49 | |
50 | #include <QtCore/qdir.h> |
51 | #include <QtCore/qfileinfo.h> |
52 | #include <QtCore/qstring.h> |
53 | #include <QtCore/qstringlist.h> |
54 | #include <QtCore/qdebug.h> |
55 | #include <QtScript/qscriptcontextinfo.h> |
56 | #include <QtScript/qscriptengine.h> |
57 | |
58 | Q_DECLARE_METATYPE(QScriptDebuggerResponse) |
59 | Q_DECLARE_METATYPE(QScriptBreakpointData) |
60 | Q_DECLARE_METATYPE(QScriptBreakpointMap) |
61 | Q_DECLARE_METATYPE(QScriptScriptData) |
62 | Q_DECLARE_METATYPE(QScriptScriptMap) |
63 | Q_DECLARE_METATYPE(QScriptContextInfo) |
64 | Q_DECLARE_METATYPE(QScriptDebuggerValue) |
65 | Q_DECLARE_METATYPE(QScriptDebuggerValueProperty) |
66 | Q_DECLARE_METATYPE(QScriptDebuggerValuePropertyList) |
67 | Q_DECLARE_METATYPE(QScriptDebuggerConsoleCommand*) |
68 | Q_DECLARE_METATYPE(QScriptDebuggerConsoleCommandList) |
69 | Q_DECLARE_METATYPE(QScriptDebuggerConsoleCommandGroupData) |
70 | Q_DECLARE_METATYPE(QScriptDebuggerConsoleCommandGroupMap) |
71 | |
72 | QT_BEGIN_NAMESPACE |
73 | |
74 | static QScriptValue debuggerResponseToScriptValue(QScriptEngine *eng, const QScriptDebuggerResponse &in) |
75 | { |
76 | QScriptValue out = eng->newObject(); |
77 | out.setProperty(name: QString::fromLatin1(str: "result" ), value: eng->toScriptValue(value: in.result())); |
78 | out.setProperty(name: QString::fromLatin1(str: "error" ), value: QScriptValue(eng, in.error())); |
79 | out.setProperty(name: QString::fromLatin1(str: "async" ), value: QScriptValue(eng, in.async())); |
80 | return out; |
81 | } |
82 | |
83 | static void debuggerResponseFromScriptValue(const QScriptValue &, QScriptDebuggerResponse &) |
84 | { |
85 | Q_ASSERT(0); |
86 | } |
87 | |
88 | static QScriptValue breakpointDataToScriptValue(QScriptEngine *eng, const QScriptBreakpointData &in) |
89 | { |
90 | QScriptValue out = eng->newObject(); |
91 | out.setProperty(name: QString::fromLatin1(str: "scriptId" ), value: QScriptValue(eng, qsreal(in.scriptId()))); |
92 | out.setProperty(name: QString::fromLatin1(str: "fileName" ), value: QScriptValue(eng, in.fileName())); |
93 | out.setProperty(name: QString::fromLatin1(str: "lineNumber" ), value: QScriptValue(eng, in.lineNumber())); |
94 | out.setProperty(name: QString::fromLatin1(str: "enabled" ), value: QScriptValue(eng, in.isEnabled())); |
95 | out.setProperty(name: QString::fromLatin1(str: "singleShot" ), value: QScriptValue(eng, in.isSingleShot())); |
96 | out.setProperty(name: QString::fromLatin1(str: "ignoreCount" ), value: QScriptValue(eng, in.ignoreCount())); |
97 | out.setProperty(name: QString::fromLatin1(str: "condition" ), value: QScriptValue(eng, in.condition())); |
98 | return out; |
99 | } |
100 | |
101 | static void breakpointDataFromScriptValue(const QScriptValue &in, QScriptBreakpointData &out) |
102 | { |
103 | QScriptValue scriptId = in.property(name: QString::fromLatin1(str: "scriptId" )); |
104 | if (scriptId.isValid()) |
105 | out.setScriptId((qint64)scriptId.toNumber()); |
106 | out.setFileName(in.property(name: QString::fromLatin1(str: "fileName" )).toString()); |
107 | out.setLineNumber(in.property(name: QString::fromLatin1(str: "lineNumber" )).toInt32()); |
108 | QScriptValue enabled = in.property(name: QString::fromLatin1(str: "enabled" )); |
109 | if (enabled.isValid()) |
110 | out.setEnabled(enabled.toBoolean()); |
111 | QScriptValue singleShot = in.property(name: QString::fromLatin1(str: "singleShot" )); |
112 | if (singleShot.isValid()) |
113 | out.setSingleShot(singleShot.toBoolean()); |
114 | out.setIgnoreCount(in.property(name: QString::fromLatin1(str: "ignoreCount" )).toInt32()); |
115 | out.setCondition(in.property(name: QString::fromLatin1(str: "condition" )).toString()); |
116 | } |
117 | |
118 | static QScriptValue breakpointMapToScriptValue(QScriptEngine *eng, const QScriptBreakpointMap &in) |
119 | { |
120 | QScriptValue out = eng->newObject(); |
121 | QScriptBreakpointMap::const_iterator it; |
122 | for (it = in.constBegin(); it != in.constEnd(); ++it) { |
123 | out.setProperty(name: QString::number(it.key()), value: eng->toScriptValue(value: it.value())); |
124 | } |
125 | return out; |
126 | } |
127 | |
128 | static void breakpointMapFromScriptValue(const QScriptValue &, QScriptBreakpointMap &) |
129 | { |
130 | Q_ASSERT(0); |
131 | } |
132 | |
133 | static QScriptValue scriptDataToScriptValue(QScriptEngine *eng, const QScriptScriptData &in) |
134 | { |
135 | QScriptValue out = eng->newObject(); |
136 | out.setProperty(name: QString::fromLatin1(str: "contents" ), value: QScriptValue(eng, in.contents())); |
137 | out.setProperty(name: QString::fromLatin1(str: "fileName" ), value: QScriptValue(eng, in.fileName())); |
138 | out.setProperty(name: QString::fromLatin1(str: "baseLineNumber" ), value: QScriptValue(eng, in.baseLineNumber())); |
139 | return out; |
140 | } |
141 | |
142 | static void scriptDataFromScriptValue(const QScriptValue &in, QScriptScriptData &out) |
143 | { |
144 | QString contents = in.property(name: QString::fromLatin1(str: "contents" )).toString(); |
145 | QString fileName = in.property(name: QString::fromLatin1(str: "fileName" )).toString(); |
146 | int baseLineNumber = in.property(name: QString::fromLatin1(str: "baseLineNumber" )).toInt32(); |
147 | QScriptScriptData tmp(contents, fileName, baseLineNumber); |
148 | out = tmp; |
149 | } |
150 | |
151 | static QScriptValue scriptMapToScriptValue(QScriptEngine *eng, const QScriptScriptMap &in) |
152 | { |
153 | QScriptValue out = eng->newObject(); |
154 | QScriptScriptMap::const_iterator it; |
155 | for (it = in.constBegin(); it != in.constEnd(); ++it) { |
156 | out.setProperty(name: QString::number(it.key()), value: eng->toScriptValue(value: it.value())); |
157 | } |
158 | return out; |
159 | } |
160 | |
161 | static void scriptMapFromScriptValue(const QScriptValue &, QScriptScriptMap &) |
162 | { |
163 | Q_ASSERT(0); |
164 | } |
165 | |
166 | static QScriptValue consoleCommandToScriptValue( |
167 | QScriptEngine *eng, QScriptDebuggerConsoleCommand* const &in) |
168 | { |
169 | if (!in) |
170 | return eng->undefinedValue(); |
171 | QScriptValue out = eng->newObject(); |
172 | out.setProperty(name: QString::fromLatin1(str: "name" ), value: QScriptValue(eng, in->name())); |
173 | out.setProperty(name: QString::fromLatin1(str: "group" ), value: QScriptValue(eng, in->group())); |
174 | out.setProperty(name: QString::fromLatin1(str: "shortDescription" ), value: QScriptValue(eng, in->shortDescription())); |
175 | out.setProperty(name: QString::fromLatin1(str: "longDescription" ), value: QScriptValue(eng, in->longDescription())); |
176 | out.setProperty(name: QString::fromLatin1(str: "aliases" ), value: eng->toScriptValue(value: in->aliases())); |
177 | out.setProperty(name: QString::fromLatin1(str: "seeAlso" ), value: eng->toScriptValue(value: in->seeAlso())); |
178 | return out; |
179 | } |
180 | |
181 | static void consoleCommandFromScriptValue( |
182 | const QScriptValue &, QScriptDebuggerConsoleCommand* &) |
183 | { |
184 | Q_ASSERT(0); |
185 | } |
186 | |
187 | static QScriptValue consoleCommandGroupDataToScriptValue( |
188 | QScriptEngine *eng, const QScriptDebuggerConsoleCommandGroupData &in) |
189 | { |
190 | QScriptValue out = eng->newObject(); |
191 | out.setProperty(name: QString::fromLatin1(str: "longDescription" ), value: QScriptValue(eng, in.longDescription())); |
192 | out.setProperty(name: QString::fromLatin1(str: "shortDescription" ), value: QScriptValue(eng, in.shortDescription())); |
193 | return out; |
194 | } |
195 | |
196 | static void consoleCommandGroupDataFromScriptValue( |
197 | const QScriptValue &, QScriptDebuggerConsoleCommandGroupData &) |
198 | { |
199 | Q_ASSERT(0); |
200 | } |
201 | |
202 | static QScriptValue consoleCommandGroupMapToScriptValue( |
203 | QScriptEngine *eng, const QScriptDebuggerConsoleCommandGroupMap &in) |
204 | { |
205 | QScriptValue out = eng->newObject(); |
206 | QScriptDebuggerConsoleCommandGroupMap::const_iterator it; |
207 | for (it = in.constBegin(); it != in.constEnd(); ++it) { |
208 | out.setProperty(name: it.key(), value: eng->toScriptValue(value: it.value())); |
209 | } |
210 | return out; |
211 | } |
212 | |
213 | static void consoleCommandGroupMapFromScriptValue( |
214 | const QScriptValue &, QScriptDebuggerConsoleCommandGroupMap &) |
215 | { |
216 | Q_ASSERT(0); |
217 | } |
218 | |
219 | static QScriptValue contextInfoToScriptValue(QScriptEngine *eng, const QScriptContextInfo &in) |
220 | { |
221 | QScriptValue out = eng->newObject(); |
222 | out.setProperty(name: QString::fromLatin1(str: "scriptId" ), value: QScriptValue(eng, qsreal(in.scriptId()))); |
223 | out.setProperty(name: QString::fromLatin1(str: "fileName" ), value: QScriptValue(eng, in.fileName())); |
224 | out.setProperty(name: QString::fromLatin1(str: "lineNumber" ), value: QScriptValue(eng, in.lineNumber())); |
225 | out.setProperty(name: QString::fromLatin1(str: "columnNumber" ), value: QScriptValue(eng, in.columnNumber())); |
226 | out.setProperty(name: QString::fromLatin1(str: "functionName" ), value: QScriptValue(eng, in.functionName())); |
227 | return out; |
228 | } |
229 | |
230 | static void contextInfoFromScriptValue(const QScriptValue &, QScriptContextInfo &) |
231 | { |
232 | Q_ASSERT(0); |
233 | } |
234 | |
235 | static QScriptValue debuggerScriptValuePropertyToScriptValue(QScriptEngine *eng, const QScriptDebuggerValueProperty &in) |
236 | { |
237 | QScriptValue out = eng->newObject(); |
238 | out.setProperty(name: QString::fromLatin1(str: "name" ), value: QScriptValue(eng, in.name())); |
239 | out.setProperty(name: QString::fromLatin1(str: "value" ), value: eng->toScriptValue(value: in.value())); |
240 | out.setProperty(name: QString::fromLatin1(str: "valueAsString" ), value: QScriptValue(eng, in.valueAsString())); |
241 | out.setProperty(name: QString::fromLatin1(str: "flags" ), value: QScriptValue(eng, static_cast<int>(in.flags()))); |
242 | return out; |
243 | } |
244 | |
245 | static void debuggerScriptValuePropertyFromScriptValue(const QScriptValue &in, QScriptDebuggerValueProperty &out) |
246 | { |
247 | QString name = in.property(name: QString::fromLatin1(str: "name" )).toString(); |
248 | QScriptDebuggerValue value = qscriptvalue_cast<QScriptDebuggerValue>(value: in.property(name: QString::fromLatin1(str: "value" ))); |
249 | QString valueAsString = in.property(name: QString::fromLatin1(str: "valueAsString" )).toString(); |
250 | int flags = in.property(name: QString::fromLatin1(str: "flags" )).toInt32(); |
251 | QScriptDebuggerValueProperty tmp(name, value, valueAsString, QScriptValue::PropertyFlags(flags)); |
252 | out = tmp; |
253 | } |
254 | |
255 | /*! |
256 | \since 4.5 |
257 | \class QScriptDebuggerConsole |
258 | \internal |
259 | |
260 | \brief The QScriptDebuggerConsole class provides the core functionality of a debugger console. |
261 | */ |
262 | |
263 | class QScriptDebuggerConsolePrivate |
264 | { |
265 | Q_DECLARE_PUBLIC(QScriptDebuggerConsole) |
266 | public: |
267 | QScriptDebuggerConsolePrivate(QScriptDebuggerConsole*); |
268 | ~QScriptDebuggerConsolePrivate(); |
269 | |
270 | void loadScriptedCommands(const QString &scriptsPath, |
271 | QScriptMessageHandlerInterface *messageHandler); |
272 | QScriptDebuggerConsoleCommandJob *createJob( |
273 | const QString &command, |
274 | QScriptMessageHandlerInterface *messageHandler, |
275 | QScriptDebuggerCommandSchedulerInterface *commandScheduler); |
276 | |
277 | QScriptEngine *commandEngine; |
278 | QScriptDebuggerConsoleCommandManager *commandManager; |
279 | QString commandPrefix; |
280 | QString input; |
281 | QStringList commandHistory; |
282 | int currentFrameIndex; |
283 | qint64 currentScriptId; |
284 | int currentLineNumber; |
285 | int evaluateAction; |
286 | qint64 sessionId; |
287 | |
288 | QScriptDebuggerConsole *q_ptr; |
289 | }; |
290 | |
291 | QScriptDebuggerConsolePrivate::QScriptDebuggerConsolePrivate(QScriptDebuggerConsole* parent) |
292 | : q_ptr(parent) |
293 | { |
294 | sessionId = 0; |
295 | currentFrameIndex = 0; |
296 | currentScriptId = -1; |
297 | currentLineNumber = -1; |
298 | evaluateAction = 0; |
299 | commandPrefix = QLatin1String("." ); |
300 | commandManager = new QScriptDebuggerConsoleCommandManager(); |
301 | |
302 | commandEngine = new QScriptEngine; |
303 | qScriptRegisterMetaType<QScriptBreakpointData>(eng: commandEngine, toScriptValue: breakpointDataToScriptValue, fromScriptValue: breakpointDataFromScriptValue); |
304 | qScriptRegisterMetaType<QScriptBreakpointMap>(eng: commandEngine, toScriptValue: breakpointMapToScriptValue, fromScriptValue: breakpointMapFromScriptValue); |
305 | qScriptRegisterMetaType<QScriptScriptData>(eng: commandEngine, toScriptValue: scriptDataToScriptValue, fromScriptValue: scriptDataFromScriptValue); |
306 | qScriptRegisterMetaType<QScriptScriptMap>(eng: commandEngine, toScriptValue: scriptMapToScriptValue, fromScriptValue: scriptMapFromScriptValue); |
307 | qScriptRegisterMetaType<QScriptContextInfo>(eng: commandEngine, toScriptValue: contextInfoToScriptValue, fromScriptValue: contextInfoFromScriptValue); |
308 | qScriptRegisterMetaType<QScriptDebuggerValueProperty>(eng: commandEngine, toScriptValue: debuggerScriptValuePropertyToScriptValue, fromScriptValue: debuggerScriptValuePropertyFromScriptValue); |
309 | qScriptRegisterSequenceMetaType<QScriptDebuggerValuePropertyList>(engine: commandEngine); |
310 | qScriptRegisterMetaType<QScriptDebuggerResponse>(eng: commandEngine, toScriptValue: debuggerResponseToScriptValue, fromScriptValue: debuggerResponseFromScriptValue); |
311 | qScriptRegisterMetaType<QScriptDebuggerConsoleCommand*>(eng: commandEngine, toScriptValue: consoleCommandToScriptValue, fromScriptValue: consoleCommandFromScriptValue); |
312 | qScriptRegisterSequenceMetaType<QScriptDebuggerConsoleCommandList>(engine: commandEngine); |
313 | qScriptRegisterMetaType<QScriptDebuggerConsoleCommandGroupData>(eng: commandEngine, toScriptValue: consoleCommandGroupDataToScriptValue, fromScriptValue: consoleCommandGroupDataFromScriptValue); |
314 | qScriptRegisterMetaType<QScriptDebuggerConsoleCommandGroupMap>(eng: commandEngine, toScriptValue: consoleCommandGroupMapToScriptValue, fromScriptValue: consoleCommandGroupMapFromScriptValue); |
315 | // ### can't do this, if it's an object ID the conversion will be incorrect since |
316 | // ### the object ID refers to an object in a different engine! |
317 | // qScriptRegisterMetaType(commandEngine, debuggerScriptValueToScriptValue, debuggerScriptValueFromScriptValue); |
318 | } |
319 | |
320 | QScriptDebuggerConsolePrivate::~QScriptDebuggerConsolePrivate() |
321 | { |
322 | delete commandManager; |
323 | delete commandEngine; |
324 | } |
325 | |
326 | /* |
327 | Loads command definitions from scripts located in the given \a scriptsPath. |
328 | */ |
329 | void QScriptDebuggerConsolePrivate::loadScriptedCommands( |
330 | const QString &scriptsPath, |
331 | QScriptMessageHandlerInterface *messageHandler) |
332 | { |
333 | QDir dir(scriptsPath); |
334 | QFileInfoList entries = dir.entryInfoList(nameFilters: QStringList() |
335 | << QLatin1String("*.qs" )); |
336 | for (int i = 0; i < entries.size(); ++i) { |
337 | const QFileInfo &fi = entries.at(i); |
338 | QString fileName = fi.fileName(); |
339 | QFile file(scriptsPath + QLatin1Char('/') + fileName); |
340 | if (!file.open(flags: QIODevice::ReadOnly)) |
341 | continue; |
342 | QTextStream stream(&file); |
343 | QString program = stream.readAll(); |
344 | QScriptDebuggerScriptedConsoleCommand *command; |
345 | command = QScriptDebuggerScriptedConsoleCommand::parse( |
346 | program, fileName, engine: commandEngine, messageHandler); |
347 | if (!command) |
348 | continue; |
349 | commandManager->addCommand(command); |
350 | } |
351 | } |
352 | |
353 | |
354 | /* |
355 | Creates a job that will execute the given debugger \a command. |
356 | Returns the new job, or 0 if the command is undefined. |
357 | */ |
358 | QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsolePrivate::createJob( |
359 | const QString &command, QScriptMessageHandlerInterface *messageHandler, |
360 | QScriptDebuggerCommandSchedulerInterface *commandScheduler) |
361 | { |
362 | QString name; |
363 | int i = command.indexOf(c: QLatin1Char(' ')); |
364 | if (i == -1) { |
365 | name = command; |
366 | i = name.size(); |
367 | } else { |
368 | name = command.left(n: i); |
369 | } |
370 | if (name.isEmpty()) |
371 | return 0; |
372 | QScriptDebuggerConsoleCommand *cmd = commandManager->findCommand(name); |
373 | if (!cmd) { |
374 | // try to auto-complete |
375 | QStringList completions = commandManager->completions(prefix: name); |
376 | if (!completions.isEmpty()) { |
377 | if (completions.size() > 1) { |
378 | QString msg; |
379 | msg.append(s: QString::fromLatin1(str: "Ambiguous command \"%0\": " ) |
380 | .arg(a: name)); |
381 | for (int j = 0; j < completions.size(); ++j) { |
382 | if (j > 0) |
383 | msg.append(s: QLatin1String(", " )); |
384 | msg.append(s: completions.at(i: j)); |
385 | } |
386 | msg.append(c: QLatin1Char('.')); |
387 | messageHandler->message(type: QtWarningMsg, text: msg); |
388 | return 0; |
389 | } |
390 | cmd = commandManager->findCommand(name: completions.at(i: 0)); |
391 | Q_ASSERT(cmd != 0); |
392 | } |
393 | if (!cmd) { |
394 | messageHandler->message( |
395 | type: QtWarningMsg, |
396 | text: QString::fromLatin1(str: "Undefined command \"%0\". Try \"help\"." ) |
397 | .arg(a: name)); |
398 | return 0; |
399 | } |
400 | } |
401 | QStringList args; |
402 | QString tmp = command.mid(position: i+1); |
403 | if (cmd->argumentTypes().contains(str: QString::fromLatin1(str: "script" ))) { |
404 | if (!tmp.isEmpty()) |
405 | args.append(t: tmp); |
406 | } else { |
407 | args = tmp.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
408 | } |
409 | return cmd->createJob(arguments: args, console: q_func(), messageHandler, scheduler: commandScheduler); |
410 | } |
411 | |
412 | QScriptDebuggerConsole::QScriptDebuggerConsole() |
413 | : d_ptr(new QScriptDebuggerConsolePrivate(this)) |
414 | { |
415 | } |
416 | |
417 | QScriptDebuggerConsole::~QScriptDebuggerConsole() |
418 | { |
419 | } |
420 | |
421 | void QScriptDebuggerConsole::loadScriptedCommands(const QString &scriptsPath, |
422 | QScriptMessageHandlerInterface *messageHandler) |
423 | { |
424 | Q_D(QScriptDebuggerConsole); |
425 | d->loadScriptedCommands(scriptsPath, messageHandler); |
426 | } |
427 | |
428 | QScriptDebuggerConsoleCommandManager *QScriptDebuggerConsole::commandManager() const |
429 | { |
430 | Q_D(const QScriptDebuggerConsole); |
431 | return d->commandManager; |
432 | } |
433 | |
434 | bool QScriptDebuggerConsole::hasIncompleteInput() const |
435 | { |
436 | Q_D(const QScriptDebuggerConsole); |
437 | return !d->input.isEmpty(); |
438 | } |
439 | |
440 | QString QScriptDebuggerConsole::incompleteInput() const |
441 | { |
442 | Q_D(const QScriptDebuggerConsole); |
443 | return d->input; |
444 | } |
445 | |
446 | void QScriptDebuggerConsole::setIncompleteInput(const QString &input) |
447 | { |
448 | Q_D(QScriptDebuggerConsole); |
449 | d->input = input; |
450 | } |
451 | |
452 | QString QScriptDebuggerConsole::commandPrefix() const |
453 | { |
454 | Q_D(const QScriptDebuggerConsole); |
455 | return d->commandPrefix; |
456 | } |
457 | |
458 | /*! |
459 | Consumes the given line of \a input. If the input starts with the |
460 | command prefix, it is regarded as a debugger command; otherwise the |
461 | input is evaluated as a plain script. |
462 | */ |
463 | QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsole::consumeInput( |
464 | const QString &input, QScriptMessageHandlerInterface *messageHandler, |
465 | QScriptDebuggerCommandSchedulerInterface *commandScheduler) |
466 | { |
467 | Q_D(QScriptDebuggerConsole); |
468 | static const int maximumHistoryCount = 100; |
469 | QString cmd; |
470 | if (d->input.isEmpty() && input.isEmpty()) { |
471 | if (d->commandHistory.isEmpty()) |
472 | return 0; |
473 | cmd = d->commandHistory.first(); |
474 | } else { |
475 | cmd = input; |
476 | } |
477 | if (d->input.isEmpty() && cmd.startsWith(s: d->commandPrefix)) { |
478 | if (!input.isEmpty()) { |
479 | d->commandHistory.prepend(t: cmd); |
480 | if (d->commandHistory.size() > maximumHistoryCount) |
481 | d->commandHistory.removeLast(); |
482 | } |
483 | cmd.remove(i: 0, len: d->commandPrefix.length()); |
484 | return d->createJob(command: cmd, messageHandler, commandScheduler); |
485 | } |
486 | d->input += cmd; |
487 | d->input += QLatin1Char('\n'); |
488 | QScriptSyntaxCheckResult check = QScriptEngine::checkSyntax(program: d->input); |
489 | if (check.state() == QScriptSyntaxCheckResult::Intermediate) |
490 | return 0; |
491 | d->input.chop(n: 1); // remove the last \n |
492 | cmd = QString(); |
493 | cmd.append(s: d->commandPrefix); |
494 | cmd.append(s: QString::fromLatin1(str: "eval " )); |
495 | cmd.append(s: d->input); |
496 | d->commandHistory.prepend(t: cmd); |
497 | if (d->commandHistory.size() > maximumHistoryCount) |
498 | d->commandHistory.removeLast(); |
499 | d->input.clear(); |
500 | cmd.remove(i: 0, len: d->commandPrefix.length()); |
501 | return d->createJob(command: cmd, messageHandler, commandScheduler); |
502 | } |
503 | |
504 | int QScriptDebuggerConsole::currentFrameIndex() const |
505 | { |
506 | Q_D(const QScriptDebuggerConsole); |
507 | return d->currentFrameIndex; |
508 | } |
509 | |
510 | void QScriptDebuggerConsole::setCurrentFrameIndex(int index) |
511 | { |
512 | Q_D(QScriptDebuggerConsole); |
513 | d->currentFrameIndex = index; |
514 | } |
515 | |
516 | qint64 QScriptDebuggerConsole::currentScriptId() const |
517 | { |
518 | Q_D(const QScriptDebuggerConsole); |
519 | return d->currentScriptId; |
520 | } |
521 | |
522 | void QScriptDebuggerConsole::setCurrentScriptId(qint64 id) |
523 | { |
524 | Q_D(QScriptDebuggerConsole); |
525 | d->currentScriptId = id; |
526 | } |
527 | |
528 | int QScriptDebuggerConsole::currentLineNumber() const |
529 | { |
530 | Q_D(const QScriptDebuggerConsole); |
531 | return d->currentLineNumber; |
532 | } |
533 | |
534 | void QScriptDebuggerConsole::setCurrentLineNumber(int lineNumber) |
535 | { |
536 | Q_D(QScriptDebuggerConsole); |
537 | d->currentLineNumber = lineNumber; |
538 | } |
539 | |
540 | int QScriptDebuggerConsole::evaluateAction() const |
541 | { |
542 | Q_D(const QScriptDebuggerConsole); |
543 | return d->evaluateAction; |
544 | } |
545 | |
546 | void QScriptDebuggerConsole::setEvaluateAction(int action) |
547 | { |
548 | Q_D(QScriptDebuggerConsole); |
549 | d->evaluateAction = action; |
550 | } |
551 | |
552 | qint64 QScriptDebuggerConsole::sessionId() const |
553 | { |
554 | Q_D(const QScriptDebuggerConsole); |
555 | return d->sessionId; |
556 | } |
557 | |
558 | void QScriptDebuggerConsole::bumpSessionId() |
559 | { |
560 | Q_D(QScriptDebuggerConsole); |
561 | ++d->sessionId; |
562 | } |
563 | |
564 | void QScriptDebuggerConsole::showDebuggerInfoMessage( |
565 | QScriptMessageHandlerInterface *messageHandler) |
566 | { |
567 | messageHandler->message( |
568 | type: QtDebugMsg, |
569 | text: QString::fromLatin1( |
570 | str: "Welcome to the Qt Script debugger.\n" |
571 | "Debugger commands start with a . (period).\n" |
572 | "Any other input will be evaluated by the script interpreter.\n" |
573 | "Type \".help\" for help.\n" )); |
574 | } |
575 | |
576 | /*! |
577 | \reimp |
578 | */ |
579 | int QScriptDebuggerConsole::historyCount() const |
580 | { |
581 | Q_D(const QScriptDebuggerConsole); |
582 | return d->commandHistory.size(); |
583 | } |
584 | |
585 | /*! |
586 | \reimp |
587 | */ |
588 | QString QScriptDebuggerConsole::historyAt(int index) const |
589 | { |
590 | Q_D(const QScriptDebuggerConsole); |
591 | return d->commandHistory.value(i: index); |
592 | } |
593 | |
594 | /*! |
595 | \reimp |
596 | */ |
597 | void QScriptDebuggerConsole::changeHistoryAt(int index, const QString &newHistory) |
598 | { |
599 | Q_D(QScriptDebuggerConsole); |
600 | d->commandHistory[index] = newHistory; |
601 | } |
602 | |
603 | QT_END_NAMESPACE |
604 | |