cppquickfix_test.cpp 102 KB
Newer Older
1 2
/****************************************************************************
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** 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.
**
** GNU Lesser General Public License Usage
** 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
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

30
#include "cppeditor.h"
31
#include "cppeditorplugin.h"
32
#include "cppeditortestcase.h"
33 34
#include "cppquickfixassistant.h"
#include "cppquickfixes.h"
35
#include "cppquickfix_test.h"
36

37
#include <cpptools/cppcodestylepreferences.h>
38
#include <cpptools/cppmodelmanager.h>
39 40
#include <cpptools/cppsourceprocessertesthelper.h>
#include <cpptools/cppsourceprocessor.h>
41
#include <cpptools/cpptoolssettings.h>
42
#include <cpptools/includeutils.h>
43

44 45 46 47
#include <utils/fileutils.h>

#include <QDebug>
#include <QDir>
48 49
#include <QtTest>

50 51 52
/*!
    Tests for quick-fixes.
 */
53
using namespace Core;
54 55 56
using namespace CPlusPlus;
using namespace CppEditor;
using namespace CppEditor::Internal;
57
using namespace CppEditor::Internal::Tests;
58
using namespace CppTools;
59
using namespace IncludeUtils;
60 61
using namespace TextEditor;

62 63
using CppTools::Tests::TestIncludePaths;

64 65 66
namespace CppEditor {
namespace Internal {
namespace Tests {
67

68 69 70
QuickFixTestDocument::Ptr QuickFixTestDocument::create(const QByteArray &fileName,
                                                       const QByteArray &source,
                                                       const QByteArray &expectedSource)
71
{
72 73
    return Ptr(new QuickFixTestDocument(fileName, source, expectedSource));
}
74 75


76 77 78 79
QuickFixTestDocument::QuickFixTestDocument(const QByteArray &fileName,
                                           const QByteArray &source,
                                           const QByteArray &expectedSource)
    : TestDocument(fileName, source)
80
    , m_expectedSource(QString::fromUtf8(expectedSource))
81
{
82 83 84
    if (m_cursorPosition > -1)
        m_source.remove(m_cursorPosition, 1);

85 86
    const int cursorPositionInExpectedSource
        = m_expectedSource.indexOf(QLatin1Char(m_cursorMarker));
87 88
    if (cursorPositionInExpectedSource > -1)
        m_expectedSource.remove(cursorPositionInExpectedSource, 1);
89 90
}

91 92
QList<QuickFixTestDocument::Ptr> singleDocument(const QByteArray &original,
                                                const QByteArray &expected)
93
{
94 95
    return QList<QuickFixTestDocument::Ptr>()
            << QuickFixTestDocument::create("file.cpp", original, expected);
96 97
}

98 99
/// Leading whitespace is not removed, so we can check if the indetation ranges
/// have been set correctly by the quick-fix.
100
static QString &removeTrailingWhitespace(QString &input)
101
{
102
    const QStringList lines = input.split(QLatin1Char('\n'));
103
    input.resize(0);
104
    for (int i = 0, total = lines.size(); i < total; ++i) {
105
        QString line = lines.at(i);
106
        while (line.length() > 0) {
107 108
            QChar lastChar = line[line.length() - 1];
            if (lastChar == QLatin1Char(' ') || lastChar == QLatin1Char('\t'))
109
                line.chop(1);
110 111 112 113
            else
                break;
        }
        input.append(line);
114 115 116

        const bool isLastLine = i == lines.size() - 1;
        if (!isLastLine)
117
            input.append(QLatin1Char('\n'));
118 119
    }
    return input;
120 121
}

122 123 124 125
} // namespace Tests
} // namespace Internal
} // namespace CppEditor

126
/// The '@' in the originalSource is the position from where the quick-fix discovery is triggered.
127
/// Exactly one TestFile must contain the cursor position marker '@' in the originalSource.
128
QuickFixTestCase::QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
129 130 131
                                   CppQuickFixFactory *factory,
                                   const QStringList &includePaths,
                                   int resultIndex)
132 133 134
    : m_testFiles(theTestFiles)
    , m_cppCodeStylePreferences(0)
    , m_restoreIncludePaths(false)
