cppcompletion_test.cpp 74.1 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29

30
#include "cppcompletionassist.h"
31
#include "cppmodelmanager.h"
32
33
#include "cpptoolsplugin.h"
#include "cpptoolstestcase.h"
34
35

#include <texteditor/codeassist/iassistproposal.h>
36
#include <texteditor/convenience.h>
37
#include <texteditor/plaintexteditor.h>
38
39

#include <utils/changeset.h>
40
41
#include <utils/fileutils.h>

hjk's avatar
hjk committed
42
#include <QDebug>
43
#include <QDir>
44
45
#include <QTextDocument>
#include <QtTest>
46
47
48
49
50
51
52
53
54
55

/*!
    Tests for code completion.
 */
using namespace CPlusPlus;
using namespace CppTools;
using namespace CppTools::Internal;
using namespace TextEditor;
using namespace Core;

56
57
58
namespace {

typedef QByteArray _;
59

60
class CompletionTestCase : public CppTools::Tests::TestCase
61
62
63
{
public:
    CompletionTestCase(const QByteArray &sourceText, const QByteArray &textToInsert = QByteArray())
64
        : m_position(-1), m_editorWidget(0), m_textDocument(0), m_editor(0)
65
    {
66
67
68
        QVERIFY(succeededSoFar());
        m_succeededSoFar = false;

69
70
71
72
        m_source = sourceText;
        m_position = m_source.indexOf('@');
        QVERIFY(m_position != -1);
        m_source[m_position] = ' ';
73
74
75

        // Write source to file
        const QString fileName = QDir::tempPath() + QLatin1String("/file.h");
76
        QVERIFY(writeFile(fileName, m_source));
77
78

        // Open in editor
79
80
81
82
83
        m_editor = EditorManager::openEditor(fileName);
        QVERIFY(m_editor);
        closeEditorAtEndOfTestCase(m_editor);
        m_editorWidget = qobject_cast<TextEditor::BaseTextEditorWidget *>(m_editor->widget());
        QVERIFY(m_editorWidget);
84

85
        m_textDocument = m_editorWidget->document();
86
87

        // Get Document
88
89
        waitForFileInGlobalSnapshot(fileName);
        const Document::Ptr document = globalSnapshot().document(fileName);
90

91
        m_snapshot.insert(document);
92
93
94

        if (!textToInsert.isEmpty())
            insertText(textToInsert);
95
96

        m_succeededSoFar = true;
97
    }
98

99
100
101
102
    QStringList getCompletions(bool *replaceAccessOperator = 0) const
    {
        QStringList completions;
        CppCompletionAssistInterface *ai
103
104
105
            = new CppCompletionAssistInterface(m_editorWidget->document(), m_position,
                                               m_editorWidget->baseTextDocument()->filePath(),
                                               ExplicitlyInvoked, m_snapshot,
106
107
108
109
110
111
112
113
114
115
116
117
                                               QStringList(), QStringList());
        CppCompletionAssistProcessor processor;
        IAssistProposal *proposal = processor.perform(ai);
        if (!proposal)
            return completions;
        IAssistProposalModel *model = proposal->model();
        if (!model)
            return completions;
        CppAssistProposalModel *listmodel = dynamic_cast<CppAssistProposalModel *>(model);
        if (!listmodel)
            return completions;

118
        const int pos = proposal->basePosition();
119
120
121
        const int length = m_position - pos;
        const QString prefix = Convenience::textAt(QTextCursor(m_editorWidget->document()), pos,
                                                   length);
122
123
        if (!prefix.isEmpty())
            listmodel->filter(prefix);
124
125
        if (listmodel->isSortable(prefix))
            listmodel->sort(prefix);
126

127
128
129
130
131
        for (int i = 0; i < listmodel->size(); ++i)
            completions << listmodel->text(i);

        if (replaceAccessOperator)
            *replaceAccessOperator = listmodel->m_replaceDotForArrow;
132

133
134
        return completions;
    }
135

136
137
138
    void insertText(const QByteArray &text)
    {
        Utils::ChangeSet change;
139
140
        change.insert(m_position, QLatin1String(text));
        QTextCursor cursor(m_textDocument);
141
        change.apply(&cursor);
142
        m_position += text.length();
143
    }
144

145
private:
146
147
148
149
150
151
    QByteArray m_source;
    int m_position;
    Snapshot m_snapshot;
    BaseTextEditorWidget *m_editorWidget;
    QTextDocument *m_textDocument;
    IEditor *m_editor;
152
};
153

154
155
} // anonymous namespace

