tst_codegen.cpp 10.3 KB
Newer Older
1
2
3
4
5
6
7
#include <AST.h>
#include <Control.h>
#include <CppDocument.h>
#include <DiagnosticClient.h>
#include <Scope.h>
#include <TranslationUnit.h>
#include <Literals.h>
Roberto Raggi's avatar
Compile    
Roberto Raggi committed
8
#include <Bind.h>
9
#include <Symbols.h>
10
11
#include <cpptools/insertionpointlocator.h>
#include <cpptools/cpprefactoringchanges.h>
12
13
#include <cpptools/cpptoolsplugin.h>
#include <extensionsystem/pluginmanager.h>
14
15
16
17
18

#include <QtTest>
#include <QtDebug>
#include <QTextDocument>

19
20
//TESTED_COMPONENT=src/libs/cplusplus

21
22
23
24
/*!
    Tests for various parts of the code generation. Well, okay, currently it only
    tests the InsertionPointLocator.
 */
25
using namespace CPlusPlus;
26
using namespace CppTools;
27
28
29
30
31
32

class tst_Codegen: public QObject
{
    Q_OBJECT

private slots:
33
34
    void initTestCase();
    void cleanupTestCase();
35
36
37
38
39
40
41
    void public_in_empty_class();
    void public_in_nonempty_class();
    void public_before_protected();
    void private_after_protected();
    void protected_in_nonempty_class();
    void protected_betwee_public_and_private();
    void qtdesigner_integration();
42
43
private:
    ExtensionSystem::PluginManager *pluginManager;
44
45
};

46
47
48
void tst_Codegen::initTestCase()
{
    pluginManager = new ExtensionSystem::PluginManager;
Bill King's avatar
Bill King committed
49
50
51
    QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                                 QLatin1String("Nokia"), QLatin1String("QtCreator"));
    pluginManager->setSettings(settings);
52
53
54
55
56
57
58
59
60
61
    pluginManager->setFileExtension(QLatin1String("pluginspec"));
    pluginManager->setPluginPaths(QStringList() << QLatin1String(Q_PLUGIN_PATH));
    pluginManager->loadPlugins();
}

void tst_Codegen::cleanupTestCase()
{
    pluginManager->shutdown();
    delete pluginManager;
}
62
63
64
65
/*!
    Should insert at line 3, column 1, with "public:\n" as prefix and without suffix.
 */
void tst_Codegen::public_in_empty_class()
66
67
68
69
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
70
            "};\n"
71
72
            "\n";

73
    Document::Ptr doc = Document::create("public_in_empty_class");
74
75
76
77
78
79
80
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

81
82
83
84
85
86
87
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);

    Snapshot snapshot;
    snapshot.insert(doc);
88
89
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
90
    InsertionLocation loc = find.methodDeclarationInClass(
91
92
                doc->fileName(),
                foo,
93
                InsertionPointLocator::Public);
94
    QVERIFY(loc.isValid());
95
    QCOMPARE(loc.prefix(), QLatin1String("public:\n"));
96
    QVERIFY(loc.suffix().isEmpty());
97
    QCOMPARE(loc.line(), 3U);
98
99
100
    QCOMPARE(loc.column(), 1U);
}

101
102
103
104
/*!
    Should insert at line 3, column 1, without prefix and without suffix.
 */
void tst_Codegen::public_in_nonempty_class()
105
106
107
108
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
109
110
            "public:\n"   // line 3
            "};\n"        // line 4
111
112
            "\n";

113
    Document::Ptr doc = Document::create("public_in_nonempty_class");
114
115
116
117
118
119
120
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

121
122
123
124
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
125

126
127
    Snapshot snapshot;
    snapshot.insert(doc);
128
129
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
130
    InsertionLocation loc = find.methodDeclarationInClass(
131
132
                doc->fileName(),
                foo,
133
                InsertionPointLocator::Public);
134
    QVERIFY(loc.isValid());
135
    QVERIFY(loc.prefix().isEmpty());
136
    QVERIFY(loc.suffix().isEmpty());
137
    QCOMPARE(loc.line(), 4U);
138
139
140
    QCOMPARE(loc.column(), 1U);
}

141
142
143
/*!
    Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix.
 */
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
void tst_Codegen::public_before_protected()
{
    const QByteArray src = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "protected:\n" // line 3
            "};\n"
            "\n";

    Document::Ptr doc = Document::create("public_before_protected");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

161
162
163
164
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
165

166
167
    Snapshot snapshot;
    snapshot.insert(doc);
168
169
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
170
    InsertionLocation loc = find.methodDeclarationInClass(
171
172
                doc->fileName(),
                foo,
173
                InsertionPointLocator::Public);
174
175
176
177
178
179
180
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("public:\n"));
    QCOMPARE(loc.suffix(), QLatin1String("\n"));
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.line(), 3U);
}