135
{
136
    QVERIFY(succeededSoFar());
137 138 139

    // Check if there is exactly one cursor marker
    unsigned cursorMarkersCount = 0;
140
    foreach (const QuickFixTestDocument::Ptr testFile, m_testFiles) {
141
        if (testFile->hasCursorMarker())
142
            ++cursorMarkersCount;
143
    }
144
    QVERIFY2(cursorMarkersCount == 1, "Exactly one cursor marker is allowed.");
145

146
    // Write files to disk
147
    foreach (QuickFixTestDocument::Ptr testFile, m_testFiles)
148
        testFile->writeToDisk();
149 150 151

    // Set appropriate include paths
    if (!includePaths.isEmpty()) {
152 153
        m_restoreIncludePaths = true;
        m_includePathsToRestore = m_modelManager->includePaths();
154
        m_modelManager->setIncludePaths(includePaths);
155
    }
156

157 158
    // Update Code Model
    QStringList filePaths;
159
    foreach (const QuickFixTestDocument::Ptr &testFile, m_testFiles)
160
        filePaths << testFile->filePath();
161
    QVERIFY(parseFiles(filePaths));
162 163

    // Open Files
164
    foreach (QuickFixTestDocument::Ptr testFile, m_testFiles) {
165 166
        QVERIFY(openCppEditor(testFile->filePath(), &testFile->m_editor,
                              &testFile->m_editorWidget));
167
        closeEditorAtEndOfTestCase(testFile->m_editor);
168 169

        // Set cursor position
170 171 172
        const int cursorPosition = testFile->hasCursorMarker()
                ? testFile->m_cursorPosition : 0;
        testFile->m_editor->setCursorPosition(cursorPosition);
173 174

        // Rehighlight
175
        waitForRehighlightedSemanticDocument(testFile->m_editorWidget);
176
    }
177 178 179

    // Enforce the default cpp code style, so we are independent of config file settings.
    // This is needed by e.g. the GenerateGetterSetter quick fix.
180 181 182 183
    m_cppCodeStylePreferences = CppToolsSettings::instance()->cppCodeStyle();
    QVERIFY(m_cppCodeStylePreferences);
    m_cppCodeStylePreferencesOriginalDelegateId = m_cppCodeStylePreferences->currentDelegateId();
    m_cppCodeStylePreferences->setCurrentDelegate("qt");
184

185
    // Run the fix in the file having the cursor marker
186 187
    QuickFixTestDocument::Ptr testFile;
    foreach (const QuickFixTestDocument::Ptr file, m_testFiles) {
188
        if (file->hasCursorMarker())
189 190 191 192
            testFile = file;
    }
    QVERIFY2(testFile, "No test file with cursor marker found");

193
    if (QuickFixOperation::Ptr fix = getFix(factory, testFile->m_editorWidget, resultIndex))
194 195 196 197 198
        fix->perform();
    else
        qDebug() << "Quickfix was not triggered";

    // Compare all files
199
    foreach (const QuickFixTestDocument::Ptr testFile, m_testFiles) {
200
        // Check
201
        QString result = testFile->m_editorWidget->document()->toPlainText();
202
        removeTrailingWhitespace(result);
203
        QCOMPARE(result, testFile->m_expectedSource);
204 205 206

        // Undo the change
        for (int i = 0; i < 100; ++i)
207
            testFile->m_editorWidget->undo();
208
        result = testFile->m_editorWidget->document()->toPlainText();
209
        QCOMPARE(result, testFile->m_source);
210
    }
211
}
212

213 214 215 216 217 218 219 220 221 222 223
QuickFixTestCase::~QuickFixTestCase()
{
    // Restore default cpp code style
    if (m_cppCodeStylePreferences)
        m_cppCodeStylePreferences->setCurrentDelegate(m_cppCodeStylePreferencesOriginalDelegateId);

    // Restore include paths
    if (m_restoreIncludePaths)
        m_modelManager->setIncludePaths(m_includePathsToRestore);

    // Remove created files from file system
224
    foreach (const QuickFixTestDocument::Ptr &testDocument, m_testFiles)
225 226 227
        QVERIFY(QFile::remove(testDocument->filePath()));
}

228 229 230 231 232 233 234
/// Delegates directly to AddIncludeForUndefinedIdentifierOp for easier testing.
class AddIncludeForUndefinedIdentifierTestFactory : public CppQuickFixFactory
{
public:
    AddIncludeForUndefinedIdentifierTestFactory(const QString &include)
        : m_include(include) {}

Thomas Hartmann's avatar
Thomas Hartmann committed
235
    void match(const CppQuickFixInterface &cppQuickFixInterface, QuickFixOperations &result)
236 237
    {
        result += CppQuickFixOperation::Ptr(
Thomas Hartmann's avatar
Thomas Hartmann committed
238
            new AddIncludeForUndefinedIdentifierOp(cppQuickFixInterface, 0, m_include));
239 240 241 242 243 244
    }

private:
    const QString m_include;
};

245 246 247 248 249 250 251 252 253
/// Apply the factory on the source and get back the resultIndex'th result or a null pointer.
QSharedPointer<TextEditor::QuickFixOperation> QuickFixTestCase::getFix(
        CppQuickFixFactory *factory, CPPEditorWidget *editorWidget, int resultIndex)
{
    CppQuickFixInterface qfi(new CppQuickFixAssistInterface(editorWidget, ExplicitlyInvoked));
    TextEditor::QuickFixOperations results;
    factory->match(qfi, results);
    return results.isEmpty() ? QuickFixOperation::Ptr() : results.at(resultIndex);
}
254

255 256 257 258 259
typedef QSharedPointer<CppQuickFixFactory> CppQuickFixFactoryPtr;

Q_DECLARE_METATYPE(CppQuickFixFactoryPtr)

