~ubuntu-branches/ubuntu/vivid/kate/vivid-proposed

« back to all changes in this revision

Viewing changes to addons/ktexteditor/lumen/dcd.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2014-12-04 16:49:41 UTC
  • mfrom: (1.6.6)
  • Revision ID: package-import@ubuntu.com-20141204164941-l3qbvsly83hhlw2v
Tags: 4:14.11.97-0ubuntu1
* New upstream release
* Update build-deps and use pkg-kde v3 for Qt 5 build
* kate-data now kate5-data for co-installability

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2014  David Herberth kde@dav1d.de
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2.1 of the License, or (at your option) version 3, or any
8
 
 * later version accepted by the membership of KDE e.V. (or its
9
 
 * successor approved by the membership of KDE e.V.), which shall
10
 
 * act as a proxy defined in Section 6 of version 3 of the license.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
19
 
**/
20
 
 
21
 
#include "dcd.h"
22
 
#include <kprocess.h>
23
 
#include <kdebug.h>
24
 
#include <QtCore/QFile>
25
 
 
26
 
 
27
 
char DCDCompletionItemType::toChar(DCDCompletionItemType e)
28
 
{
29
 
    switch (e) {
30
 
        case Invalid: return 0;
31
 
        case Calltip: return 1;
32
 
        case ClassName: return 'c';
33
 
        case InterfaceName: return 'i';
34
 
        case StructName: return 's';
35
 
        case UnionName: return 'u';
36
 
        case VariableName: return 'v';
37
 
        case MemberVariableName: return 'm';
38
 
        case Keyword: return 'k';
39
 
        case FunctionName: return 'f';
40
 
        case EnumName: return 'g';
41
 
        case EnumMember: return 'e';
42
 
        case PackageName: return 'p';
43
 
        case ModuleName: return 'M';
44
 
    }
45
 
 
46
 
    return 0;
47
 
}
48
 
 
49
 
DCDCompletionItemType::DCDCompletionItemType DCDCompletionItemType::fromChar(char c)
50
 
{
51
 
    switch (c) {
52
 
        case 0: return Invalid;
53
 
        case 1: return Calltip;
54
 
        case 'c': return ClassName;
55
 
        case 'i': return InterfaceName;
56
 
        case 's': return StructName;
57
 
        case 'u': return UnionName;
58
 
        case 'v': return VariableName;
59
 
        case 'm': return MemberVariableName;
60
 
        case 'k': return Keyword;
61
 
        case 'f': return FunctionName;
62
 
        case 'g': return EnumName;
63
 
        case 'e': return EnumMember;
64
 
        case 'p': return PackageName;
65
 
        case 'M': return ModuleName;
66
 
    }
67
 
 
68
 
    return Invalid;
69
 
}
70
 
 
71
 
 
72
 
 
73
 
DCDCompletionItem::DCDCompletionItem(DCDCompletionItemType::DCDCompletionItemType t, QString s): type(t), name(s)
74
 
{
75
 
 
76
 
}
77
 
 
78
 
#define RETURN_CACHED_ICON(name) {static QIcon icon(KIcon(name).pixmap(QSize(16, 16))); return icon;}
79
 
QIcon DCDCompletionItem::icon() const
80
 
{
81
 
    using namespace DCDCompletionItemType;
82
 
    switch (type)
83
 
    {
84
 
        case Invalid: break;
85
 
        case Calltip: RETURN_CACHED_ICON("code-function")
86
 
        case ClassName: RETURN_CACHED_ICON("code-class")
87
 
        case InterfaceName: RETURN_CACHED_ICON("code-class")
88
 
        case StructName: RETURN_CACHED_ICON("struct")
89
 
        case UnionName: RETURN_CACHED_ICON("union")
90
 
        case VariableName: RETURN_CACHED_ICON("code-variable")
91
 
        case MemberVariableName: RETURN_CACHED_ICON("field")
92
 
        case Keyword: RETURN_CACHED_ICON("field")
93
 
        case FunctionName: RETURN_CACHED_ICON("code-function")
94
 
        case EnumName: RETURN_CACHED_ICON("enum")
95
 
        case EnumMember: RETURN_CACHED_ICON("enum")
96
 
        case PackageName: RETURN_CACHED_ICON("field")
97
 
        case ModuleName: RETURN_CACHED_ICON("field")
98
 
    }
99
 
 
100
 
    return KIcon();
101
 
}
102
 
 
103
 
QString DCDCompletionItem::typeLong() const
104
 