156
157
158
159
160
161
162
163
164
165
166
167
168
169
void CppToolsPlugin::test_completion_basic_1()
{
    const QByteArray source =
            "class Foo\n"
            "{\n"
            "    void foo();\n"
            "    int m;\n"
            "};\n"
            "\n"
            "void func() {\n"
            "    Foo f;\n"
            "    @\n"
            "}";
    CompletionTestCase test(source);
170
    QVERIFY(test.succeededSoFar());
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

    QStringList basicCompletions = test.getCompletions();
    QVERIFY(!basicCompletions.contains(QLatin1String("foo")));
    QVERIFY(!basicCompletions.contains(QLatin1String("m")));
    QVERIFY(basicCompletions.contains(QLatin1String("Foo")));
    QVERIFY(basicCompletions.contains(QLatin1String("func")));
    QVERIFY(basicCompletions.contains(QLatin1String("f")));

    test.insertText("f.");

    QStringList memberCompletions = test.getCompletions();
    QVERIFY(memberCompletions.contains(QLatin1String("foo")));
    QVERIFY(memberCompletions.contains(QLatin1String("m")));
    QVERIFY(!memberCompletions.contains(QLatin1String("func")));
    QVERIFY(!memberCompletions.contains(QLatin1String("f")));
}

void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_8737()
{
    const QByteArray source =
            "void f()\n"
            "{\n"
            "    int a_b_c, a_c, a_c_a;\n"
            "    @;\n"
            "}\n"
            ;
    CompletionTestCase test(source, "a_c");
198
    QVERIFY(test.succeededSoFar());
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

    QStringList completions = test.getCompletions();

    QVERIFY(completions.size() >= 2);
    QCOMPARE(completions.at(0), QLatin1String("a_c"));
    QCOMPARE(completions.at(1), QLatin1String("a_c_a"));
    QVERIFY(completions.contains(QLatin1String("a_b_c")));
}

void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_9236()
{
    const QByteArray source =
            "class r_etclass\n"
            "{\n"
            "public:\n"
            "    int raEmTmber;\n"
            "    void r_e_t(int re_t)\n"
            "    {\n"
            "        int r_et;\n"
            "        int rETUCASE;\n"
            "        @\n"
            "    }\n"
            "};\n"
            ;
    CompletionTestCase test(source, "ret");
224
    QVERIFY(test.succeededSoFar());
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

    QStringList completions = test.getCompletions();
    QVERIFY(completions.size() >= 2);
    QCOMPARE(completions.at(0), QLatin1String("return"));
    QCOMPARE(completions.at(1), QLatin1String("rETUCASE"));
    QVERIFY(completions.contains(QLatin1String("r_etclass")));
    QVERIFY(completions.contains(QLatin1String("raEmTmber")));
    QVERIFY(completions.contains(QLatin1String("r_e_t")));
    QVERIFY(completions.contains(QLatin1String("re_t")));
    QVERIFY(completions.contains(QLatin1String("r_et")));
}

void CppToolsPlugin::test_completion_template_function()
{
    QFETCH(QByteArray, code);
    QFETCH(QStringList, expectedCompletions);

    CompletionTestCase test(code);
243
    QVERIFY(test.succeededSoFar());
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

    QStringList actualCompletions = test.getCompletions();
    QString errorPattern(QLatin1String("Completion not found: %1"));
    foreach (const QString &completion, expectedCompletions) {
        QByteArray errorMessage = errorPattern.arg(completion).toUtf8();
        QVERIFY2(actualCompletions.contains(completion), errorMessage.data());
    }
}