void CppEditorPlugin::test_quickfix_data()
260
{
261 262 263 264 265 266 267
    QTest::addColumn<CppQuickFixFactoryPtr>("factory");
    QTest::addColumn<QByteArray>("original");
    QTest::addColumn<QByteArray>("expected");

    // Checks: All enum values are added as case statements for a blank switch.
    QTest::newRow("CompleteSwitchCaseStatement_basic1")
        << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _(
268 269 270 271 272 273 274
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    @switch (t) {\n"
        "    }\n"
275 276
        "}\n"
        ) << _(
277 278 279 280 281 282 283 284 285 286 287 288
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    switch (t) {\n"
        "    case V1:\n"
        "        break;\n"
        "    case V2:\n"
        "        break;\n"
        "    }\n"
        "}\n"
289
    );
290

291 292 293
    // Checks: All enum values are added as case statements for a blank switch with a default case.
    QTest::newRow("CompleteSwitchCaseStatement_basic2")
        << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _(
294 295 296 297 298 299 300 301 302
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    @switch (t) {\n"
        "    default:\n"
        "        break;\n"
        "    }\n"
303 304
        "}\n"
        ) << _(
305 306 307 308 309 310 311 312 313 314 315 316 317 318
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    switch (t) {\n"
        "    case V1:\n"
        "        break;\n"
        "    case V2:\n"
        "        break;\n"
        "    default:\n"
        "        break;\n"
        "    }\n"
        "}\n"
319
    );
320

321 322 323
    // Checks: The missing enum value is added.
    QTest::newRow("CompleteSwitchCaseStatement_oneValueMissing")
        << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _(
324 325 326 327 328 329 330 331 332 333 334
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    @switch (t) {\n"
        "    case V2:\n"
        "        break;\n"
        "    default:\n"
        "        break;\n"
        "    }\n"
335 336
        "}\n"
        ) << _(
337 338 339 340 341 342 343 344 345 346 347 348 349 350
        "enum EnumType { V1, V2 };\n"
        "\n"
        "void f()\n"
        "{\n"
        "    EnumType t;\n"
        "    switch (t) {\n"
        "    case V1:\n"
        "        break;\n"
        "    case V2:\n"
        "        break;\n"
        "    default:\n"
        "        break;\n"
        "    }\n"
        "}\n"
351
    );
352

353 354 355
    // Checks: Find the correct enum type despite there being a declaration with the same name.
    QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_1")
        << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _(
356 357 358 359 360 361 362
        "enum test { TEST_1, TEST_2 };\n"
        "\n"
        "void f() {\n"
        "    enum test test;\n"
        "    @switch (test) {\n"
        "    }\n"
        "}\n"
363
        ) << _(
364 365 366 367 368 369 370 371 372 373 374
        "enum test { TEST_1, TEST_2 };\n"
        "\n"
        "void f() {\n"
        "    enum test test;\n"
        "    switch (test) {\n"
        "    case TEST_1:\n"
        "        break;\n"
        "    case TEST_2:\n"
        "        break;\n"
        "    }\n"
        "}\n"
375
    );
376

377 378 379
    // Checks: Find the correct enum type despite there being a declaration with the same name.
    QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_2")
        << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _(
380 381 382 383 384 385 386 387 388
        "enum test1 { Wrong11, Wrong12 };\n"
        "enum test { Right1, Right2 };\n"
        "enum test2 { Wrong21, Wrong22 };\n"
        "\n"
        "int main() {\n"
        "    enum test test;\n"
        "    @switch (test) {\n"
        "    }\n"
        "}\n"
389
        ) << _(
390 391 392 393 394 395 396 397 398 399 400 401 402
        "enum test1 { Wrong11, Wrong12 };\n"
        "enum test { Right1, Right2 };\n"
        "enum test2 { Wrong21, Wrong22 };\n"
        "\n"
        "int main() {\n"
        "    enum test test;\n"
        "    switch (test) {\n"
        "    case Right1:\n"
        "        break;\n"
        "    case Right2:\n"
        "        break;\n"
        "    }\n"
        "}\n"
403
    );
404

405 406 407 408 409 410
    // Checks:
    // 1. If the name does not start with ("m_" or "_") and does not
    //    end with "_", we are forced to prefix the getter with "get".
    // 2. Setter: Use pass by value on integer/float and pointer types.
    QTest::newRow("GenerateGetterSetter_basicGetterWithPrefix")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
411 412 413 414 415
        "\n"
        "class Something\n"
        "{\n"
        "    int @it;\n"
        "};\n"
416
        ) << _(
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
        "\n"
        "class Something\n"
        "{\n"
        "    int it;\n"
        "\n"
        "public:\n"
        "    int getIt() const;\n"
        "    void setIt(int value);\n"
        "};\n"
        "\n"
        "int Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
436
    );
437

438 439 440 441
    // Checks: In addition to test_quickfix_GenerateGetterSetter_basicGetterWithPrefix
    // generated definitions should fit in the namespace.
    QTest::newRow("GenerateGetterSetter_basicGetterWithPrefixAndNamespace")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
442 443 444 445 446
        "namespace SomeNamespace {\n"
        "class Something\n"
        "{\n"
        "    int @it;\n"
        "};\n"
447 448
        "}\n"
        ) << _(
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
        "namespace SomeNamespace {\n"
        "class Something\n"
        "{\n"
        "    int it;\n"
        "\n"
        "public:\n"
        "    int getIt() const;\n"
        "    void setIt(int value);\n"
        "};\n"
        "int Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
        "\n"
468
        "}\n"
469
    );
470

471 472 473 474 475
    // Checks:
    // 1. Getter: "get" prefix is not necessary.
    // 2. Setter: Parameter name is base name.
    QTest::newRow("GenerateGetterSetter_basicGetterWithoutPrefix")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
476 477 478 479 480
        "\n"
        "class Something\n"
        "{\n"
        "    int @m_it;\n"
        "};\n"
481
        ) << _(
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
        "\n"
        "class Something\n"
        "{\n"
        "    int m_it;\n"
        "\n"
        "public:\n"
        "    int it() const;\n"
        "    void setIt(int it);\n"
        "};\n"
        "\n"
        "int Something::it() const\n"
        "{\n"
        "    return m_it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int it)\n"
        "{\n"
        "    m_it = it;\n"
        "}\n"
501
    );
502

503 504 505 506
    // Check: Setter: Use pass by reference for parameters which
    // are not integer, float or pointers.
    QTest::newRow("GenerateGetterSetter_customType")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
507 508 509 510 511
        "\n"
        "class Something\n"
        "{\n"
        "    MyType @it;\n"
        "};\n"
512
        ) << _(
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
        "\n"
        "class Something\n"
        "{\n"
        "    MyType it;\n"
        "\n"
        "public:\n"
        "    MyType getIt() const;\n"
        "    void setIt(const MyType &value);\n"
        "};\n"
        "\n"
        "MyType Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(const MyType &value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
532
    );
533

534 535 536 537 538
    // Checks:
    // 1. Setter: No setter is generated for const members.
    // 2. Getter: Return a non-const type since it pass by value anyway.
    QTest::newRow("GenerateGetterSetter_constMember")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
539 540 541 542 543
        "\n"
        "class Something\n"
        "{\n"
        "    const int @it;\n"
        "};\n"
544
        ) << _(
545 546 547 548 549 550 551 552 553 554 555 556 557
        "\n"
        "class Something\n"
        "{\n"
        "    const int it;\n"
        "\n"
        "public:\n"
        "    int getIt() const;\n"
        "};\n"
        "\n"
        "int Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
558
    );
559

560 561 562
    // Checks: No special treatment for pointer to non const.
    QTest::newRow("GenerateGetterSetter_pointerToNonConst")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
563 564 565 566 567
        "\n"
        "class Something\n"
        "{\n"
        "    int *it@;\n"
        "};\n"
568
        ) << _(
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
        "\n"
        "class Something\n"
        "{\n"
        "    int *it;\n"
        "\n"
        "public:\n"
        "    int *getIt() const;\n"
        "    void setIt(int *value);\n"
        "};\n"
        "\n"
        "int *Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int *value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
588
    );