181
182
183
184
/*!
    Should insert at line 4, column 1, with "private:\n" as prefix and without
    suffix.
 */
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
void tst_Codegen::private_after_protected()
{
    const QByteArray src = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "protected:\n" // line 3
            "};\n"
            "\n";

    Document::Ptr doc = Document::create("private_after_protected");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

202
203
204
205
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
206

207
208
    Snapshot snapshot;
    snapshot.insert(doc);
209
210
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
211
    InsertionLocation loc = find.methodDeclarationInClass(
212
213
                doc->fileName(),
                foo,
214
                InsertionPointLocator::Private);
215
216
217
218
219
220
221
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("private:\n"));
    QVERIFY(loc.suffix().isEmpty());
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.line(), 4U);
}

222
223
224
225
/*!
    Should insert at line 4, column 1, with "protected:\n" as prefix and without
    suffix.
 */
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
void tst_Codegen::protected_in_nonempty_class()
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
            "public:\n"   // line 3
            "};\n"        // line 4
            "\n";

    Document::Ptr doc = Document::create("protected_in_nonempty_class");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

243
244
245
246
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
247

248
249
    Snapshot snapshot;
    snapshot.insert(doc);
250
251
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
252
    InsertionLocation loc = find.methodDeclarationInClass(
253
254
                doc->fileName(),
                foo,
255
                InsertionPointLocator::Protected);
256
257
258
259
260
261
262
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("protected:\n"));
    QVERIFY(loc.suffix().isEmpty());
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.line(), 4U);
}

263
264
265
/*!
    Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix.
 */
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
void tst_Codegen::protected_betwee_public_and_private()
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
            "public:\n"   // line 3
            "private:\n"  // line 4
            "};\n"        // line 5
            "\n";

    Document::Ptr doc = Document::create("protected_betwee_public_and_private");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

284
285
286
287
    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
288

289
290
    Snapshot snapshot;
    snapshot.insert(doc);
291
292
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
293
    InsertionLocation loc = find.methodDeclarationInClass(
294
295
                doc->fileName(),
                foo,
296
                InsertionPointLocator::Protected);
297
298
299
300
301
302
303
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("protected:\n"));
    QCOMPARE(loc.suffix(), QLatin1String("\n"));
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.line(), 4U);
}

304
305
306
307
308
309
310
/*!
    Should insert at line 18, column 1, with "private slots:\n" as prefix and "\n"
    as suffix.

    This is the typical Qt Designer case, with test-input like what the integration
    generates.
 */
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
void tst_Codegen::qtdesigner_integration()
{
    const QByteArray src = "/**** Some long (C)opyright notice ****/\n"
            "#ifndef MAINWINDOW_H\n"
            "#define MAINWINDOW_H\n"
            "\n"
            "#include <QMainWindow>\n"
            "\n"
            "namespace Ui {\n"
            "    class MainWindow;\n"
            "}\n"
            "\n"
            "class MainWindow : public QMainWindow\n" // line 10
            "{\n"
            "    Q_OBJECT\n"
            "\n"
            "public:\n" // line 14
            "    explicit MainWindow(QWidget *parent = 0);\n"
            "    ~MainWindow();\n"
            "\n"
            "private:\n" // line 18
            "    Ui::MainWindow *ui;\n"
            "};\n"
            "\n"
            "#endif // MAINWINDOW_H\n";

    Document::Ptr doc = Document::create("qtdesigner_integration");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 2U);

345
346
347
348
    Class *foo = doc->globalSymbolAt(1)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 10U);
    QCOMPARE(foo->column(), 7U);
349

350
351
    Snapshot snapshot;
    snapshot.insert(doc);
352
353
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(&changes);
354
    InsertionLocation loc = find.methodDeclarationInClass(
355
356
                doc->fileName(),
                foo,
357
                InsertionPointLocator::PrivateSlot);
358
359
360
361
362
363
364
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("private slots:\n"));
    QCOMPARE(loc.suffix(), QLatin1String("\n"));
    QCOMPARE(loc.line(), 18U);
    QCOMPARE(loc.column(), 1U);
}

365
QTEST_MAIN(tst_Codegen)
366
#include "tst_codegen.moc"