void CppToolsPlugin::test_completion_template_function_data()
{
    QTest::addColumn<QByteArray>("code");
    QTest::addColumn<QStringList>("expectedCompletions");

    QByteArray code;
    QStringList completions;

    code =
           "template <class tclass, typename tname, int tint>\n"
           "tname Hello(const tclass &e)\n"
           "{\n"
           "    tname e2 = e;\n"
           "    @\n"
           "}";

    completions.append(QLatin1String("tclass"));
    completions.append(QLatin1String("tname"));
    completions.append(QLatin1String("tint"));
272

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
    QTest::newRow("case: template parameters in template function body")
            << code << completions;

    completions.clear();

    code =
           "template <class tclass, typename tname, int tint>\n"
           "tname Hello(const tclass &e, @)\n"
           "{\n"
           "    tname e2 = e;\n"
           "}";

    completions.append(QLatin1String("tclass"));
    completions.append(QLatin1String("tname"));
    completions.append(QLatin1String("tint"));
288

289
290
291
292
293
294
295
296
297
298
299
    QTest::newRow("case: template parameters in template function parameters list")
            << code << completions;
}

void CppToolsPlugin::test_completion()
{
    QFETCH(QByteArray, code);
    QFETCH(QByteArray, prefix);
    QFETCH(QStringList, expectedCompletions);

    CompletionTestCase test(code, prefix);
300
    QVERIFY(test.succeededSoFar());
301
302
303
304
305

    QStringList actualCompletions = test.getCompletions();
    actualCompletions.sort();
    expectedCompletions.sort();

306
    QEXPECT_FAIL("enum_in_function_in_struct_in_function", "doesn't work", Abort);
307
308
309
    QCOMPARE(actualCompletions, expectedCompletions);
}