589

590 591 592
    // Checks: No special treatment for pointer to const.
    QTest::newRow("GenerateGetterSetter_pointerToConst")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
593 594 595 596 597
        "\n"
        "class Something\n"
        "{\n"
        "    const int *it@;\n"
        "};\n"
598
        ) << _(
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
        "\n"
        "class Something\n"
        "{\n"
        "    const int *it;\n"
        "\n"
        "public:\n"
        "    const int *getIt() const;\n"
        "    void setIt(const int *value);\n"
        "};\n"
        "\n"
        "const int *Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(const int *value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
618
    );
619

620 621 622 623 624
    // Checks:
    // 1. Setter: Setter is a static function.
    // 2. Getter: Getter is a static, non const function.
    QTest::newRow("GenerateGetterSetter_staticMember")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
625 626 627 628 629
        "\n"
        "class Something\n"
        "{\n"
        "    static int @m_member;\n"
        "};\n"
630
        ) << _(
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
        "\n"
        "class Something\n"
        "{\n"
        "    static int m_member;\n"
        "\n"
        "public:\n"
        "    static int member();\n"
        "    static void setMember(int member);\n"
        "};\n"
        "\n"
        "int Something::member()\n"
        "{\n"
        "    return m_member;\n"
        "}\n"
        "\n"
        "void Something::setMember(int member)\n"
        "{\n"
        "    m_member = member;\n"
        "}\n"
650
    );
651

652 653 654
    // Check: Check if it works on the second declarator
    QTest::newRow("GenerateGetterSetter_secondDeclarator")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
655 656 657 658 659
        "\n"
        "class Something\n"
        "{\n"
        "    int *foo, @it;\n"
        "};\n"
660
        ) << _(
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
        "\n"
        "class Something\n"
        "{\n"
        "    int *foo, it;\n"
        "\n"
        "public:\n"
        "    int getIt() const;\n"
        "    void setIt(int value);\n"
        "};\n"
        "\n"
        "int Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
680
    );
681

682 683 684
    // Check: Quick fix is offered for "int *@it;" ('@' denotes the text cursor position)
    QTest::newRow("GenerateGetterSetter_triggeringRightAfterPointerSign")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
685 686 687 688 689
        "\n"
        "class Something\n"
        "{\n"
        "    int *@it;\n"
        "};\n"