{
105
 
    using namespace DCDCompletionItemType;
106
 
    switch (type)
107
 
    {
108
 
        case Invalid: return "invalid";
109
 
        case Calltip: return "calltip";
110
 
        case ClassName: return "class";
111
 
        case InterfaceName: return "interface";
112
 
        case StructName: return "struct";
113
 
        case UnionName: return "union";
114
 
        case VariableName: return "variable";
115
 
        case MemberVariableName: return "member";
116
 
        case Keyword: return "keyword";
117
 
        case FunctionName: return "function";
118
 
        case EnumName: return "enum";
119
 
        case EnumMember: return "enum member";
120
 
        case PackageName: return "package";
121
 
        case ModuleName: return "module";
122
 
    }
123
 
 
124
 
    return "completion";
125
 
}
126
 
 
127
 
 
128
 
static const int TIMEOUT_START_SERVER = 200;
129
 
static const int TIMEOUT_COMPLETE = 200;
130
 
static const int TIMEOUT_IMPORTPATH = 200;
131
 
static const int TIMEOUT_SHUTDOWN = 350;
132
 
static const int TIMEOUT_SHUTDOWN_SERVER = 200;
133
 
 
134
 
 
135
 
DCD::DCD(int port, const QString& server, const QString& client)
136
 
{
137
 
    m_port = port;
138
 
    m_server = server;
139
 
    m_client = client;
140
 
}
141
 
 
142
 
int DCD::port()
143
 
{
144
 
    return m_port;
145
 
}
146
 
 
147
 
bool DCD::running()
148
 
{
149
 
    return m_sproc.state() == KProcess::Running;
150
 
}
151
 
 
152
 
 
153
 
bool DCD::startServer()
154
 
{
155
 
    m_sproc.setOutputChannelMode(KProcess::MergedChannels);
156
 
    m_sproc.setProgram(m_server, QStringList(QString("-p%1").arg(m_port)));
157
 
    m_sproc.start();
158
 
    bool started = m_sproc.waitForStarted(TIMEOUT_START_SERVER);
159
 
    bool finished = m_sproc.waitForFinished(TIMEOUT_START_SERVER);
160
 
 
161
 
    if (!started || finished || m_sproc.state() == KProcess::NotRunning) {
162
 
        kWarning() << "unable to start completion-server:" << m_sproc.exitCode();
163
 
        kWarning() << m_sproc.readAll();
164
 
        return false;
165
 
    }
166
 
    kDebug() << "started completion-server";
167
 
    return true;
168
 
}
169
 
 
170
 
 
171
 
DCDCompletion DCD::complete(QString file, int offset)
172
 
{
173
 
    KProcess proc;
174
 
    proc.setOutputChannelMode(KProcess::MergedChannels);
175
 
    proc.setProgram(m_client,
176
 
        QStringList()
177
 
            << QString("-p%1").arg(m_port)
178
 
            << QString("-c%1").arg(offset)
179
 
            << file
180
 
    );
181
 
    int ret = proc.execute(TIMEOUT_COMPLETE);
182
 
 
183
 
    if (ret != 0) {
184
 
        kWarning() << "unable to complete:" << ret;
185
 
        kWarning() << proc.readAll();
186
 
        return DCDCompletion();
187
 
    }
188
 
 
189
 
    return processCompletion(proc.readAllStandardOutput());
190
 
}
191
 
 
192
 
DCDCompletion DCD::complete(QByteArray data, int offset)
193
 
{
194
 
    KProcess proc;
195
 
    proc.setOutputChannelMode(KProcess::MergedChannels);
196
 
    proc.setProgram(m_client,
197
 
        QStringList()
198
 
            << QString("-p%1").arg(m_port)
199
 
            << QString("-c%1").arg(offset)
200
 
    );
201
 
 
202
 
    proc.start();
203
 
    proc.write(data);
204
 
    proc.closeWriteChannel();
205
 
    if (!proc.waitForFinished(TIMEOUT_COMPLETE)) {
206
 
        kWarning() << "unable to complete: client didn't finish in time";
207
 
        proc.close();
208
 
    } else if (proc.exitCode() != 0) {
209
 
        kWarning() << "unable to complete:" << proc.exitCode();
210
 
        kWarning() << proc.readAll();
211
 
    } else {
212
 
        // everything Ok
213
 
        return processCompletion(proc.readAllStandardOutput());
214
 
    }
215
 
 
216
 
    return DCDCompletion();
217
 
}
218
 
 
219
 
QString DCD::doc(QByteArray data, int offset)
220
 
{
221
 
    KProcess proc;
222
 
    proc.setOutputChannelMode(KProcess::MergedChannels);
223
 
    proc.setProgram(m_client,
224
 
        QStringList()
225
 
            << QString("-p%1").arg(m_port)
226
 
            << QString("-c%1").arg(offset)
227
 
            << QString("--doc")
228
 
    );
229
 
 
230
 
    proc.start();
231
 
    proc.write(data);
232
 
    proc.closeWriteChannel();
233
 
    if (!proc.waitForFinished(TIMEOUT_COMPLETE)) {
234
 
        kWarning() << "unable to lookup documentation: client didn't finish in time";
235
 
        proc.close();
236
 
    } else if (proc.exitCode() != 0) {
237
 
        kWarning() << "unable to lookup documentation:" << proc.exitCode();
238
 
        kWarning() << proc.readAll();
239
 
    } else {
240
 
        return proc.readAllStandardOutput();
241
 
    }
242
 
 
243
 
    return QString("");
244
 
}
245
 
 
246
 
 
247
 
