diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-11-14 15:08:25 +0100 |
---|---|---|
committer | Bill King <bill.king@nokia.com> | 2011-11-15 15:37:29 +0100 |
commit | bc1b724476db3f7d52ad135857b693487644611f (patch) | |
tree | b25c6573d3cd1c56631d2abea8460ff2e7f208ea /src/plugins/cpptools/cppcodegen_test.cpp | |
parent | e93d685a9e8637d78dc0f6cceaf1959a8213f9e0 (diff) | |
download | qt-creator-bc1b724476db3f7d52ad135857b693487644611f.tar.gz |
C++: Move codegen test into the CppTools plugin.
Change-Id: I4c70a9dbd5445188c3d202427da96e1c6ff90b63
Reviewed-by: Bill King <bill.king@nokia.com>
Diffstat (limited to 'src/plugins/cpptools/cppcodegen_test.cpp')
-rw-r--r-- | src/plugins/cpptools/cppcodegen_test.cpp | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/src/plugins/cpptools/cppcodegen_test.cpp b/src/plugins/cpptools/cppcodegen_test.cpp new file mode 100644 index 0000000000..3bbdaf1e30 --- /dev/null +++ b/src/plugins/cpptools/cppcodegen_test.cpp @@ -0,0 +1,636 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "cpptoolsplugin.h" + +#include <AST.h> +#include <Control.h> +#include <CppDocument.h> +#include <DiagnosticClient.h> +#include <Scope.h> +#include <TranslationUnit.h> +#include <Literals.h> +#include <Bind.h> +#include <Symbols.h> +#include <cpptools/insertionpointlocator.h> +#include <cpptools/cpprefactoringchanges.h> +#include <cpptools/cpptoolsplugin.h> +#include <extensionsystem/pluginmanager.h> +#include <utils/fileutils.h> + +#include <QtTest> +#include <QtDebug> +#include <QTextDocument> +#include <QDir> + +/*! + Tests for various parts of the code generation. Well, okay, currently it only + tests the InsertionPointLocator. + */ +using namespace CPlusPlus; +using namespace CppTools; +using namespace CppTools::Internal; + +/*! + Should insert at line 3, column 1, with "public:\n" as prefix and without suffix. + */ +void CppToolsPlugin::test_codegen_public_in_empty_class() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "};\n" + "\n"; + + Document::Ptr doc = Document::create("public_in_empty_class"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Public); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("public:\n")); + QVERIFY(loc.suffix().isEmpty()); + QCOMPARE(loc.line(), 3U); + QCOMPARE(loc.column(), 1U); +} + +/*! + Should insert at line 3, column 1, without prefix and without suffix. + */ +void CppToolsPlugin::test_codegen_public_in_nonempty_class() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "public:\n" // line 3 + "};\n" // line 4 + "\n"; + + Document::Ptr doc = Document::create("public_in_nonempty_class"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Public); + QVERIFY(loc.isValid()); + QVERIFY(loc.prefix().isEmpty()); + QVERIFY(loc.suffix().isEmpty()); + QCOMPARE(loc.line(), 4U); + QCOMPARE(loc.column(), 1U); +} + +/*! + Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix. + */ +void CppToolsPlugin::test_codegen_public_before_protected() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "protected:\n" // line 3 + "};\n" + "\n"; + + Document::Ptr doc = Document::create("public_before_protected"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Public); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("public:\n")); + QCOMPARE(loc.suffix(), QLatin1String("\n")); + QCOMPARE(loc.column(), 1U); + QCOMPARE(loc.line(), 3U); +} + +/*! + Should insert at line 4, column 1, with "private:\n" as prefix and without + suffix. + */ +void CppToolsPlugin::test_codegen_private_after_protected() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "protected:\n" // line 3 + "};\n" + "\n"; + + Document::Ptr doc = Document::create("private_after_protected"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Private); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("private:\n")); + QVERIFY(loc.suffix().isEmpty()); + QCOMPARE(loc.column(), 1U); + QCOMPARE(loc.line(), 4U); +} + +/*! + Should insert at line 4, column 1, with "protected:\n" as prefix and without + suffix. + */ +void CppToolsPlugin::test_codegen_protected_in_nonempty_class() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "public:\n" // line 3 + "};\n" // line 4 + "\n"; + + Document::Ptr doc = Document::create("protected_in_nonempty_class"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Protected); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("protected:\n")); + QVERIFY(loc.suffix().isEmpty()); + QCOMPARE(loc.column(), 1U); + QCOMPARE(loc.line(), 4U); +} + +/*! + Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix. + */ +void CppToolsPlugin::test_codegen_protected_between_public_and_private() +{ + const QByteArray src = "\n" + "class Foo\n" // line 1 + "{\n" + "public:\n" // line 3 + "private:\n" // line 4 + "};\n" // line 5 + "\n"; + + Document::Ptr doc = Document::create("protected_betwee_public_and_private"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Class *foo = doc->globalSymbolAt(0)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 1U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::Protected); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("protected:\n")); + QCOMPARE(loc.suffix(), QLatin1String("\n")); + QCOMPARE(loc.column(), 1U); + QCOMPARE(loc.line(), 4U); +} + +/*! + 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. + */ +void CppToolsPlugin::test_codegen_qtdesigner_integration() +{ + const QByteArray src = "/**** Some long (C)opyright notice ****/\n" + "#ifndef MAINWINDOW_H\n" + "#define MAINWINDOW_H\n" + "\n" + "#include <QMainWindow>\n" + "\n" + "namespace Ui {\n" + " class MainWindow;\n" + "}\n" + "\n" + "class MainWindow : public QMainWindow\n" // line 10 + "{\n" + " Q_OBJECT\n" + "\n" + "public:\n" // line 14 + " explicit MainWindow(QWidget *parent = 0);\n" + " ~MainWindow();\n" + "\n" + "private:\n" // line 18 + " Ui::MainWindow *ui;\n" + "};\n" + "\n" + "#endif // MAINWINDOW_H\n"; + + Document::Ptr doc = Document::create("qtdesigner_integration"); + doc->setSource(src); + doc->parse(); + doc->check(); + + QCOMPARE(doc->diagnosticMessages().size(), 0); + QCOMPARE(doc->globalSymbolCount(), 2U); + + Class *foo = doc->globalSymbolAt(1)->asClass(); + QVERIFY(foo); + QCOMPARE(foo->line(), 10U); + QCOMPARE(foo->column(), 7U); + + Snapshot snapshot; + snapshot.insert(doc); + CppRefactoringChanges changes(snapshot); + InsertionPointLocator find(changes); + InsertionLocation loc = find.methodDeclarationInClass( + doc->fileName(), + foo, + InsertionPointLocator::PrivateSlot); + QVERIFY(loc.isValid()); + QCOMPARE(loc.prefix(), QLatin1String("private slots:\n")); + QCOMPARE(loc.suffix(), QLatin1String("\n")); + QCOMPARE(loc.line(), 18U); + QCOMPARE(loc.column(), 1U); +} + +void CppToolsPlugin::test_codegen_definition_empty_class() +{ + 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"; + + Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h")); + Utils::FileSaver srcSaver(src->fileName()); + srcSaver.write(srcText); + srcSaver.finalize(); + src->setSource(srcText); + src->parse(); + src->check(); + QCOMPARE(src->diagnosticMessages().size(), 0); + QCOMPARE(src->globalSymbolCount(), 1U); + + Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp")); + Utils::FileSaver dstSaver(dst->fileName()); + dstSaver.write(dstText); + dstSaver.finalize(); + dst->setSource(dstText); + 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(); + QCOMPARE(loc.fileName(), dst->fileName()); + QCOMPARE(loc.prefix(), QLatin1String("\n\n")); + QCOMPARE(loc.suffix(), QString()); + QCOMPARE(loc.line(), 1U); + QCOMPARE(loc.column(), 7U); +} + +void CppToolsPlugin::test_codegen_definition_first_member() +{ + const QByteArray srcText = "\n" + "class Foo\n" // line 1 + "{\n" + "void foo();\n" // line 3 + "void bar();\n" // line 4 + "};\n" + "\n"; + + 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" + "int y;\n").arg(QDir::tempPath()).toLatin1(); + + Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h")); + Utils::FileSaver srcSaver(src->fileName()); + srcSaver.write(srcText); + srcSaver.finalize(); + src->setSource(srcText); + src->parse(); + src->check(); + QCOMPARE(src->diagnosticMessages().size(), 0); + QCOMPARE(src->globalSymbolCount(), 1U); + + Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp")); + dst->addIncludeFile(src->fileName(), 1); + Utils::FileSaver dstSaver(dst->fileName()); + dstSaver.write(dstText); + dstSaver.finalize(); + dst->setSource(dstText); + 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(); + QCOMPARE(loc.fileName(), dst->fileName()); + QCOMPARE(loc.line(), 4U); + QCOMPARE(loc.column(), 1U); + QCOMPARE(loc.suffix(), QLatin1String("\n\n")); + QCOMPARE(loc.prefix(), QString()); +} + +void CppToolsPlugin::test_codegen_definition_last_member() +{ + const QByteArray srcText = "\n" + "class Foo\n" // line 1 + "{\n" + "void foo();\n" // line 3 + "void bar();\n" // line 4 + "};\n" + "\n"; + + 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" + "int y;\n").arg(QDir::tempPath()).toLatin1(); + + Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h")); + Utils::FileSaver srcSaver(src->fileName()); + srcSaver.write(srcText); + srcSaver.finalize(); + src->setSource(srcText); + src->parse(); + src->check(); + QCOMPARE(src->diagnosticMessages().size(), 0); + QCOMPARE(src->globalSymbolCount(), 1U); + + Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp")); + dst->addIncludeFile(src->fileName(), 1); + Utils::FileSaver dstSaver(dst->fileName()); + dstSaver.write(dstText); + dstSaver.finalize(); + dst->setSource(dstText); + 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(); + QCOMPARE(loc.fileName(), dst->fileName()); + QCOMPARE(loc.line(), 7U); + QCOMPARE(loc.column(), 2U); + QCOMPARE(loc.prefix(), QLatin1String("\n\n")); + QCOMPARE(loc.suffix(), QString()); +} + +void CppToolsPlugin::test_codegen_definition_middle_member() +{ + 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"; + + 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" + "int y;\n").arg(QDir::tempPath()).toLatin1(); + + Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h")); + Utils::FileSaver srcSaver(src->fileName()); + srcSaver.write(srcText); + srcSaver.finalize(); + src->setSource(srcText); + src->parse(); + src->check(); + QCOMPARE(src->diagnosticMessages().size(), 0); + QCOMPARE(src->globalSymbolCount(), 1U); + + Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp")); + dst->addIncludeFile(src->fileName(), 1); + Utils::FileSaver dstSaver(dst->fileName()); + dstSaver.write(dstText); + dstSaver.finalize(); + dst->setSource(dstText); + 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(); + QCOMPARE(loc.fileName(), dst->fileName()); + QCOMPARE(loc.line(), 7U); + QCOMPARE(loc.column(), 2U); + QCOMPARE(loc.prefix(), QLatin1String("\n\n")); + QCOMPARE(loc.suffix(), QString()); +} |