690
        ) << _(
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
        "\n"
        "class Something\n"
        "{\n"
        "    int *it;\n"
        "\n"
        "public:\n"
        "    int *getIt() const;\n"
        "    void setIt(int *value);\n"
        "};\n"
        "\n"
        "int *Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int *value)\n"
        "{\n"
        "    it = value;\n"
        "}\n"
710
    );
711

712 713 714
    // Check: Quick fix is not triggered on a member function.
    QTest::newRow("GenerateGetterSetter_notTriggeringOnMemberFunction")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter)
715
        << _("class Something { void @f(); };\n") << _();
716

717 718 719
    // Check: Quick fix is not triggered on an member array;
    QTest::newRow("GenerateGetterSetter_notTriggeringOnMemberArray")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter)
720
        << _("class Something { void @a[10]; };\n") << _();
721

722 723 724 725
    // Check: Do not offer the quick fix if there is already a member with the
    // getter or setter name we would generate.
    QTest::newRow("GenerateGetterSetter_notTriggeringWhenGetterOrSetterExist")
        << CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
726 727 728
        "class Something {\n"
        "     int @it;\n"
        "     void setIt();\n"
729 730
        "};\n"
        ) << _();
731

732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
    QTest::newRow("MoveDeclarationOutOfIf_ifOnly")
        << CppQuickFixFactoryPtr(new MoveDeclarationOutOfIf) << _(
        "void f()\n"
        "{\n"
        "    if (Foo *@foo = g())\n"
        "        h();\n"
        "}\n"
        ) << _(
        "void f()\n"
        "{\n"
        "    Foo *foo = g();\n"
        "    if (foo)\n"
        "        h();\n"
        "}\n"
    );
747

748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
    QTest::newRow("MoveDeclarationOutOfIf_ifElse")
        << CppQuickFixFactoryPtr(new MoveDeclarationOutOfIf) << _(
        "void f()\n"
        "{\n"
        "    if (Foo *@foo = g())\n"
        "        h();\n"
        "    else\n"
        "        i();\n"
        "}\n"
        ) << _(
        "void f()\n"
        "{\n"
        "    Foo *foo = g();\n"
        "    if (foo)\n"
        "        h();\n"
        "    else\n"
        "        i();\n"
        "}\n"
    );
767

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
    QTest::newRow("MoveDeclarationOutOfIf_ifElseIf")
        << CppQuickFixFactoryPtr(new MoveDeclarationOutOfIf) << _(
        "void f()\n"
        "{\n"
        "    if (Foo *foo = g()) {\n"
        "        if (Bar *@bar = x()) {\n"
        "            h();\n"
        "            j();\n"
        "        }\n"
        "    } else {\n"
        "        i();\n"
        "    }\n"
        "}\n"
        ) << _(
        "void f()\n"
        "{\n"
        "    if (Foo *foo = g()) {\n"
        "        Bar *bar = x();\n"
        "        if (bar) {\n"
        "            h();\n"
        "            j();\n"
        "        }\n"
        "    } else {\n"
        "        i();\n"
        "    }\n"
        "}\n"
    );
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
    QTest::newRow("MoveDeclarationOutOfWhile_singleWhile")
        << CppQuickFixFactoryPtr(new MoveDeclarationOutOfWhile) << _(
        "void f()\n"
        "{\n"
        "    while (Foo *@foo = g())\n"
        "        j();\n"
        "}\n"
        ) << _(
        "void f()\n"
        "{\n"
        "    Foo *foo;\n"
        "    while ((foo = g()) != 0)\n"
        "        j();\n"
        "}\n"
    );
811

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
    QTest::newRow("MoveDeclarationOutOfWhile_whileInWhile")
        << CppQuickFixFactoryPtr(new MoveDeclarationOutOfWhile) << _(
        "void f()\n"
        "{\n"
        "    while (Foo *foo = g()) {\n"
        "        while (Bar *@bar = h()) {\n"
        "            i();\n"
        "            j();\n"
        "        }\n"
        "    }\n"
        "}\n"
        ) << _(
        "void f()\n"
        "{\n"
        "    while (Foo *foo = g()) {\n"
        "        Bar *bar;\n"
        "        while ((bar = h()) != 0) {\n"
        "            i();\n"
        "            j();\n"
        "        }\n"
        "    }\n"
        "}\n"
    );
835

836 837 838 839 840
    // Check: Just a basic test since the main functionality is tested in
    // cpppointerdeclarationformatter_test.cpp
    QTest::newRow("ReformatPointerDeclaration")
        << CppQuickFixFactoryPtr(new ReformatPointerDeclaration)
        << _("char@*s;")
841
        << _("char *s;");
842

843 844
    // Check from source file: If there is no header file, insert the definition after the class.
    QByteArray original =
845 846 847
        "struct Foo\n"
        "{\n"
        "    Foo();@\n"
848
        "};\n";
849 850 851 852

    QTest::newRow("InsertDefFromDecl_basic")
        << CppQuickFixFactoryPtr(new InsertDefFromDecl) << original
           << original + _(
853 854
        "\n"
        "\n"
855
        "Foo::Foo()\n"
856
        "{\n\n"
857
        "}\n"
858
    );
