cppcodegen_test.cpp 19.1 KB
Newer Older
Bill King's avatar
Bill King committed
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
Bill King's avatar
Bill King committed
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
Bill King's avatar
Bill King committed
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
Bill King's avatar
Bill King committed
18 19
**
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
Bill King's avatar
Bill King committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
Bill King's avatar
Bill King committed
28 29 30
**
**************************************************************************/

31 32
#include "cpptoolsplugin.h"

33 34 35 36 37 38 39
#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
40
#include <Bind.h>
41
#include <Symbols.h>
42 43
#include <cpptools/insertionpointlocator.h>
#include <cpptools/cpprefactoringchanges.h>
44 45
#include <cpptools/cpptoolsplugin.h>
#include <extensionsystem/pluginmanager.h>
46
#include <utils/fileutils.h>
47 48

#include <QtTest>
hjk's avatar
hjk committed
49
#include <QDebug>
50
#include <QTextDocument>
51
#include <QDir>
52

53 54 55 56
/*!
    Tests for various parts of the code generation. Well, okay, currently it only
    tests the InsertionPointLocator.
 */
57
using namespace CPlusPlus;
58
using namespace CppTools;
59
using namespace CppTools::Internal;
60

61 62 63
/*!
    Should insert at line 3, column 1, with "public:\n" as prefix and without suffix.
 */
64
void CppToolsPlugin::test_codegen_public_in_empty_class()
65 66 67 68
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
69
            "};\n"
70 71
            "\n";

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

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

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

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

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

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

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

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

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

140 141 142
/*!
    Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix.
 */