310
void CppToolsPlugin::test_completion_data()
311
{
312
313
314
315
316
    QTest::addColumn<QByteArray>("code");
    QTest::addColumn<QByteArray>("prefix");
    QTest::addColumn<QStringList>("expectedCompletions");

    QTest::newRow("forward_declarations_present") << _(
317
318
319
320
321
322
323
324
325
326
327
328
            "class Foo\n"
            "{\n"
            "    struct Bar;\n"
            "    int i;\n"
            "};\n"
            "\n"
            "struct Foo::Bar \n"
            "{\n"
            "    Bar() {}\n"
            "};\n"
            "\n"
            "@\n"
329
330
        ) << _("Foo::Bar::") << (QStringList()
            << QLatin1String("Bar"));
331

332
    QTest::newRow("inside_parentheses_c_style_conversion") << _(
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
            "class Base\n"
            "{\n"
            "    int i_base;\n"
            "};\n"
            "\n"
            "class Derived : public Base\n"
            "{\n"
            "    int i_derived;\n"
            "};\n"
            "\n"
            "void fun()\n"
            "{\n"
            "    Base *b = new Derived;\n"
            "    if (1)\n"
            "        @\n"
            "}\n"
349
350
351
352
353
        ) << _("((Derived *)b)->") << (QStringList()
            << QLatin1String("Derived")
            << QLatin1String("Base")
            << QLatin1String("i_derived")
            << QLatin1String("i_base"));
354

355
    QTest::newRow("inside_parentheses_cast_operator_conversion") << _(
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
            "class Base\n"
            "{\n"
            "    int i_base;\n"
            "};\n"
            "\n"
            "class Derived : public Base\n"
            "{\n"
            "    int i_derived;\n"
            "};\n"
            "\n"
            "void fun()\n"
            "{\n"
            "    Base *b = new Derived;\n"
            "    if (1)\n"
            "        @\n"
            "}\n"
372
373
374
375
376
        ) << _("(static_cast<Derived *>(b))->") << (QStringList()
            << QLatin1String("Derived")
            << QLatin1String("Base")
            << QLatin1String("i_derived")
            << QLatin1String("i_base"));
377

378
    QTest::newRow("template_1") << _(
379
380
381
382
383
384
385
386
387
388
389
            "template <class T>\n"
            "class Foo\n"
            "{\n"
            "    typedef T Type;\n"
            "    T foo();\n"
            "    T m;\n"
            "};\n"
            "\n"
            "void func() {\n"
            "    Foo f;\n"
            "    @\n"
390
391
392
393
394
395
            "}"
        ) << _("Foo::") << (QStringList()
              << QLatin1String("Foo")
              << QLatin1String("Type")
              << QLatin1String("foo")
              << QLatin1String("m"));
396

397
    QTest::newRow("template_2") << _(
398
399
400
401
402
403
404
405
406
407
408
            "template <class T>\n"
            "struct List\n"
            "{\n"
            "    T &at(int);\n"
            "};\n"
            "\n"
            "struct Tupple { int a; int b; };\n"
            "\n"
            "void func() {\n"
            "    List<Tupple> l;\n"
            "    @\n"
409
410
411
412
413
            "}"
        ) << _("l.at(0).") << (QStringList()
            << QLatin1String("Tupple")
            << QLatin1String("a")
            << QLatin1String("b"));
414

415
    QTest::newRow("template_3") << _(
416
417
418
419
420
421
422
423
424
425
426
            "template <class T>\n"
            "struct List\n"
            "{\n"
            "    T t;\n"
            "};\n"
            "\n"
            "struct Tupple { int a; int b; };\n"
            "\n"
            "void func() {\n"
            "    List<Tupple> l;\n"
            "    @\n"
427
428
429
430
431
            "}"
        ) << _("l.t.") << (QStringList()
            << QLatin1String("Tupple")
            << QLatin1String("a")
            << QLatin1String("b"));
432

433
    QTest::newRow("template_4") << _(
434
435
436
437
438
439
440
441
442
443
444
445
            "template <class T>\n"
            "struct List\n"
            "{\n"
            "    typedef T U;\n"
            "    U u;\n"
            "};\n"
            "\n"
            "struct Tupple { int a; int b; };\n"
            "\n"
            "void func() {\n"
            "    List<Tupple> l;\n"
            "    @\n"
446
447
448
449
450
            "}"
        ) << _("l.u.") << (QStringList()
            << QLatin1String("Tupple")
            << QLatin1String("a")
            << QLatin1String("b"));
451

452
    QTest::newRow("template_5") << _(
453
454
455
456
457
458
459
460
461
462
463
464
            "template <class T>\n"
            "struct List\n"
            "{\n"
            "    T u;\n"
            "};\n"
            "\n"
            "struct Tupple { int a; int b; };\n"
            "\n"
            "void func() {\n"
            "    typedef List<Tupple> LT;\n"
            "    LT l;"
            "    @\n"
465
466
467
468
469
            "}"
        ) << _("l.u.") << (QStringList()
            << QLatin1String("Tupple")
            << QLatin1String("a")
            << QLatin1String("b"));
470

471
    QTest::newRow("template_6") << _(
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
            "class Item\n"
            "{\n"
            "    int i;\n"
            "};\n"
            "\n"
            "template <typename T>\n"
            "class Container\n"
            "{\n"
            "    T get();\n"
            "};\n"
            "\n"
            "template <typename T> class Container;\n"
            "\n"
            "class ItemContainer: public Container<Item>\n"
            "{};\n"
            "ItemContainer container;\n"
            "@\n"
489
490
491
        ) << _("container.get().") << (QStringList()
            << QLatin1String("Item")
            << QLatin1String("i"));
492

493
    QTest::newRow("template_7") << _(
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
            "struct Test\n"
            "{\n"
            "   int i;\n"
            "};\n"
            "\n"
            "template<typename T>\n"
            "struct TemplateClass\n"
            "{\n"
            "    T* ptr;\n"
            "\n"
            "    typedef T element_type;\n"
            "    TemplateClass(T* t) : ptr(t) {}\n"
            "    element_type* operator->()\n"
            "    {\n"
            "        return ptr;\n"
            "    }\n"
            "};\n"
            "\n"
            "TemplateClass<Test> p(new Test);\n"
            "@\n"
514
515
516
        ) << _("p->") << (QStringList()
            << QLatin1String("Test")
            << QLatin1String("i"));
517

518
    QTest::newRow("type_of_pointer_is_typedef") << _(
519
520
521
522
523
524
            "typedef struct Foo\n"
            "{\n"
            "    int foo;\n"
            "} Foo;\n"
            "Foo *bar;\n"
            "@\n"
525
526
527
        ) << _("bar->") << (QStringList()
            << QLatin1String("Foo")
            << QLatin1String("foo"));
528

529
    QTest::newRow("instantiate_full_specialization") << _(
530
531
532
533
534
535
536
537
538
539
540
541
542
543
            "template<typename T>\n"
            "struct Template\n"
            "{\n"
            "   int templateT_i;\n"
            "};\n"
            "\n"
            "template<>\n"
            "struct Template<char>\n"
            "{\n"
            "    int templateChar_i;\n"
            "};\n"
            "\n"
            "Template<char> templateChar;\n"
            "@\n"
544
545
546
        ) << _("templateChar.") << (QStringList()
            << QLatin1String("Template")
            << QLatin1String("templateChar_i"));
547

548
    QTest::newRow("template_as_base: base as template directly") << _(
549
550
551
552
553
554
            "class Data { int dataMember; };\n"
            "template <class T> class Other : public T { int otherMember; };\n"
            "\n"
            "void func() {\n"
            "    Other<Data> c;\n"
            "    @\n"
555
556
557
558
559
560
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Other")
            << QLatin1String("otherMember"));
561

562
    QTest::newRow("template_as_base: base as class template") << _(
563
564
565
566
567
568
569
            "class Data { int dataMember; };\n"
            "template <class T> class Other : public T { int otherMember; };\n"
            "template <class T> class More : public Other<T> { int moreMember; };\n"
            "\n"
            "void func() {\n"
            "    More<Data> c;\n"
            "    @\n"
570
571
572
573
574
575
576
577
578
579
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Other")
            << QLatin1String("otherMember")
            << QLatin1String("More")
            << QLatin1String("moreMember"));

    QTest::newRow("template_as_base: base as globally qualified class template") << _(
580
581
582
583
584
585
586
            "class Data { int dataMember; };\n"
            "template <class T> class Other : public T { int otherMember; };\n"
            "template <class T> class More : public ::Other<T> { int moreMember; };\n"
            "\n"
            "void func() {\n"
            "    More<Data> c;\n"
            "    @\n"
587
588
589
590
591
592
593
594
595
596
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Other")
            << QLatin1String("otherMember")
            << QLatin1String("More")
            << QLatin1String("moreMember"));

    QTest::newRow("template_as_base: base as namespace qualified class template") << _(
597
598
599
600
601
602
603
604
605
            "class Data { int dataMember; };\n"
            "namespace NS {\n"
            "template <class T> class Other : public T { int otherMember; };\n"
            "}\n"
            "template <class T> class More : public NS::Other<T> { int moreMember; };\n"
            "\n"
            "void func() {\n"
            "    More<Data> c;\n"
            "    @\n"
606
607
608
609
610
611
612
613
614
615
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Other")
            << QLatin1String("otherMember")
            << QLatin1String("More")
            << QLatin1String("moreMember"));

    QTest::newRow("template_as_base: base as nested template name") << _(
616
617
618
619
620
621
622
623
624
            "class Data { int dataMember; };\n"
            "namespace NS {\n"
            "template <class T> class Delegate { typedef Data<T> Type; };\n"
            "}\n"
            "template <class T> class Final : public NS::Delegate<T>::Type { int finalMember; };\n"
            "\n"
            "void func() {\n"
            "    Final<Data> c;\n"
            "    @\n"
625
626
627
628
629
630
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Final")
            << QLatin1String("finalMember"));
631

632
    QTest::newRow("template_as_base: base as nested template name in non-template") << _(
633
634
635
636
637
638
639
640
641
            "class Data { int dataMember; };\n"
            "namespace NS {\n"
            "template <class T> class Delegate { typedef Data<T> Type; };\n"
            "}\n"
            "class Final : public NS::Delegate<Data>::Type { int finalMember; };\n"
            "\n"
            "void func() {\n"
            "    Final c;\n"
            "    @\n"
642
643
644
645
646
647
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Final")
            << QLatin1String("finalMember"));
648

649
    QTest::newRow("template_as_base: base as template name in non-template") << _(
650
651
652
653
654
655
656
657
658
            "class Data { int dataMember; };\n"
            "namespace NS {\n"
            "template <class T> class Other : public T { int otherMember; };\n"
            "}\n"
            "class Final : public NS::Other<Data> { int finalMember; };\n"
            "\n"
            "void func() {\n"
            "    Final c;\n"
            "    @\n"
659
660
661
662
663
664
665
666
667
668
            "}"
        ) << _("c.") << (QStringList()
            << QLatin1String("Data")
            << QLatin1String("dataMember")
            << QLatin1String("Final")
            << QLatin1String("finalMember")
            << QLatin1String("Other")
            << QLatin1String("otherMember"));

    QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _(
669
670
671
672
673
674
675
676
677
678
679
            "struct Global\n"
            "{\n"
            "    int int_global;\n"
            "};\n"
            "\n"
            "struct Final : ::Global\n"
            "{\n"
            "   int int_final;\n"
            "};\n"
            "\n"
            "Final c;\n"
680
681
682
683
684
685
686
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_global")
            << QLatin1String("int_final")
            << QLatin1String("Final")
            << QLatin1String("Global"));

687
    QTest::newRow("use_global_identifier_as_base_class: derived is inside namespace. "
688
                  "base as global") << _(
689
690
691
692
693
694
695
696
697
698
699
700
701
702
            "struct Global\n"
            "{\n"
            "    int int_global;\n"
            "};\n"
            "\n"
            "namespace NS\n"
            "{\n"
            "struct Final : ::Global\n"
            "{\n"
            "   int int_final;\n"
            "};\n"
            "}\n"
            "\n"
            "NS::Final c;\n"
703
704
705
706
707
708
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_global")
            << QLatin1String("int_final")
            << QLatin1String("Final")
            << QLatin1String("Global"));
709

710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
    QTest::newRow("use_global_identifier_as_base_class: derived is enclosed by template. "
                  "base as global") << _(
            "struct Global\n"
            "{\n"
            "    int int_global;\n"
            "};\n"
            "\n"
            "template <typename T>\n"
            "struct Enclosing\n"
            "{\n"
            "struct Final : ::Global\n"
            "{\n"
            "   int int_final;\n"
            "};\n"
            "};\n"
            "\n"
            "Enclosing<int>::Final c;\n"
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_global")
            << QLatin1String("int_final")
            << QLatin1String("Final")
            << QLatin1String("Global"));
733

734
    QTest::newRow("base_class_has_name_the_same_as_derived: base class is derived class") << _(
735
736
737
738
739
740
            "struct A : A\n"
            "{\n"
            "   int int_a;\n"
            "};\n"
            "\n"
            "A c;\n"
741
742
743
744
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_a")
            << QLatin1String("A"));
745

746
747
    QTest::newRow("base_class_has_name_the_same_as_derived: base class is derived class. "
                  "class is in namespace") << _(
748
749
750
751
752
753
754
755
756
            "namespace NS\n"
            "{\n"
            "struct A : A\n"
            "{\n"
            "   int int_a;\n"
            "};\n"
            "}\n"
            "\n"
            "NS::A c;\n"
757
758
759
760
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_a")
            << QLatin1String("A"));
761

762
763
    QTest::newRow("base_class_has_name_the_same_as_derived: base class is derived class. "
                  "class is in namespace. use scope operator for base class") << _(
764
765
766
767
768
769
770
771
772
            "namespace NS\n"
            "{\n"
            "struct A : NS::A\n"
            "{\n"
            "   int int_a;\n"
            "};\n"
            "}\n"
            "\n"
            "NS::A c;\n"
773
774
775
776
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_a")
            << QLatin1String("A"));
777

778
779
    QTest::newRow("base_class_has_name_the_same_as_derived: base class has the same name as "
                  "derived but in different namespace") << _(
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
            "namespace NS1\n"
            "{\n"
            "struct A\n"
            "{\n"
            "   int int_ns1_a;\n"
            "};\n"
            "}\n"
            "namespace NS2\n"
            "{\n"
            "struct A : NS1::A\n"
            "{\n"
            "   int int_ns2_a;\n"
            "};\n"
            "}\n"
            "\n"
            "NS2::A c;\n"
796
797
798
799
800
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_ns1_a")
            << QLatin1String("int_ns2_a")
            << QLatin1String("A"));
801

802
803
    QTest::newRow("base_class_has_name_the_same_as_derived: base class has the same name as "
                  "derived (in namespace) but is nested by different class") << _(
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
            "struct Enclosing\n"
            "{\n"
            "struct A\n"
            "{\n"
            "   int int_enclosing_a;\n"
            "};\n"
            "};\n"
            "namespace NS2\n"
            "{\n"
            "struct A : Enclosing::A\n"
            "{\n"
            "   int int_ns2_a;\n"
            "};\n"
            "}\n"
            "\n"
            "NS2::A c;\n"
820
821
822
823
824
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_enclosing_a")
            << QLatin1String("int_ns2_a")
            << QLatin1String("A"));
825

826
827
    QTest::newRow("base_class_has_name_the_same_as_derived: base class has the same name as "
                  "derived (nested) but is nested by different class") << _(
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
            "struct EnclosingBase\n"
            "{\n"
            "struct A\n"
            "{\n"
            "   int int_enclosing_base_a;\n"
            "};\n"
            "};\n"
            "struct EnclosingDerived\n"
            "{\n"
            "struct A : EnclosingBase::A\n"
            "{\n"
            "   int int_enclosing_derived_a;\n"
            "};\n"
            "};\n"
            "\n"
            "EnclosingDerived::A c;\n"
844
845
846
847
848
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_enclosing_base_a")
            << QLatin1String("int_enclosing_derived_a")
            << QLatin1String("A"));
849

850
851
    QTest::newRow("base_class_has_name_the_same_as_derived: base class is derived class. "
                  "class is a template") << _(
852
853
854
855
856
857
858
            "template <typename T>\n"
            "struct A : A\n"
            "{\n"
            "   int int_a;\n"
            "};\n"
            "\n"
            "A<int> c;\n"
859
860
861
862
            "@\n"
        ) << _("c.") << (QStringList()
            << QLatin1String("int_a")
            << QLatin1String("A"));
863

864
    QTest::newRow("cyclic_inheritance: direct cyclic inheritance") << _(
865
866
867
868
869
870
            "struct B;\n"
            "struct A : B { int _a; };\n"
            "struct B : A { int _b; };\n"
            "\n"
            "A c;\n"
            "@\n"
871
872
873
874
875
        ) << _("c.") << (QStringList()
            << QLatin1String("A")
            << QLatin1String("_a")
            << QLatin1String("B")
            << QLatin1String("_b"));
876

877
    QTest::newRow("cyclic_inheritance: indirect cyclic inheritance") << _(
878
879
880
881
882
883
884
            "struct C;\n"
            "struct A : C { int _a; };\n"
            "struct B : A { int _b; };\n"
            "struct C : B { int _c; };\n"
            "\n"
            "A c;\n"
            "@\n"
885
886
887
888
889
890
891
892
893
        ) << _("c.") << (QStringList()
            << QLatin1String("A")
            << QLatin1String("_a")
            << QLatin1String("B")
            << QLatin1String("_b")
            << QLatin1String("C")
            << QLatin1String("_c"));

    QTest::newRow("cyclic_inheritance: indirect cyclic inheritance") << _(
894
895
896
897
898
899
900
            "struct B;\n"
            "struct A : B { int _a; };\n"
            "struct C { int _c; };\n"
            "struct B : C, A { int _b; };\n"
            "\n"
            "A c;\n"
            "@\n"
901
902
903
904
905
906
907
908
909
        ) << _("c.") << (QStringList()
            << QLatin1String("A")
            << QLatin1String("_a")
            << QLatin1String("B")
            << QLatin1String("_b")
            << QLatin1String("C")
            << QLatin1String("_c"));

    QTest::newRow("cyclic_inheritance: direct cyclic inheritance with templates") << _(
910
911
912
913
914
915
916
917
918
919
920
921
922
            "template< typename T > struct C;\n"
            "template< typename T, typename S > struct D : C< S >\n"
            "{\n"
            "   T _d_t;\n"
            "   S _d_s;\n"
            "};\n"
            "template< typename T > struct C : D< T, int >\n"
            "{\n"
            "   T _c_t;\n"
            "};\n"
            "\n"
            "D<int, float> c;\n"
            "@\n"
923
924
925
926
927
928
929
930
        ) << _("c.") << (QStringList()
            << QLatin1String("D")
            << QLatin1String("_d_t")
            << QLatin1String("_d_s")
            << QLatin1String("C")
            << QLatin1String("_c_t"));

    QTest::newRow("cyclic_inheritance: indirect cyclic inheritance with templates") << _(
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
            "template< typename T > struct C;\n"
            "template< typename T, typename S > struct D : C< S >\n"
            "{\n"
            "   T _d_t;\n"
            "   S _d_s;\n"
            "};\n"
            "template< typename T > struct B : D< T, int >\n"
            "{\n"
            "   T _b_t;\n"
            "};\n"
            "template< typename T > struct C : B<T>\n"
            "{\n"
            "   T _c_t;\n"
            "};\n"
            "\n"
            "D<int, float> c;\n"
            "@\n"
948
949
950
951
952
953
954
955
956
        ) << _("c.") << (QStringList()
            << QLatin1String("D")
            << QLatin1String("_d_t")
            << QLatin1String("_d_s")
            << QLatin1String("C")
            << QLatin1String("_c_t")
            << QLatin1String("B")
            << QLatin1String("_b_t"));

957
    QTest::newRow("cyclic_inheritance: direct cyclic inheritance with templates. "
958
                  "more complex situation") << _(
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
           "namespace NS\n"
           "{\n"
           "template <typename T> struct SuperClass\n"
           "{\n"
           "    typedef T Type;\n"
           "    Type super_class_type;\n"
           "};\n"
           "}\n"
           "\n"
           "template <typename T>\n"
           "struct Class;\n"
           "\n"
           "template <typename T, typename S>\n"
           "struct ClassRecurse : Class<S>\n"
           "{\n"
           "    T class_recurse_t;\n"
           "    S class_recurse_s;\n"
           "};\n"
           "\n"
           "template <typename T>\n"
           "struct Class : ClassRecurse< T, typename ::NS::SuperClass<T>::Type >\n"
           "{\n"
           "    T class_t;\n"
           "};\n"
           "\n"
           "Class<int> c;\n"
           "@\n"
986
987
988
989
990
991
992
993
        ) << _("c.") << (QStringList()
            << QLatin1String("Class")
            << QLatin1String("ClassRecurse")
            << QLatin1String("class_t")
            << QLatin1String("class_recurse_s")
            << QLatin1String("class_recurse_t"));

    QTest::newRow("enclosing_template_class: nested class with enclosing template class") << _(
994
995
996
997
998
999
1000
            "template<typename T>\n"
            "struct Enclosing\n"
            "{\n"
            "    struct Nested { int int_nested; }; \n"
            "    int int_enclosing;\n"
            "};\n"
            "\n"
For faster browsing, not all history is shown. View entire blame