859

860 861 862 863
    QTest::newRow("InsertDefFromDecl_freeFunction")
        << CppQuickFixFactoryPtr(new InsertDefFromDecl)
        << _("void free()@;\n")
        << _(
864
        "void free()\n"
865
        "{\n\n"
866
        "}\n"
867
    );
868

869 870 871
    // Check not triggering when it is a statement
    QTest::newRow("InsertDefFromDecl_notTriggeringStatement")
        << CppQuickFixFactoryPtr(new InsertDefFromDecl) << _(
872 873 874 875 876 877
            "class Foo {\n"
            "public:\n"
            "    Foo() {}\n"
            "};\n"
            "void freeFunc() {\n"
            "    Foo @f();"
878 879
            "}\n"
        ) << _();
880

881 882 883
    // Check: Add local variable for a free function.
    QTest::newRow("AssignToLocalVariable_freeFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
884
        "int foo() {return 1;}\n"
885
        "void bar() {fo@o();}\n"
886
        ) << _(
887
        "int foo() {return 1;}\n"
888 889
        "void bar() {int localFoo = foo();}\n"
    );
890

891 892 893
    // Check: Add local variable for a member function.
    QTest::newRow("AssignToLocalVariable_memberFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
894 895 896 897
        "class Foo {public: int* fooFunc();}\n"
        "void bar() {\n"
        "    Foo *f = new Foo;\n"
        "    @f->fooFunc();\n"
898
        "}\n"
899
        ) << _(
900 901 902 903
        "class Foo {public: int* fooFunc();}\n"
        "void bar() {\n"
        "    Foo *f = new Foo;\n"
        "    int *localFooFunc = f->fooFunc();\n"
904 905
        "}\n"
    );
906

907 908 909
    // Check: Add local variable for a static member function.
    QTest::newRow("AssignToLocalVariable_staticMemberFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
910 911 912
        "class Foo {public: static int* fooFunc();}\n"
        "void bar() {\n"
        "    Foo::fooF@unc();\n"
913 914
        "}"
        ) << _(
915 916 917
        "class Foo {public: static int* fooFunc();}\n"
        "void bar() {\n"
        "    int *localFooFunc = Foo::fooFunc();\n"
918
        "}"
919
    );
920

921 922 923
    // Check: Add local variable for a new Expression.
    QTest::newRow("AssignToLocalVariable_newExpression")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
924 925 926
        "class Foo {}\n"
        "void bar() {\n"
        "    new Fo@o;\n"
927 928
        "}"
        ) << _(
929 930 931
        "class Foo {}\n"
        "void bar() {\n"
        "    Foo *localFoo = new Foo;\n"
932
        "}"
933
    );
934

935 936 937
    // Check: No trigger for function inside member initialization list.
    QTest::newRow("AssignToLocalVariable_noInitializationList")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
938 939 940 941 942
        "class Foo\n"
        "{\n"
        "    public: Foo : m_i(fooF@unc()) {}\n"
        "    int fooFunc() {return 2;}\n"
        "    int m_i;\n"
943
        "};\n"
944
        ) << _();
945

946 947 948
    // Check: No trigger for void functions.
    QTest::newRow("AssignToLocalVariable_noVoidFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
949
        "void foo() {}\n"
950 951
        "void bar() {fo@o();}"
        ) << _();
952

953 954 955
    // Check: No trigger for void member functions.
    QTest::newRow("AssignToLocalVariable_noVoidMemberFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
956 957 958 959
        "class Foo {public: void fooFunc();}\n"
        "void bar() {\n"
        "    Foo *f = new Foo;\n"
        "    @f->fooFunc();\n"
960 961
        "}"
        ) << _();
962

963 964 965
    // Check: No trigger for void static member functions.
    QTest::newRow("AssignToLocalVariable_noVoidStaticMemberFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
966 967 968
        "class Foo {public: static void fooFunc();}\n"
        "void bar() {\n"
        "    Foo::fo@oFunc();\n"
969 970
        "}"
        ) << _();
971

972 973 974
    // Check: No trigger for functions in expressions.
    QTest::newRow("AssignToLocalVariable_noFunctionInExpression")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
975 976
        "int foo(int a) {return a;}\n"
        "int bar() {return 1;}"
977 978
        "void baz() {foo(@bar() + bar());}"
        ) << _();
979

980 981 982
    // Check: No trigger for functions in functions. (QTCREATORBUG-9510)
    QTest::newRow("AssignToLocalVariable_noFunctionInFunction")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
983 984 985 986
        "int foo(int a, int b) {return a + b;}\n"
        "int bar(int a) {return a;}\n"
        "void baz() {\n"
        "    int a = foo(ba@r(), bar());\n"
987 988
        "}\n"
        ) << _();
989

990 991 992
    // Check: No trigger for functions in return statements (classes).
    QTest::newRow("AssignToLocalVariable_noReturnClass1")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
993 994 995
        "class Foo {public: static void fooFunc();}\n"
        "Foo* bar() {\n"
        "    return new Fo@o;\n"
996 997
        "}"
        ) << _();
998

