source: trunk/src/scripttools/debugging/qscriptcompletiontask.cpp@ 715

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

trunk: Merged in qt 4.6.2 sources.

File size: 10.7 KB
RevLine 
[2]1/****************************************************************************
2**
[651]3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
[561]4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
[2]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**
[561]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.
[2]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**
[561]36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
[2]38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptcompletiontask_p.h"
43#include "qscriptcompletiontaskinterface_p_p.h"
44#include "qscriptdebuggerconsole_p.h"
45#include "qscriptdebuggerconsolecommand_p.h"
46#include "qscriptdebuggerconsolecommandmanager_p.h"
[561]47#include "qscriptdebuggercommandschedulerjob_p.h"
48#include "qscriptdebuggercommandschedulerfrontend_p.h"
49#include "qscriptdebuggerjobschedulerinterface_p.h"
50#include "qscriptdebuggerresponse_p.h"
[2]51
52#include "private/qobject_p.h"
53
54#include <QtCore/qset.h>
55#include <QtCore/qdebug.h>
56
57QT_BEGIN_NAMESPACE
58
59class QScriptCompletionTaskPrivate
60 : public QScriptCompletionTaskInterfacePrivate
61{
62 Q_DECLARE_PUBLIC(QScriptCompletionTask)
63public:
64 QScriptCompletionTaskPrivate();
65 ~QScriptCompletionTaskPrivate();
66
67 void completeScriptExpression();
[561]68 void emitFinished();
[2]69
70 QString contents;
71 int cursorPosition;
72 int frameIndex;
[561]73 QScriptDebuggerCommandSchedulerInterface *commandScheduler;
74 QScriptDebuggerJobSchedulerInterface *jobScheduler;
[2]75 QScriptDebuggerConsole *console;
76};
77
78QScriptCompletionTaskPrivate::QScriptCompletionTaskPrivate()
[561]79 : cursorPosition(0), frameIndex(0), commandScheduler(0),
80 jobScheduler(0), console(0)
[2]81{
82}
83
84QScriptCompletionTaskPrivate::~QScriptCompletionTaskPrivate()
85{
86}
87
[561]88class QScriptCompleteExpressionJob : public QScriptDebuggerCommandSchedulerJob
[2]89{
[561]90public:
91 QScriptCompleteExpressionJob(int frameIndex, const QStringList &path,
92 QScriptCompletionTaskPrivate *task,
93 QScriptDebuggerCommandSchedulerInterface *scheduler)
94 : QScriptDebuggerCommandSchedulerJob(scheduler),
95 m_frameIndex(frameIndex), m_path(path), m_task(task)
96 {}
[2]97
[561]98 void start()
99 {
100 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
101 frontend.scheduleGetCompletions(m_frameIndex, m_path);
102 }
103 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
104 {
105 m_task->results = response.result().toStringList();
106 m_task->emitFinished();
107 finish();
108 }
[2]109
[561]110private:
111 int m_frameIndex;
112 QStringList m_path;
113 QScriptCompletionTaskPrivate *m_task;
114};
115
[2]116namespace {
117
118static bool isIdentChar(const QChar &ch)
119{
120 static QChar underscore = QLatin1Char('_');
121 return ch.isLetter() || (ch == underscore);
122}
123
124static bool isPrefixOf(const QString &prefix, const QString &what)
125{
126 return ((what.length() > prefix.length())
127 && what.startsWith(prefix));
128}
129
130} // namespace
131
[561]132class QScriptCompleteScriptsJob : public QScriptDebuggerCommandSchedulerJob
133{
134public:
135 QScriptCompleteScriptsJob(const QString &prefix, QScriptCompletionTaskPrivate *task,
136 QScriptDebuggerCommandSchedulerInterface *scheduler)
137 : QScriptDebuggerCommandSchedulerJob(scheduler),
138 m_prefix(prefix), m_task(task)
139 {}
140
141 void start()
142 {
143 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
144 frontend.scheduleGetScripts();
145 }
146 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
147 {
148 QScriptScriptMap scripts = response.resultAsScripts();
149 QScriptScriptMap::const_iterator it;
150 for (it = scripts.constBegin(); it != scripts.constEnd(); ++it) {
151 QString fileName = it.value().fileName();
152 if (isPrefixOf(m_prefix, fileName))
153 m_task->results.append(fileName);
154 }
155 m_task->emitFinished();
156 finish();
157 }
158private:
159 QString m_prefix;
160 QScriptCompletionTaskPrivate *m_task;
161};
162
[2]163void QScriptCompletionTaskPrivate::completeScriptExpression()
164{
165 int pos = cursorPosition;
166 if ((pos > 0) && contents.at(pos-1).isNumber()) {
167 // completion of numbers is pointless
[561]168 emitFinished();
[2]169 return;
170 }
171
172 while ((pos > 0) && isIdentChar(contents.at(pos-1)))
173 --pos;
[561]174 int pos2 = cursorPosition - 1;
[2]175 while ((pos2 < contents.size()-1) && isIdentChar(contents.at(pos2+1)))
176 ++pos2;
177 QString ident = contents.mid(pos, pos2 - pos + 1);
178 position = pos;
179
180 QStringList path;
181 path.append(ident);
182 while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) {
183 --pos;
184 pos2 = pos;
185 while ((pos > 0) && isIdentChar(contents.at(pos-1)))
186 --pos;
187 path.prepend(contents.mid(pos, pos2 - pos));
188 }
189
[561]190 length = path.last().length();
191 type = QScriptCompletionTask::ScriptIdentifierCompletion;
[2]192
[561]193 QScriptDebuggerJob *job = new QScriptCompleteExpressionJob(frameIndex, path, this, commandScheduler);
194 jobScheduler->scheduleJob(job);
195}
[2]196
[561]197void QScriptCompletionTaskPrivate::emitFinished()
198{
199 emit q_func()->finished();
[2]200}
201
[561]202QScriptCompletionTask::QScriptCompletionTask(
203 const QString &contents, int cursorPosition, int frameIndex,
204 QScriptDebuggerCommandSchedulerInterface *commandScheduler,
205 QScriptDebuggerJobSchedulerInterface *jobScheduler,
206 QScriptDebuggerConsole *console,
207 QObject *parent)
208 : QScriptCompletionTaskInterface(
209 *new QScriptCompletionTaskPrivate, parent)
210{
211 Q_D(QScriptCompletionTask);
212 d->contents = contents;
213 d->cursorPosition = cursorPosition;
214 if ((frameIndex == -1) && console)
215 d->frameIndex = console->currentFrameIndex();
216 else
217 d->frameIndex = frameIndex;
218 d->commandScheduler = commandScheduler;
219 d->jobScheduler = jobScheduler;
220 d->console = console;
221}
222
223QScriptCompletionTask::~QScriptCompletionTask()
224{
225}
226
[2]227void QScriptCompletionTask::start()
228{
229 Q_D(QScriptCompletionTask);
230 d->type = NoCompletion;
231 // see if we're typing a command
232 // ### don't hardcode the command prefix
233 QRegExp cmdRx(QString::fromLatin1("^\\s*\\.([a-zA-Z]*)"));
234 int cmdIndex = cmdRx.indexIn(d->contents);
235 if ((cmdIndex != -1) && d->console) {
236 int len = cmdRx.matchedLength();
237 QString prefix = cmdRx.capturedTexts().at(1);
238 if ((d->cursorPosition >= cmdIndex) && (d->cursorPosition <= (cmdIndex+len))) {
239 // editing command --> get command completions
240 d->results = d->console->commandManager()->completions(prefix);
241 d->position = cmdRx.pos(1);
242 d->length = prefix.length();
243 d->type = CommandNameCompletion;
244 d->appendix = QString::fromLatin1(" ");
245 emit finished();
246 } else {
247 QScriptDebuggerConsoleCommand *cmd = d->console->commandManager()->findCommand(prefix);
248 if (!cmd) {
249 emit finished();
250 return;
251 }
252 // editing an argument
253 int argNum = 0;
254 QString arg;
255 int pos = cmdIndex + len;
256 while (pos < d->contents.size()) {
257 while ((pos < d->contents.size()) && d->contents.at(pos).isSpace())
258 ++pos;
259 if (pos < d->contents.size()) {
260 int pos2 = pos + 1;
261 while ((pos2 < d->contents.size()) && !d->contents.at(pos2).isSpace())
262 ++pos2;
263 if ((d->cursorPosition >= pos) && (d->cursorPosition <= pos2)) {
264 arg = d->contents.mid(pos, pos2 - pos);
265 break;
266 }
267 pos = pos2;
268 ++argNum;
269 }
270 }
271 QString argType = cmd->argumentTypes().value(argNum);
272 if (!argType.isEmpty()) {
[561]273 if (argType == QLatin1String("command-or-group-name")) {
[2]274 d->results = d->console->commandManager()->completions(arg);
[561]275 } else if (argType == QLatin1String("script-filename")) {
276 d->position = pos;
277 d->length = arg.length();
278 d->type = CommandArgumentCompletion;
279 QScriptDebuggerJob *job = new QScriptCompleteScriptsJob(arg, d, d->commandScheduler);
280 d->jobScheduler->scheduleJob(job);
281 } else if (argType == QLatin1String("subcommand-name")) {
[2]282 for (int i = 0; i < cmd->subCommands().size(); ++i) {
283 QString name = cmd->subCommands().at(i);
284 if (isPrefixOf(arg, name))
285 d->results.append(name);
286 }
[561]287 qStableSort(d->results);
288 } else if (argType == QLatin1String("script")) {
[2]289 d->completeScriptExpression();
[561]290 } else {
291 emit finished();
[2]292 }
293 if ((d->type == NoCompletion) && !d->results.isEmpty()) {
294 d->position = pos;
295 d->length = arg.length();
296 d->type = CommandArgumentCompletion;
[561]297 emit finished();
[2]298 }
299 }
300 }
301 } else {
302 // assume it's an eval expression
303 d->completeScriptExpression();
304 }
305}
306
307QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.