DCDCompletion DCD::processCompletion(QString data)
248
 
{
249
 
    DCDCompletion completion;
250
 
 
251
 
    QStringList lines = data.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
252
 
    if (lines.length() == 0) {
253
 
        return completion;
254
 
    }
255
 
 
256
 
    QString type = lines.front();
257
 
    if (type == "identifiers") { completion.type = DCDCompletionType::Identifiers; }
258
 
    else if (type == "calltips") { completion.type = DCDCompletionType::Calltips; }
259
 
    else {
260
 
        kWarning() << "Invalid type:" << type;
261
 
        return completion;
262
 
    }
263
 
    lines.pop_front();
264
 
 
265
 
    foreach(QString line, lines) {
266
 
        if (line.trimmed().length() == 0) {
267
 
            continue;
268
 
        }
269
 
 
270
 
        QStringList kv = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
271
 
        if (kv.length() != 2 && completion.type != DCDCompletionType::Calltips) {
272
 
            kWarning() << "invalid completion data:" << kv.length() << completion.type;
273
 
            continue;
274
 
        }
275
 
 
276
 
        if (completion.type == DCDCompletionType::Identifiers) {
277
 
            completion.completions.append(DCDCompletionItem(
278
 
                DCDCompletionItemType::fromChar(kv[1].at(0).toAscii()), kv[0]
279
 
            ));
280
 
        } else {
281
 
            completion.completions.append(DCDCompletionItem(
282
 
                DCDCompletionItemType::Calltip, line
283
 
            ));
284
 
        }
285
 
    }
286
 
 
287
 
    return completion;
288
 
}
289
 
 
290
 
 
291
 
void DCD::addImportPath(QString path)
292
 
{
293
 
    addImportPath(QStringList(path));
294
 
}
295
 
 
296
 
void DCD::addImportPath(QStringList paths)
297
 
{
298
 
    if (paths.isEmpty()) {
299
 
        return;
300
 
    }
301
 
 
302
 
    QStringList arguments = QStringList(QString("-p%1").arg(m_port));
303
 
    foreach(QString path, paths) {
304
 
        if (QFile::exists(path))
305
 
            arguments << QString("-I%1").arg(path);
306
 
    }
307
 
 
308
 
    kDebug() << "ARGUMENTS:" << arguments;
309
 
 
310
 
    KProcess proc;
311
 
    proc.setOutputChannelMode(KProcess::MergedChannels);
312
 
    proc.setProgram(m_client, arguments);
313
 
    int ret = proc.execute(TIMEOUT_IMPORTPATH);
314
 
 
315
 
    if (ret != 0) {
316
 
        kWarning() << "unable to add importpath(s)" << paths << ":" << ret;
317
 
        kWarning() << proc.readAll();
318
 
    }
319
 
}
320
 
 
321
 
void DCD::shutdown()
322
 
{
323
 
    KProcess proc;
324
 
    proc.setOutputChannelMode(KProcess::MergedChannels);
325
 
    proc.setProgram(m_client,
326
 
        QStringList()
327
 
            << QString("-p%1").arg(m_port)
328
 
            << QString("--shutdown")
329
 
    );
330
 
    int ret = proc.execute(TIMEOUT_SHUTDOWN);
331
 
 
332
 
    if (ret != 0) {
333
 
        kWarning() << "unable to shutdown dcd:" << ret;
334
 
        kWarning() << proc.readAll();
335
 
    }
336
 
}
337
 
 
338
 
 
339
 
bool DCD::stopServer()
340
 
{
341
 
    if (m_sproc.state() == KProcess::Running) {
342
 
        kDebug() << "shutting down dcd";
343
 
        shutdown();
344
 
        if(!m_sproc.waitForFinished(TIMEOUT_SHUTDOWN_SERVER))
345
 
            m_sproc.terminate();
346
 
        if(!m_sproc.waitForFinished(TIMEOUT_SHUTDOWN_SERVER))
347
 
            m_sproc.kill();
348
 
 
349
 
        return true;
350
 
    }
351
 
    return false;
352
 
}
353
 
 
354
 
 
355
 
 
356
 
DCD::~DCD()
357
 
{
358
 
    if (running()) {
359
 
        stopServer();
360
 
    }
361
 
}
362
 
 
363
 
 
364
 
#include "dcd.moc"
 
 
b'\\ No newline at end of file'