999 1000 1001
    // Check: No trigger for functions in return statements (classes). (QTCREATORBUG-9525)
    QTest::newRow("AssignToLocalVariable_noReturnClass2")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
1002 1003 1004
        "class Foo {public: int fooFunc();}\n"
        "int bar() {\n"
        "    return (new Fo@o)->fooFunc();\n"
1005 1006
        "}"
        ) << _();
1007

1008 1009 1010
    // Check: No trigger for functions in return statements (functions).
    QTest::newRow("AssignToLocalVariable_noReturnFunc1")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
1011 1012 1013
        "class Foo {public: int fooFunc();}\n"
        "int bar() {\n"
        "    return Foo::fooFu@nc();\n"
1014 1015
        "}"
        ) << _();
1016

1017 1018 1019
    // Check: No trigger for functions in return statements (functions). (QTCREATORBUG-9525)
    QTest::newRow("AssignToLocalVariable_noReturnFunc2")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
1020 1021
        "int bar() {\n"
        "    return list.firs@t().foo;\n"
1022 1023
        "}\n"
        ) << _();
1024

1025 1026 1027
    // Check: No trigger for functions which does not match in signature.
    QTest::newRow("AssignToLocalVariable_noSignatureMatch")
        << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _(
1028 1029 1030 1031 1032
        "int someFunc(int);\n"
        "\n"
        "void f()\n"
        "{\n"
        "    some@Func();\n"
1033 1034
        "}"
        ) << _();
1035

1036 1037
    QTest::newRow("ExtractLiteralAsParameter_freeFunction")
        << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _(
1038
        "void foo(const char *a, long b = 1)\n"
1039
        "{return 1@56 + 123 + 156;}\n"
1040
        ) << _(
1041
        "void foo(const char *a, long b = 1, int newParameter = 156)\n"
1042 1043
        "{return newParameter + 123 + newParameter;}\n"
    );
1044

1045 1046
    QTest::newRow("ExtractLiteralAsParameter_memberFunction")
        << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _(
1047 1048 1049 1050 1051
        "class Narf {\n"
        "public:\n"
        "    int zort();\n"
        "};\n\n"
        "int Narf::zort()\n"
1052
        "{ return 15@5 + 1; }\n"
1053
        ) << _(
1054 1055 1056 1057 1058
        "class Narf {\n"
        "public:\n"
        "    int zort(int newParameter = 155);\n"
        "};\n\n"
        "int Narf::zort(int newParameter)\n"
1059 1060
        "{ return newParameter + 1; }\n"
    );
1061

1062 1063
    QTest::newRow("ExtractLiteralAsParameter_memberFunctionInline")
        << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _(
1064 1065 1066 1067
        "class Narf {\n"
        "public:\n"
        "    int zort()\n"
        "    { return 15@5 + 1; }\n"
1068
        "};\n"
1069
        ) << _(
1070 1071 1072 1073
        "class Narf {\n"
        "public:\n"
        "    int zort(int newParameter = 155)\n"
        "    { return newParameter + 1; }\n"
1074 1075 1076 1077 1078 1079 1080
        "};\n"
    );

    // Check: optimize postcrement
    QTest::newRow("OptimizeForLoop_postcrement")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {f@or (int i = 0; i < 3; i++) {}}\n")
1081
        << _("void foo() {for (int i = 0; i < 3; ++i) {}}\n");
1082 1083 1084 1085 1086

    // Check: optimize condition
    QTest::newRow("OptimizeForLoop_condition")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {f@or (int i = 0; i < 3 + 5; ++i) {}}\n")
1087
        << _("void foo() {for (int i = 0, total = 3 + 5; i < total; ++i) {}}\n");
1088 1089 1090 1091 1092

    // Check: optimize fliped condition
    QTest::newRow("OptimizeForLoop_flipedCondition")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {f@or (int i = 0; 3 + 5 > i; ++i) {}}\n")
1093
        << _("void foo() {for (int i = 0, total = 3 + 5; total > i; ++i) {}}\n");
1094 1095 1096 1097 1098

    // Check: if "total" used, create other name.
    QTest::newRow("OptimizeForLoop_alterVariableName")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {f@or (int i = 0, total = 0; i < 3 + 5; ++i) {}}\n")
1099
        << _("void foo() {for (int i = 0, total = 0, totalX = 3 + 5; i < totalX; ++i) {}}\n");
1100 1101 1102 1103 1104

    // Check: optimize postcrement and condition
    QTest::newRow("OptimizeForLoop_optimizeBoth")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {f@or (int i = 0; i < 3 + 5; i++) {}}\n")
1105
        << _("void foo() {for (int i = 0, total = 3 + 5; i < total; ++i) {}}\n");
1106 1107 1108 1109 1110

    // Check: empty initializier
    QTest::newRow("OptimizeForLoop_emptyInitializer")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("int i; void foo() {f@or (; i < 3 + 5; ++i) {}}\n")
1111
        << _("int i; void foo() {for (int total = 3 + 5; i < total; ++i) {}}\n");
1112 1113 1114 1115 1116

    // Check: wrong initializier type -> no trigger
    QTest::newRow("OptimizeForLoop_wrongInitializer")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("int i; void foo() {f@or (double a = 0; i < 3 + 5; ++i) {}}\n")