143
void CppToolsPlugin::test_codegen_public_before_protected()
144 145 146 147 148 149 150 151 152
{
    const QByteArray src = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "protected:\n" // line 3
            "};\n"
            "\n";

    Document::Ptr doc = Document::create("public_before_protected");
153
    doc->setUtf8Source(src);
154 155 156 157 158 159
    doc->parse();
    doc->check();

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

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

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

180 181 182 183
/*!
    Should insert at line 4, column 1, with "private:\n" as prefix and without
    suffix.
 */
184
void CppToolsPlugin::test_codegen_private_after_protected()
185 186 187 188 189 190 191 192 193
{
    const QByteArray src = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "protected:\n" // line 3
            "};\n"
            "\n";

    Document::Ptr doc = Document::create("private_after_protected");
194
    doc->setUtf8Source(src);
195 196 197 198 199 200
    doc->parse();
    doc->check();

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

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

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

221 222 223 224
/*!
    Should insert at line 4, column 1, with "protected:\n" as prefix and without
    suffix.
 */
225
void CppToolsPlugin::test_codegen_protected_in_nonempty_class()
226 227 228 229 230 231 232 233 234
{
    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");
235
    doc->setUtf8Source(src);
236 237 238 239 240 241
    doc->parse();
    doc->check();

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

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

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

262 263 264
/*!
    Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix.
 */
265
void CppToolsPlugin::test_codegen_protected_between_public_and_private()
266 267 268 269 270 271 272 273 274 275
{
    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");
276
    doc->setUtf8Source(src);
277 278 279 280 281 282
    doc->parse();
    doc->check();

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

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

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

303 304 305 306 307 308 309
/*!
    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.
 */
310
void CppToolsPlugin::test_codegen_qtdesigner_integration()
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
{
    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");
337
    doc->setUtf8Source(src);
338 339 340 341 342 343
    doc->parse();
    doc->check();

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

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

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

364
void CppToolsPlugin::test_codegen_definition_empty_class()
365 366 367 368 369 370 371 372 373 374 375 376
{
    const QByteArray srcText = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "void foo();\n" // line 3
            "};\n"
            "\n";

    const QByteArray dstText = "\n"
            "int x;\n"  // line 1
            "\n";

377
    Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h"));
378 379 380
    Utils::FileSaver srcSaver(src->fileName());
    srcSaver.write(srcText);
    srcSaver.finalize();
381
    src->setUtf8Source(srcText);
382 383 384 385 386
    src->parse();
    src->check();
    QCOMPARE(src->diagnosticMessages().size(), 0);
    QCOMPARE(src->globalSymbolCount(), 1U);

387
    Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp"));
388 389 390
    Utils::FileSaver dstSaver(dst->fileName());
    dstSaver.write(dstText);
    dstSaver.finalize();
391
    dst->setUtf8Source(dstText);
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    dst->parse();
    dst->check();
    QCOMPARE(dst->diagnosticMessages().size(), 0);
    QCOMPARE(dst->globalSymbolCount(), 1U);

    Snapshot snapshot;
    snapshot.insert(src);
    snapshot.insert(dst);

    Class *foo = src->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
    QCOMPARE(foo->memberCount(), 1U);
    Declaration *decl = foo->memberAt(0)->asDeclaration();
    QVERIFY(decl);
    QCOMPARE(decl->line(), 3U);
    QCOMPARE(decl->column(), 6U);

    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    QList<InsertionLocation> locList = find.methodDefinition(decl);
    QVERIFY(locList.size() == 1);
    InsertionLocation loc = locList.first();
416
    QCOMPARE(loc.fileName(), dst->fileName());
417 418
    QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
    QCOMPARE(loc.suffix(), QString());
Leandro Melo's avatar
Leandro Melo committed
419 420
    QCOMPARE(loc.line(), 3U);
    QCOMPARE(loc.column(), 1U);
421 422
}

423
void CppToolsPlugin::test_codegen_definition_first_member()
424 425 426 427 428 429 430 431 432
{
    const QByteArray srcText = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "void foo();\n" // line 3
            "void bar();\n" // line 4
            "};\n"
            "\n";

433 434 435 436 437 438 439 440 441 442
    const QByteArray dstText = QString(
                "\n"
                "#include \"%1/file.h\"\n" // line 1
                "int x;\n"
                "\n"
                "void Foo::bar()\n" // line 4
                "{\n"
                "\n"
                "}\n"
                "\n"
443
                "int y;\n").arg(QDir::tempPath()).toLatin1();
444

445
    Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h"));
446 447 448
    Utils::FileSaver srcSaver(src->fileName());
    srcSaver.write(srcText);
    srcSaver.finalize();
449
    src->setUtf8Source(srcText);
450 451 452 453 454
    src->parse();
    src->check();
    QCOMPARE(src->diagnosticMessages().size(), 0);
    QCOMPARE(src->globalSymbolCount(), 1U);

455
    Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp"));
456
    dst->addIncludeFile(src->fileName(), 1);
457 458 459
    Utils::FileSaver dstSaver(dst->fileName());
    dstSaver.write(dstText);
    dstSaver.finalize();
460
    dst->setUtf8Source(dstText);
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
    dst->parse();
    dst->check();
    QCOMPARE(dst->diagnosticMessages().size(), 0);
    QCOMPARE(dst->globalSymbolCount(), 3U);

    Snapshot snapshot;
    snapshot.insert(src);
    snapshot.insert(dst);

    Class *foo = src->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
    QCOMPARE(foo->memberCount(), 2U);
    Declaration *decl = foo->memberAt(0)->asDeclaration();
    QVERIFY(decl);
    QCOMPARE(decl->line(), 3U);
    QCOMPARE(decl->column(), 6U);

    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    QList<InsertionLocation> locList = find.methodDefinition(decl);
    QVERIFY(locList.size() == 1);
    InsertionLocation loc = locList.first();
485
    QCOMPARE(loc.fileName(), dst->fileName());
486 487 488 489 490 491
    QCOMPARE(loc.line(), 4U);
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.suffix(), QLatin1String("\n\n"));
    QCOMPARE(loc.prefix(), QString());
}

492
void CppToolsPlugin::test_codegen_definition_last_member()
493 494 495 496 497 498 499 500 501
{
    const QByteArray srcText = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "void foo();\n" // line 3
            "void bar();\n" // line 4
            "};\n"
            "\n";

502 503 504 505 506 507 508 509 510 511
    const QByteArray dstText = QString(
                "\n"
                "#include \"%1/file.h\"\n" // line 1
                "int x;\n"
                "\n"
                "void Foo::foo()\n" // line 4
                "{\n"
                "\n"
                "}\n" // line 7
                "\n"
512
                "int y;\n").arg(QDir::tempPath()).toLatin1();
513

514
    Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h"));
515 516 517
    Utils::FileSaver srcSaver(src->fileName());
    srcSaver.write(srcText);
    srcSaver.finalize();
518
    src->setUtf8Source(srcText);
519 520 521 522 523
    src->parse();
    src->check();
    QCOMPARE(src->diagnosticMessages().size(), 0);
    QCOMPARE(src->globalSymbolCount(), 1U);

524
    Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp"));
525
    dst->addIncludeFile(src->fileName(), 1);
526 527 528
    Utils::FileSaver dstSaver(dst->fileName());
    dstSaver.write(dstText);
    dstSaver.finalize();
529
    dst->setUtf8Source(dstText);
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
    dst->parse();
    dst->check();
    QCOMPARE(dst->diagnosticMessages().size(), 0);
    QCOMPARE(dst->globalSymbolCount(), 3U);

    Snapshot snapshot;
    snapshot.insert(src);
    snapshot.insert(dst);

    Class *foo = src->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
    QCOMPARE(foo->memberCount(), 2U);
    Declaration *decl = foo->memberAt(1)->asDeclaration();
    QVERIFY(decl);
    QCOMPARE(decl->line(), 4U);
    QCOMPARE(decl->column(), 6U);

    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    QList<InsertionLocation> locList = find.methodDefinition(decl);
    QVERIFY(locList.size() == 1);
    InsertionLocation loc = locList.first();
554
    QCOMPARE(loc.fileName(), dst->fileName());
555 556 557 558 559 560
    QCOMPARE(loc.line(), 7U);
    QCOMPARE(loc.column(), 2U);
    QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
    QCOMPARE(loc.suffix(), QString());
}

561
void CppToolsPlugin::test_codegen_definition_middle_member()
562 563 564 565 566 567 568 569 570 571
{
    const QByteArray srcText = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "void foo();\n" // line 3
            "void bar();\n" // line 4
            "void car();\n" // line 5
            "};\n"
            "\n";

572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
    const QByteArray dstText = QString(
                "\n"
                "#include \"%1/file.h\"\n" // line 1
                "int x;\n"
                "\n"
                "void Foo::foo()\n" // line 4
                "{\n"
                "\n"
                "}\n" // line 7
                "\n"
                "void Foo::car()\n" // line 9
                "{\n"
                "\n"
                "}\n"
                "\n"
587
                "int y;\n").arg(QDir::tempPath()).toLatin1();
588

589
    Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h"));
590 591 592
    Utils::FileSaver srcSaver(src->fileName());
    srcSaver.write(srcText);
    srcSaver.finalize();
593
    src->setUtf8Source(srcText);
594 595 596 597 598
    src->parse();
    src->check();
    QCOMPARE(src->diagnosticMessages().size(), 0);
    QCOMPARE(src->globalSymbolCount(), 1U);

599
    Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp"));
600
    dst->addIncludeFile(src->fileName(), 1);
601 602 603
    Utils::FileSaver dstSaver(dst->fileName());
    dstSaver.write(dstText);
    dstSaver.finalize();
604
    dst->setUtf8Source(dstText);
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
    dst->parse();
    dst->check();
    QCOMPARE(dst->diagnosticMessages().size(), 0);
    QCOMPARE(dst->globalSymbolCount(), 4U);

    Snapshot snapshot;
    snapshot.insert(src);
    snapshot.insert(dst);

    Class *foo = src->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
    QCOMPARE(foo->memberCount(), 3U);
    Declaration *decl = foo->memberAt(1)->asDeclaration();
    QVERIFY(decl);
    QCOMPARE(decl->line(), 4U);
    QCOMPARE(decl->column(), 6U);

    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    QList<InsertionLocation> locList = find.methodDefinition(decl);
    QVERIFY(locList.size() == 1);
    InsertionLocation loc = locList.first();
629
    QCOMPARE(loc.fileName(), dst->fileName());
630 631 632 633 634
    QCOMPARE(loc.line(), 7U);
    QCOMPARE(loc.column(), 2U);
    QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
    QCOMPARE(loc.suffix(), QString());
}