1117
        << _("int i; void foo() {f@or (double a = 0; i < 3 + 5; ++i) {}}\n");
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129

    // Check: No trigger when numeric
    QTest::newRow("OptimizeForLoop_noTriggerNumeric1")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {fo@r (int i = 0; i < 3; ++i) {}}\n")
        << _();

    // Check: No trigger when numeric
    QTest::newRow("OptimizeForLoop_noTriggerNumeric2")
        << CppQuickFixFactoryPtr(new OptimizeForLoop)
        << _("void foo() {fo@r (int i = 0; i < -3; ++i) {}}\n")
        << _();
1130 1131
}

1132
void CppEditorPlugin::test_quickfix()
1133
{
1134 1135 1136
    QFETCH(CppQuickFixFactoryPtr, factory);
    QFETCH(QByteArray, original);
    QFETCH(QByteArray, expected);
1137

1138
    if (expected.isEmpty())
1139
        expected = original;
1140
    QuickFixTestCase(singleDocument(original, expected), factory.data());
1141 1142 1143 1144 1145 1146
}

/// Checks: In addition to test_quickfix_GenerateGetterSetter_basicGetterWithPrefix
/// generated definitions should fit in the namespace.
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespaceToCpp()
{
1147
    QList<QuickFixTestDocument::Ptr> testFiles;
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
    QByteArray original;
    QByteArray expected;

    // Header File
    original =
        "namespace SomeNamespace {\n"
        "class Something\n"
        "{\n"
        "    int @it;\n"
        "};\n"
        "}\n";
    expected =
        "namespace SomeNamespace {\n"
        "class Something\n"
        "{\n"
        "    int it;\n"
        "\n"
        "public:\n"
        "    int getIt() const;\n"
        "    void setIt(int value);\n"
        "};\n"
1169
        "}\n";
1170
    testFiles << QuickFixTestDocument::create("file.h", original, expected);
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188

    // Source File
    original =
        "#include \"file.h\"\n"
        "namespace SomeNamespace {\n"
        "}\n";
    expected =
        "#include \"file.h\"\n"
        "namespace SomeNamespace {\n"
        "int Something::getIt() const\n"
        "{\n"
        "    return it;\n"
        "}\n"
        "\n"
        "void Something::setIt(int value)\n"
        "{\n"
        "    it = value;\n"
        "}\n\n"
1189
        "}\n";
1190
    testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
1191 1192

    GenerateGetterSetter factory;
1193
    QuickFixTestCase(testFiles, &factory);
1194 1195 1196 1197 1198
}

/// Check if definition is inserted right after class for insert definition outside
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_afterClass()
{
1199
    QList<QuickFixTestDocument::Ptr> testFiles;
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
    QByteArray original;
    QByteArray expected;

    // Header File
    original =
        "class Foo\n"
        "{\n"
        "    Foo();\n"
        "    void a@();\n"
        "};\n"
        "\n"
        "class Bar {};\n";
    expected =
        "class Foo\n"
        "{\n"
        "    Foo();\n"
        "    void a();\n"
        "};\n"
        "\n"
        "void Foo::a()\n"
        "{\n\n}\n"
        "\n"
1222
        "class Bar {};\n";
1223
    testFiles << QuickFixTestDocument::create("file.h", original, expected);
1224 1225 1226 1227 1228 1229 1230 1231

    // Source File
    original =
        "#include \"file.h\"\n"
        "\n"
        "Foo::Foo()\n"
        "{\n\n"
        "}\n";
1232
    expected = original;
1233
    testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
1234 1235

    InsertDefFromDecl factory;
1236
    QuickFixTestCase(testFiles, &factory, QStringList(), 1);
1237 1238 1239 1240 1241
}

/// Check from header file: If there is a source file, insert the definition in the source file.
/// Case: Source file is empty.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic1()
1242
{
1243
    QList<QuickFixTestDocument::Ptr> testFiles;
1244 1245 1246 1247 1248 1249 1250 1251 1252

    QByteArray original;
    QByteArray expected;

    // Header File
    original =
        "struct Foo\n"
        "{\n"
        "    Foo()@;\n"
1253
        "};\n";
1254
    expected = original;
1255
    testFiles << QuickFixTestDocument::create("file.h", original, expected);
1256 1257 1258 1259 1260 1261 1262 1263 1264

    // Source File
    original.resize(0);
    expected =
        "\n"
        "Foo::Foo()\n"
        "{\n\n"
        "}\n"
        ;
1265
    testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
1266 1267

    InsertDefFromDecl factory;
1268
    QuickFixTestCase(testFiles, &factory);
1269 1270 1271 1272 1273 1274
}

/// Check from header file: If there is a source file, insert the definition in the source file.
/// Case: Source file is not empty.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic2()
{
1275
    QList<QuickFixTestDocument::Ptr> testFiles;
1276 1277 1278 1279 1280 1281

    QByteArray original;
    QByteArray expected;

    // Header File
    original = "void f()@;\n";
1282
    expected = original;
1283
    testFiles << QuickFixT