diff options
Diffstat (limited to 'src/plugins/cppeditor/cppquickfix_test.cpp')
-rw-r--r-- | src/plugins/cppeditor/cppquickfix_test.cpp | 9951 |
1 files changed, 0 insertions, 9951 deletions
diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp deleted file mode 100644 index 0a5b71c814..0000000000 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ /dev/null @@ -1,9951 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "cppquickfix_test.h" - -#include "cppcodestylepreferences.h" -#include "cppeditorwidget.h" -#include "cppmodelmanager.h" -#include "cppquickfixassistant.h" -#include "cppquickfixes.h" -#include "cppquickfixsettings.h" -#include "cppsourceprocessertesthelper.h" -#include "cpptoolssettings.h" - -#include <utils/fileutils.h> - -#include <QDebug> -#include <QDir> -#include <QtTest> - -/*! - Tests for quick-fixes. - */ -using namespace Core; -using namespace CPlusPlus; -using namespace TextEditor; -using namespace Utils; - -using CppEditor::Tests::TemporaryDir; -using CppEditor::Tests::Internal::TestIncludePaths; - -typedef QByteArray _; - -namespace CppEditor::Internal::Tests { -typedef QList<TestDocumentPtr> QuickFixTestDocuments; -} -Q_DECLARE_METATYPE(CppEditor::Internal::Tests::QuickFixTestDocuments) - -namespace CppEditor { -namespace Internal { -namespace Tests { - -/// Tests the offered operations provided by a given CppQuickFixFactory -class QuickFixOfferedOperationsTest : public BaseQuickFixTestCase -{ -public: - QuickFixOfferedOperationsTest(const QList<TestDocumentPtr> &testDocuments, - CppQuickFixFactory *factory, - const ProjectExplorer::HeaderPaths &headerPaths - = ProjectExplorer::HeaderPaths(), - const QStringList &expectedOperations = QStringList()); -}; - -QList<TestDocumentPtr> singleDocument(const QByteArray &original, - const QByteArray &expected) -{ - return {CppTestDocument::create("file.cpp", original, expected)}; -} - -BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments, - const ProjectExplorer::HeaderPaths &headerPaths, - const QByteArray &clangFormatSettings) - : m_testDocuments(testDocuments) - , m_cppCodeStylePreferences(0) - , m_restoreHeaderPaths(false) -{ - QVERIFY(succeededSoFar()); - m_succeededSoFar = false; - - // Check if there is exactly one cursor marker - unsigned cursorMarkersCount = 0; - for (const TestDocumentPtr &document : std::as_const(m_testDocuments)) { - if (document->hasCursorMarker()) - ++cursorMarkersCount; - } - QVERIFY2(cursorMarkersCount == 1, "Exactly one cursor marker is allowed."); - - // Write documents to disk - m_temporaryDirectory.reset(new TemporaryDir); - QVERIFY(m_temporaryDirectory->isValid()); - for (const TestDocumentPtr &document : std::as_const(m_testDocuments)) { - if (QFileInfo(document->m_fileName).isRelative()) - document->setBaseDirectory(m_temporaryDirectory->path()); - document->writeToDisk(); - } - - // Create .clang-format file - if (!clangFormatSettings.isEmpty()) - m_temporaryDirectory->createFile(".clang-format", clangFormatSettings); - - // Set appropriate include paths - if (!headerPaths.isEmpty()) { - m_restoreHeaderPaths = true; - m_headerPathsToRestore = CppModelManager::headerPaths(); - CppModelManager::setHeaderPaths(headerPaths); - } - - // Update Code Model - QSet<FilePath> filePaths; - for (const TestDocumentPtr &document : std::as_const(m_testDocuments)) - filePaths << document->filePath(); - QVERIFY(parseFiles(filePaths)); - - // Open Files - for (const TestDocumentPtr &document : std::as_const(m_testDocuments)) { - QVERIFY(openCppEditor(document->filePath(), &document->m_editor, - &document->m_editorWidget)); - closeEditorAtEndOfTestCase(document->m_editor); - - // Set cursor position - if (document->hasCursorMarker()) { - if (document->hasAnchorMarker()) { - document->m_editor->setCursorPosition(document->m_anchorPosition); - document->m_editor->select(document->m_cursorPosition); - } else { - document->m_editor->setCursorPosition(document->m_cursorPosition); - } - } else { - document->m_editor->setCursorPosition(0); - } - - // Rehighlight - waitForRehighlightedSemanticDocument(document->m_editorWidget); - } - - // Enforce the default cpp code style, so we are independent of config file settings. - // This is needed by e.g. the GenerateGetterSetter quick fix. - m_cppCodeStylePreferences = CppToolsSettings::cppCodeStyle(); - QVERIFY(m_cppCodeStylePreferences); - m_cppCodeStylePreferencesOriginalDelegateId = m_cppCodeStylePreferences->currentDelegateId(); - m_cppCodeStylePreferences->setCurrentDelegate("qt"); - - // Find the document having the cursor marker - for (const TestDocumentPtr &document : std::as_const(m_testDocuments)) { - if (document->hasCursorMarker()){ - m_documentWithMarker = document; - break; - } - } - - QVERIFY(m_documentWithMarker); - m_succeededSoFar = true; -} - -BaseQuickFixTestCase::~BaseQuickFixTestCase() -{ - // Restore default cpp code style - if (m_cppCodeStylePreferences) - m_cppCodeStylePreferences->setCurrentDelegate(m_cppCodeStylePreferencesOriginalDelegateId); - - // Restore include paths - if (m_restoreHeaderPaths) - CppModelManager::setHeaderPaths(m_headerPathsToRestore); - - // Remove created files from file system - for (const TestDocumentPtr &testDocument : std::as_const(m_testDocuments)) - QVERIFY(testDocument->filePath().removeFile()); -} - -/// Leading whitespace is not removed, so we can check if the indetation ranges -/// have been set correctly by the quick-fix. -static QString &removeTrailingWhitespace(QString &input) -{ - const QStringList lines = input.split(QLatin1Char('\n')); - input.resize(0); - for (int i = 0, total = lines.size(); i < total; ++i) { - QString line = lines.at(i); - while (line.length() > 0) { - QChar lastChar = line[line.length() - 1]; - if (lastChar == QLatin1Char(' ') || lastChar == QLatin1Char('\t')) - line.chop(1); - else - break; - } - input.append(line); - - const bool isLastLine = i == lines.size() - 1; - if (!isLastLine) - input.append(QLatin1Char('\n')); - } - return input; -} - -QuickFixOperationTest::QuickFixOperationTest(const QList<TestDocumentPtr> &testDocuments, - CppQuickFixFactory *factory, - const ProjectExplorer::HeaderPaths &headerPaths, - int operationIndex, - const QByteArray &expectedFailMessage, - const QByteArray &clangFormatSettings) - : BaseQuickFixTestCase(testDocuments, headerPaths, clangFormatSettings) -{ - if (factory->clangdReplacement() && CppModelManager::isClangCodeModelActive()) - return; - - QVERIFY(succeededSoFar()); - - // Perform operation if there is one - CppQuickFixInterface quickFixInterface(m_documentWithMarker->m_editorWidget, ExplicitlyInvoked); - QuickFixOperations operations; - factory->match(quickFixInterface, operations); - if (operations.isEmpty()) { - QEXPECT_FAIL("CompleteSwitchCaseStatement_QTCREATORBUG-25998", "FIXME", Abort); - QVERIFY(testDocuments.first()->m_expectedSource.isEmpty()); - return; - } - - QVERIFY(operationIndex < operations.size()); - const QuickFixOperation::Ptr operation = operations.at(operationIndex); - operation->perform(); - - // Compare all files - for (const TestDocumentPtr &testDocument : std::as_const(m_testDocuments)) { - // Check - QString result = testDocument->m_editorWidget->document()->toPlainText(); - removeTrailingWhitespace(result); - QEXPECT_FAIL("escape string literal: raw string literal", "FIXME", Continue); - QEXPECT_FAIL("escape string literal: unescape adjacent literals", "FIXME", Continue); - if (!expectedFailMessage.isEmpty()) - QEXPECT_FAIL("", expectedFailMessage.data(), Continue); - else if (result != testDocument->m_expectedSource) { - qDebug() << "---" << testDocument->m_expectedSource; - qDebug() << "+++" << result; - } - QCOMPARE(result, testDocument->m_expectedSource); - - // Undo the change - for (int i = 0; i < 100; ++i) - testDocument->m_editorWidget->undo(); - result = testDocument->m_editorWidget->document()->toPlainText(); - QCOMPARE(result, testDocument->m_source); - } -} - -void QuickFixOperationTest::run(const QList<TestDocumentPtr> &testDocuments, - CppQuickFixFactory *factory, - const QString &headerPath, - int operationIndex) -{ - ProjectExplorer::HeaderPaths headerPaths; - headerPaths.push_back(ProjectExplorer::HeaderPath::makeUser(headerPath)); - QuickFixOperationTest(testDocuments, factory, headerPaths, operationIndex); -} - -QuickFixOfferedOperationsTest::QuickFixOfferedOperationsTest( - const QList<TestDocumentPtr> &testDocuments, - CppQuickFixFactory *factory, - const ProjectExplorer::HeaderPaths &headerPaths, - const QStringList &expectedOperations) - : BaseQuickFixTestCase(testDocuments, headerPaths) -{ - // Get operations - CppQuickFixInterface quickFixInterface(m_documentWithMarker->m_editorWidget, ExplicitlyInvoked); - QuickFixOperations actualOperations; - factory->match(quickFixInterface, actualOperations); - - // Convert to QStringList - QStringList actualOperationsAsStringList; - for (const QuickFixOperation::Ptr &operation : std::as_const(actualOperations)) - actualOperationsAsStringList << operation->description(); - - QCOMPARE(actualOperationsAsStringList, expectedOperations); -} - -/// Delegates directly to AddIncludeForUndefinedIdentifierOp for easier testing. -class AddIncludeForUndefinedIdentifierTestFactory : public CppQuickFixFactory -{ -public: - AddIncludeForUndefinedIdentifierTestFactory(const QString &include) - : m_include(include) {} - - void doMatch(const CppQuickFixInterface &cppQuickFixInterface, QuickFixOperations &result) override - { - result << new AddIncludeForUndefinedIdentifierOp(cppQuickFixInterface, 0, m_include); - } - -private: - const QString m_include; -}; - -class AddForwardDeclForUndefinedIdentifierTestFactory : public CppQuickFixFactory -{ -public: - AddForwardDeclForUndefinedIdentifierTestFactory(const QString &className, int symbolPos) - : m_className(className), m_symbolPos(symbolPos) {} - - void doMatch(const CppQuickFixInterface &cppQuickFixInterface, QuickFixOperations &result) override - { - result << new AddForwardDeclForUndefinedIdentifierOp(cppQuickFixInterface, 0, - m_className, m_symbolPos); - } - -private: - const QString m_className; - const int m_symbolPos; -}; - -} // namespace Tests -} // namespace Internal - -typedef QSharedPointer<CppQuickFixFactory> CppQuickFixFactoryPtr; - -} // namespace CppEditor - -namespace CppEditor::Internal::Tests { - -class QuickFixSettings -{ - const CppQuickFixSettings original = *CppQuickFixSettings::instance(); - -public: - CppQuickFixSettings *operator->() { return CppQuickFixSettings::instance(); } - ~QuickFixSettings() { *CppQuickFixSettings::instance() = original; } -}; - -void QuickfixTest::testGeneric_data() -{ - 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) << _( - "enum EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "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" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_basic1_enum class") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " switch (t) {\n" - " case EnumType::V1:\n" - " break;\n" - " case EnumType::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Same as above with the cursor somewhere in the body. - QTest::newRow("CompleteSwitchCaseStatement_basic1_enum class, cursor in the body") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " switch (t) {\n" - " @}\n" - "}\n" - ) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " switch (t) {\n" - " case EnumType::V1:\n" - " break;\n" - " case EnumType::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: All enum values are added as case statements for a blank switch when - // the variable is declared alongside the enum definition. - QTest::newRow("CompleteSwitchCaseStatement_basic1_enum_with_declaration") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum EnumType { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "enum EnumType { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " switch (t) {\n" - " case V1:\n" - " break;\n" - " case V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_basic1_enum_with_declaration_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class EnumType { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "enum class EnumType { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " switch (t) {\n" - " case EnumType::V1:\n" - " break;\n" - " case EnumType::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: All enum values are added as case statements for a blank switch - // for anonymous enums. - QTest::newRow("CompleteSwitchCaseStatement_basic1_anonymous_enum") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "enum { V1, V2 } t;\n" - "\n" - "void f()\n" - "{\n" - " switch (t) {\n" - " case V1:\n" - " break;\n" - " case V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: All enum values are added as case statements for a blank switch with a default case. - QTest::newRow("CompleteSwitchCaseStatement_basic2") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " @switch (t) {\n" - " default:\n" - " break;\n" - " }\n" - "}\n" - ) << _( - "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" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_basic2_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " @switch (t) {\n" - " default:\n" - " break;\n" - " }\n" - "}\n" - ) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " switch (t) {\n" - " case EnumType::V1:\n" - " break;\n" - " case EnumType::V2:\n" - " break;\n" - " default:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Enum type in class is found. - QTest::newRow("CompleteSwitchCaseStatement_enumTypeInClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "struct C { enum EnumType { V1, V2 }; };\n" - "\n" - "void f(C::EnumType t) {\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "struct C { enum EnumType { V1, V2 }; };\n" - "\n" - "void f(C::EnumType t) {\n" - " switch (t) {\n" - " case C::V1:\n" - " break;\n" - " case C::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_enumClassInClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "struct C { enum class EnumType { V1, V2 }; };\n" - "\n" - "void f(C::EnumType t) {\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "struct C { enum class EnumType { V1, V2 }; };\n" - "\n" - "void f(C::EnumType t) {\n" - " switch (t) {\n" - " case C::EnumType::V1:\n" - " break;\n" - " case C::EnumType::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Enum type in namespace is found. - QTest::newRow("CompleteSwitchCaseStatement_enumTypeInNamespace") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "namespace N { enum EnumType { V1, V2 }; };\n" - "\n" - "void f(N::EnumType t) {\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "namespace N { enum EnumType { V1, V2 }; };\n" - "\n" - "void f(N::EnumType t) {\n" - " switch (t) {\n" - " case N::V1:\n" - " break;\n" - " case N::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_enumClassInNamespace") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "namespace N { enum class EnumType { V1, V2 }; };\n" - "\n" - "void f(N::EnumType t) {\n" - " @switch (t) {\n" - " }\n" - "}\n" - ) << _( - "namespace N { enum class EnumType { V1, V2 }; };\n" - "\n" - "void f(N::EnumType t) {\n" - " switch (t) {\n" - " case N::EnumType::V1:\n" - " break;\n" - " case N::EnumType::V2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: The missing enum value is added. - QTest::newRow("CompleteSwitchCaseStatement_oneValueMissing") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "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" - "}\n" - ) << _( - "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" - ); - - // Checks: Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_oneValueMissing_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " @switch (t) {\n" - " case EnumType::V2:\n" - " break;\n" - " default:\n" - " break;\n" - " }\n" - "}\n" - ) << _( - "enum class EnumType { V1, V2 };\n" - "\n" - "void f()\n" - "{\n" - " EnumType t;\n" - " switch (t) {\n" - " case EnumType::V1:\n" - " break;\n" - " case EnumType::V2:\n" - " break;\n" - " default:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Find the correct enum type despite there being a declaration with the same name. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_1") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum test { TEST_1, TEST_2 };\n" - "\n" - "void f() {\n" - " enum test test;\n" - " @switch (test) {\n" - " }\n" - "}\n" - ) << _( - "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" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_1_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class test { TEST_1, TEST_2 };\n" - "\n" - "void f() {\n" - " enum test test;\n" - " @switch (test) {\n" - " }\n" - "}\n" - ) << _( - "enum class test { TEST_1, TEST_2 };\n" - "\n" - "void f() {\n" - " enum test test;\n" - " switch (test) {\n" - " case test::TEST_1:\n" - " break;\n" - " case test::TEST_2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Find the correct enum type despite there being a declaration with the same name. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_2") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "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" - ) << _( - "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" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG10366_2_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class test1 { Wrong11, Wrong12 };\n" - "enum class test { Right1, Right2 };\n" - "enum class test2 { Wrong21, Wrong22 };\n" - "\n" - "int main() {\n" - " enum test test;\n" - " @switch (test) {\n" - " }\n" - "}\n" - ) << _( - "enum class test1 { Wrong11, Wrong12 };\n" - "enum class test { Right1, Right2 };\n" - "enum class test2 { Wrong21, Wrong22 };\n" - "\n" - "int main() {\n" - " enum test test;\n" - " switch (test) {\n" - " case test::Right1:\n" - " break;\n" - " case test::Right2:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Do not crash on incomplete case statetement. - QTest::newRow("CompleteSwitchCaseStatement_doNotCrashOnIncompleteCase") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum E {};\n" - "void f(E o)\n" - "{\n" - " @switch (o)\n" - " {\n" - " case\n" - " }\n" - "}\n" - ) << _( - "" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_doNotCrashOnIncompleteCase_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class E {};\n" - "void f(E o)\n" - "{\n" - " @switch (o)\n" - " {\n" - " case\n" - " }\n" - "}\n" - ) << _( - "" - ); - - // Checks: complete switch statement where enum is goes via a template type parameter - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG-24752") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum E {EA, EB};\n" - "template<typename T> struct S {\n" - " static T theType() { return T(); }\n" - "};\n" - "int main() {\n" - " @switch (S<E>::theType()) {\n" - " }\n" - "}\n" - ) << _( - "enum E {EA, EB};\n" - "template<typename T> struct S {\n" - " static T theType() { return T(); }\n" - "};\n" - "int main() {\n" - " switch (S<E>::theType()) {\n" - " case EA:\n" - " break;\n" - " case EB:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Same as above for enum class. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG-24752_enumClass") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "enum class E {A, B};\n" - "template<typename T> struct S {\n" - " static T theType() { return T(); }\n" - "};\n" - "int main() {\n" - " @switch (S<E>::theType()) {\n" - " }\n" - "}\n" - ) << _( - "enum class E {A, B};\n" - "template<typename T> struct S {\n" - " static T theType() { return T(); }\n" - "};\n" - "int main() {\n" - " switch (S<E>::theType()) {\n" - " case E::A:\n" - " break;\n" - " case E::B:\n" - " break;\n" - " }\n" - "}\n" - ); - - // Checks: Complete switch statement where enum is return type of a template function - // which is outside the scope of the return value. - // TODO: Type minimization. - QTest::newRow("CompleteSwitchCaseStatement_QTCREATORBUG-25998") - << CppQuickFixFactoryPtr(new CompleteSwitchCaseStatement) << _( - "template <typename T> T enumCast(int value) { return static_cast<T>(value); }\n" - "class Test {\n" - " enum class E { V1, V2 };" - " void func(int i) {\n" - " @switch (enumCast<E>(i)) {\n" - " }\n" - " }\n" - "};\n" - ) << _( - "template <typename T> T enumCast(int value) { return static_cast<T>(value); }\n" - "class Test {\n" - " enum class E { V1, V2 };" - " void func(int i) {\n" - " switch (enumCast<E>(i)) {\n" - " case Test::E::V1:\n" - " break;\n" - " case Test::E::V2:\n" - " break;\n" - " }\n" - " }\n" - "};\n" - ); - - // Checks: No special treatment for reference to non const. - - // Check: Quick fix is not triggered on a member function. - QTest::newRow("GenerateGetterSetter_notTriggeringOnMemberFunction") - << CppQuickFixFactoryPtr(new GenerateGetterSetter) - << _("class Something { void @f(); };\n") << _(); - - // Check: Quick fix is not triggered on an member array; - QTest::newRow("GenerateGetterSetter_notTriggeringOnMemberArray") - << CppQuickFixFactoryPtr(new GenerateGetterSetter) - << _("class Something { void @a[10]; };\n") << _(); - - 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" - ); - - 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" - ); - - 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" - ); - - 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" - ); - - 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" - ); - - // Check: Just a basic test since the main functionality is tested in - // cpppointerdeclarationformatter_test.cpp - QTest::newRow("ReformatPointerDeclaration") - << CppQuickFixFactoryPtr(new ReformatPointerDeclaration) - << _("char@*s;") - << _("char *s;"); - - // Check from source file: If there is no header file, insert the definition after the class. - QByteArray original = - "struct Foo\n" - "{\n" - " Foo();@\n" - "};\n"; - - QTest::newRow("InsertDefFromDecl_basic") - << CppQuickFixFactoryPtr(new InsertDefFromDecl) << original - << original + _( - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n" - ); - - QTest::newRow("InsertDefFromDecl_freeFunction") - << CppQuickFixFactoryPtr(new InsertDefFromDecl) - << _("void free()@;\n") - << _( - "void free()\n" - "{\n\n" - "}\n" - ); - - // Check not triggering when it is a statement - QTest::newRow("InsertDefFromDecl_notTriggeringStatement") - << CppQuickFixFactoryPtr(new InsertDefFromDecl) << _( - "class Foo {\n" - "public:\n" - " Foo() {}\n" - "};\n" - "void freeFunc() {\n" - " Foo @f();" - "}\n" - ) << _(); - - // Check: Add local variable for a free function. - QTest::newRow("AssignToLocalVariable_freeFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "int foo() {return 1;}\n" - "void bar() {fo@o();}\n" - ) << _( - "int foo() {return 1;}\n" - "void bar() {auto localFoo = foo();}\n" - ); - - // Check: Add local variable for a member function. - QTest::newRow("AssignToLocalVariable_memberFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: int* fooFunc();}\n" - "void bar() {\n" - " Foo *f = new Foo;\n" - " @f->fooFunc();\n" - "}\n" - ) << _( - "class Foo {public: int* fooFunc();}\n" - "void bar() {\n" - " Foo *f = new Foo;\n" - " auto localFooFunc = f->fooFunc();\n" - "}\n" - ); - - // Check: Add local variable for a member function, cursor in the middle (QTCREATORBUG-10355) - QTest::newRow("AssignToLocalVariable_memberFunction2ndGrade1") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "struct Foo {int* func();};\n" - "struct Baz {Foo* foo();};\n" - "void bar() {\n" - " Baz *b = new Baz;\n" - " b->foo@()->func();\n" - "}" - ) << _( - "struct Foo {int* func();};\n" - "struct Baz {Foo* foo();};\n" - "void bar() {\n" - " Baz *b = new Baz;\n" - " auto localFunc = b->foo()->func();\n" - "}" - ); - - // Check: Add local variable for a member function, cursor on function call (QTCREATORBUG-10355) - QTest::newRow("AssignToLocalVariable_memberFunction2ndGrade2") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "struct Foo {int* func();};\n" - "struct Baz {Foo* foo();};\n" - "void bar() {\n" - " Baz *b = new Baz;\n" - " b->foo()->f@unc();\n" - "}" - ) << _( - "struct Foo {int* func();};\n" - "struct Baz {Foo* foo();};\n" - "void bar() {\n" - " Baz *b = new Baz;\n" - " auto localFunc = b->foo()->func();\n" - "}" - ); - - // Check: Add local variable for a static member function. - QTest::newRow("AssignToLocalVariable_staticMemberFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: static int* fooFunc();}\n" - "void bar() {\n" - " Foo::fooF@unc();\n" - "}" - ) << _( - "class Foo {public: static int* fooFunc();}\n" - "void bar() {\n" - " auto localFooFunc = Foo::fooFunc();\n" - "}" - ); - - // Check: Add local variable for a new Expression. - QTest::newRow("AssignToLocalVariable_newExpression") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {}\n" - "void bar() {\n" - " new Fo@o;\n" - "}" - ) << _( - "class Foo {}\n" - "void bar() {\n" - " auto localFoo = new Foo;\n" - "}" - ); - - // Check: No trigger for function inside member initialization list. - QTest::newRow("AssignToLocalVariable_noInitializationList") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo\n" - "{\n" - " public: Foo : m_i(fooF@unc()) {}\n" - " int fooFunc() {return 2;}\n" - " int m_i;\n" - "};\n" - ) << _(); - - // Check: No trigger for void functions. - QTest::newRow("AssignToLocalVariable_noVoidFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "void foo() {}\n" - "void bar() {fo@o();}" - ) << _(); - - // Check: No trigger for void member functions. - QTest::newRow("AssignToLocalVariable_noVoidMemberFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: void fooFunc();}\n" - "void bar() {\n" - " Foo *f = new Foo;\n" - " @f->fooFunc();\n" - "}" - ) << _(); - - // Check: No trigger for void static member functions. - QTest::newRow("AssignToLocalVariable_noVoidStaticMemberFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: static void fooFunc();}\n" - "void bar() {\n" - " Foo::fo@oFunc();\n" - "}" - ) << _(); - - // Check: No trigger for functions in expressions. - QTest::newRow("AssignToLocalVariable_noFunctionInExpression") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "int foo(int a) {return a;}\n" - "int bar() {return 1;}" - "void baz() {foo(@bar() + bar());}" - ) << _(); - - // Check: No trigger for functions in functions. (QTCREATORBUG-9510) - QTest::newRow("AssignToLocalVariable_noFunctionInFunction") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "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" - "}\n" - ) << _(); - - // Check: No trigger for functions in return statements (classes). - QTest::newRow("AssignToLocalVariable_noReturnClass1") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: static void fooFunc();}\n" - "Foo* bar() {\n" - " return new Fo@o;\n" - "}" - ) << _(); - - // Check: No trigger for functions in return statements (classes). (QTCREATORBUG-9525) - QTest::newRow("AssignToLocalVariable_noReturnClass2") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: int fooFunc();}\n" - "int bar() {\n" - " return (new Fo@o)->fooFunc();\n" - "}" - ) << _(); - - // Check: No trigger for functions in return statements (functions). - QTest::newRow("AssignToLocalVariable_noReturnFunc1") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "class Foo {public: int fooFunc();}\n" - "int bar() {\n" - " return Foo::fooFu@nc();\n" - "}" - ) << _(); - - // Check: No trigger for functions in return statements (functions). (QTCREATORBUG-9525) - QTest::newRow("AssignToLocalVariable_noReturnFunc2") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "int bar() {\n" - " return list.firs@t().foo;\n" - "}\n" - ) << _(); - - // Check: No trigger for functions which does not match in signature. - QTest::newRow("AssignToLocalVariable_noSignatureMatch") - << CppQuickFixFactoryPtr(new AssignToLocalVariable) << _( - "int someFunc(int);\n" - "\n" - "void f()\n" - "{\n" - " some@Func();\n" - "}" - ) << _(); - - QTest::newRow("ExtractLiteralAsParameter_freeFunction") - << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _( - "void foo(const char *a, long b = 1)\n" - "{return 1@56 + 123 + 156;}\n" - ) << _( - "void foo(const char *a, long b = 1, int newParameter = 156)\n" - "{return newParameter + 123 + newParameter;}\n" - ); - - QTest::newRow("ExtractLiteralAsParameter_memberFunction") - << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _( - "class Narf {\n" - "public:\n" - " int zort();\n" - "};\n\n" - "int Narf::zort()\n" - "{ return 15@5 + 1; }\n" - ) << _( - "class Narf {\n" - "public:\n" - " int zort(int newParameter = 155);\n" - "};\n\n" - "int Narf::zort(int newParameter)\n" - "{ return newParameter + 1; }\n" - ); - - QTest::newRow("ExtractLiteralAsParameter_memberFunctionInline") - << CppQuickFixFactoryPtr(new ExtractLiteralAsParameter) << _( - "class Narf {\n" - "public:\n" - " int zort()\n" - " { return 15@5 + 1; }\n" - "};\n" - ) << _( - "class Narf {\n" - "public:\n" - " int zort(int newParameter = 155)\n" - " { return newParameter + 1; }\n" - "};\n" - ); - - // Check: optimize postcrement - QTest::newRow("OptimizeForLoop_postcrement") - << CppQuickFixFactoryPtr(new OptimizeForLoop) - << _("void foo() {f@or (int i = 0; i < 3; i++) {}}\n") - << _("void foo() {for (int i = 0; i < 3; ++i) {}}\n"); - - // Check: optimize condition - QTest::newRow("OptimizeForLoop_condition") - << CppQuickFixFactoryPtr(new OptimizeForLoop) - << _("void foo() {f@or (int i = 0; i < 3 + 5; ++i) {}}\n") - << _("void foo() {for (int i = 0, total = 3 + 5; i < total; ++i) {}}\n"); - - // Check: optimize fliped condition - QTest::newRow("OptimizeForLoop_flipedCondition") - << CppQuickFixFactoryPtr(new OptimizeForLoop) - << _("void foo() {f@or (int i = 0; 3 + 5 > i; ++i) {}}\n") - << _("void foo() {for (int i = 0, total = 3 + 5; total > i; ++i) {}}\n"); - - // 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") - << _("void foo() {for (int i = 0, total = 0, totalX = 3 + 5; i < totalX; ++i) {}}\n"); - - // Check: optimize postcrement and condition - QTest::newRow("OptimizeForLoop_optimizeBoth") - << CppQuickFixFactoryPtr(new OptimizeForLoop) - << _("void foo() {f@or (int i = 0; i < 3 + 5; i++) {}}\n") - << _("void foo() {for (int i = 0, total = 3 + 5; i < total; ++i) {}}\n"); - - // Check: empty initializier - QTest::newRow("OptimizeForLoop_emptyInitializer") - << CppQuickFixFactoryPtr(new OptimizeForLoop) - << _("int i; void foo() {f@or (; i < 3 + 5; ++i) {}}\n") - << _("int i; void foo() {for (int total = 3 + 5; i < total; ++i) {}}\n"); - - // 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") - << _(); - - // 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") - << _(); - - // Escape String Literal as UTF-8 (no-trigger) - QTest::newRow("EscapeStringLiteral_notrigger") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *notrigger = \"@abcdef \\a\\n\\\\\";\n") - << _(); - - // Escape String Literal as UTF-8 - QTest::newRow("EscapeStringLiteral") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *utf8 = \"@\xe3\x81\x82\xe3\x81\x84\";\n") - << _("const char *utf8 = \"\\xe3\\x81\\x82\\xe3\\x81\\x84\";\n"); - - // Unescape String Literal as UTF-8 (from hexdecimal escape sequences) - QTest::newRow("UnescapeStringLiteral_hex") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *hex_escaped = \"@\\xe3\\x81\\x82\\xe3\\x81\\x84\";\n") - << _("const char *hex_escaped = \"\xe3\x81\x82\xe3\x81\x84\";\n"); - - // Unescape String Literal as UTF-8 (from octal escape sequences) - QTest::newRow("UnescapeStringLiteral_oct") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *oct_escaped = \"@\\343\\201\\202\\343\\201\\204\";\n") - << _("const char *oct_escaped = \"\xe3\x81\x82\xe3\x81\x84\";\n"); - - // Unescape String Literal as UTF-8 (triggered but no change) - QTest::newRow("UnescapeStringLiteral_noconv") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *escaped_ascii = \"@\\x1b\";\n") - << _("const char *escaped_ascii = \"\\x1b\";\n"); - - // Unescape String Literal as UTF-8 (no conversion because of invalid utf-8) - QTest::newRow("UnescapeStringLiteral_invalid") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _("const char *escaped = \"@\\xe3\\x81\";\n") - << _("const char *escaped = \"\\xe3\\x81\";\n"); - - QTest::newRow("ConvertFromPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString *@str;\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n") - << _("void foo() {\n" - " QString str;\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n"); - - QTest::newRow("ConvertToPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString @str;\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n") - << _("void foo() {\n" - " QString *str = new QString;\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n"); - - QTest::newRow("ConvertReferenceToPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString narf;" - " QString &@str = narf;\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n") - << _("void foo() {\n" - " QString narf;" - " QString *str = &narf;\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n"); - - QTest::newRow("ConvertFromPointer_withInitializer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString *@str = new QString(QLatin1String(\"schnurz\"));\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - "}\n") - << _("void foo() {\n" - " QString str(QLatin1String(\"schnurz\"));\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - "}\n"); - - QTest::newRow("ConvertFromPointer_withBareInitializer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString *@str = new QString;\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - "}\n") - << _("void foo() {\n" - " QString str;\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - "}\n"); - - QTest::newRow("ConvertFromPointer_withEmptyInitializer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString *@str = new QString();\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - "}\n") - << _("void foo() {\n" - " QString str;\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - "}\n"); - - QTest::newRow("ConvertFromPointer_structWithPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("struct Bar{ QString *str; };\n" - "void foo() {\n" - " Bar *@bar = new Bar;\n" - " bar->str = new QString;\n" - " delete bar->str;\n" - " delete bar;\n" - "}\n") - << _("struct Bar{ QString *str; };\n" - "void foo() {\n" - " Bar bar;\n" - " bar.str = new QString;\n" - " delete bar.str;\n" - " // delete bar;\n" - "}\n"); - - QTest::newRow("ConvertToPointer_withInitializer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString @str = QLatin1String(\"narf\");\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - "}\n") - << _("void foo() {\n" - " QString *str = new QString(QLatin1String(\"narf\"));\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - "}\n"); - - QTest::newRow("ConvertToPointer_withParenInitializer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString @str(QLatin1String(\"narf\"));\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - "}\n") - << _("void foo() {\n" - " QString *str = new QString(QLatin1String(\"narf\"));\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - "}\n"); - - QTest::newRow("ConvertToPointer_noTriggerRValueRefs") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo(Narf &&@narf) {}\n") - << _(); - - QTest::newRow("ConvertToPointer_noTriggerGlobal") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("int @global;\n") - << _(); - - QTest::newRow("ConvertToPointer_noTriggerClassMember") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("struct C { int @member; };\n") - << _(); - - QTest::newRow("ConvertToPointer_noTriggerClassMember2") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void f() { struct C { int @member; }; }\n") - << _(); - - QTest::newRow("ConvertToPointer_functionOfFunctionLocalClass") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void f() {\n" - " struct C {\n" - " void g() { int @member; }\n" - " };\n" - "}\n") - << _("void f() {\n" - " struct C {\n" - " void g() { int *member; }\n" - " };\n" - "}\n"); - - QTest::newRow("ConvertToPointer_redeclaredVariable_block") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " QString @str;\n" - " str.clear();\n" - " {\n" - " QString str;\n" - " str.clear();\n" - " }\n" - " f1(str);\n" - "}\n") - << _("void foo() {\n" - " QString *str = new QString;\n" - " str->clear();\n" - " {\n" - " QString str;\n" - " str.clear();\n" - " }\n" - " f1(*str);\n" - "}\n"); - - QTest::newRow("ConvertAutoFromPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " auto @str = new QString(QLatin1String(\"foo\"));\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n") - << _("void foo() {\n" - " auto str = QString(QLatin1String(\"foo\"));\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n"); - - QTest::newRow("ConvertAutoFromPointer2") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " auto *@str = new QString;\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n") - << _("void foo() {\n" - " auto str = QString();\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n"); - - QTest::newRow("ConvertAutoToPointer") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("void foo() {\n" - " auto @str = QString(QLatin1String(\"foo\"));\n" - " if (!str.isEmpty())\n" - " str.clear();\n" - " f1(str);\n" - " f2(&str);\n" - "}\n") - << _("void foo() {\n" - " auto @str = new QString(QLatin1String(\"foo\"));\n" - " if (!str->isEmpty())\n" - " str->clear();\n" - " f1(*str);\n" - " f2(str);\n" - "}\n"); - - QTest::newRow("ConvertToPointerWithMacro") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _("#define BAR bar\n" - "void func()\n" - "{\n" - " int @foo = 42;\n" - " int bar;\n" - " BAR = foo;\n" - "}\n") - << _("#define BAR bar\n" - "void func()\n" - "{\n" - " int *foo = 42;\n" - " int bar;\n" - " BAR = *foo;\n" - "}\n"); - - QString testObjAndFunc = "struct Object\n" - "{\n" - " Object(%1){}\n" - "};\n" - "void func()\n" - "{\n" - " %2\n" - "}\n"; - - QTest::newRow("ConvertToStack1_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("int").arg("Object *@obj = new Object(0);").toUtf8()) - << _(testObjAndFunc.arg("int").arg("Object obj(0);").toUtf8()); - - QTest::newRow("ConvertToStack2_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("int").arg("Object *@obj = new Object{0};").toUtf8()) - << _(testObjAndFunc.arg("int").arg("Object obj{0};").toUtf8()); - - QTest::newRow("ConvertToPointer1_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("").arg("Object @obj;").toUtf8()) - << _(testObjAndFunc.arg("").arg("Object *obj = new Object;").toUtf8()); - - QTest::newRow("ConvertToPointer2_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("").arg("Object @obj();").toUtf8()) - << _(testObjAndFunc.arg("").arg("Object *obj = new Object();").toUtf8()); - - QTest::newRow("ConvertToPointer3_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("").arg("Object @obj{};").toUtf8()) - << _(testObjAndFunc.arg("").arg("Object *obj = new Object{};").toUtf8()); - - QTest::newRow("ConvertToPointer4_QTCREATORBUG23181") - << CppQuickFixFactoryPtr(new ConvertFromAndToPointer) - << _(testObjAndFunc.arg("int").arg("Object @obj(0);").toUtf8()) - << _(testObjAndFunc.arg("int").arg("Object *obj = new Object(0);").toUtf8()); - - QTest::newRow("InsertQtPropertyMembers_noTriggerInvalidCode") - << CppQuickFixFactoryPtr(new InsertQtPropertyMembers) - << _("class C { @Q_PROPERTY(typeid foo READ foo) };\n") - << _(); - - QTest::newRow("convert to camel case: normal") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @lower_case_function();\n") - << _("void lowerCaseFunction();\n"); - QTest::newRow("convert to camel case: already camel case") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @camelCaseFunction();\n") - << _(); - QTest::newRow("convert to camel case: no underscores (lower case)") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @lowercasefunction();\n") - << _(); - QTest::newRow("convert to camel case: no underscores (upper case)") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @UPPERCASEFUNCTION();\n") - << _(); - QTest::newRow("convert to camel case: non-applicable underscore") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @m_a_member;\n") - << _("void m_aMember;\n"); - QTest::newRow("convert to camel case: upper case") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @UPPER_CASE_FUNCTION();\n") - << _("void upperCaseFunction();\n"); - QTest::newRow("convert to camel case: partially camel case already") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void mixed@_andCamelCase();\n") - << _("void mixedAndCamelCase();\n"); - QTest::newRow("convert to camel case: wild mix") - << CppQuickFixFactoryPtr(new ConvertToCamelCase(true)) - << _("void @WhAt_TODO_hErE();\n") - << _("void WhAtTODOHErE();\n"); - QTest::newRow("escape string literal: simple case") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _(R"(const char *str = @"à xyz";)") - << _(R"(const char *str = "\xc3\xa0xyz";)"); - QTest::newRow("escape string literal: simple case reverse") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _(R"(const char *str = @"\xc3\xa0xyz";)") - << _(R"(const char *str = "à xyz";)"); - QTest::newRow("escape string literal: raw string literal") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _(R"x(const char *str = @R"(à xyz)";)x") - << _(R"x(const char *str = R"(\xc3\xa0xyz)";)x"); - QTest::newRow("escape string literal: splitting required") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _(R"(const char *str = @"à f23бgб1";)") - << _(R"(const char *str = "\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)"); - QTest::newRow("escape string literal: unescape adjacent literals") - << CppQuickFixFactoryPtr(new EscapeStringLiteral) - << _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)") - << _(R"(const char *str = "à f23бgб1";)"); - QTest::newRow("AddLocalDeclaration_QTCREATORBUG-26004") - << CppQuickFixFactoryPtr(new AddDeclarationForUndeclaredIdentifier) - << _("void func() {\n" - " QStringList list;\n" - " @it = list.cbegin();\n" - "}\n") - << _("void func() {\n" - " QStringList list;\n" - " auto it = list.cbegin();\n" - "}\n"); -} - -void QuickfixTest::testGeneric() -{ - QFETCH(CppQuickFixFactoryPtr, factory); - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QuickFixOperationTest(singleDocument(original, expected), factory.data()); -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingCreate_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - - QByteArray originalSource; - QByteArray expectedSource; - - const QByteArray originalHeader = - "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int @it;\n" - "};\n" - "}\n" - "}\n"; - const QByteArray expectedHeader = - "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int it;\n" - "\n" - "public:\n" - " int getIt() const;\n" - " void setIt(int value);\n" - "};\n" - "}\n" - "}\n"; - - originalSource = "#include \"file.h\"\n"; - expectedSource = - "#include \"file.h\"\n\n\n" - "namespace N1 {\n" - "namespace N2 {\n" - "int Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n\n" - "}\n" - "}\n"; - QTest::addRow("insert new namespaces") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "#include \"file.h\"\n" - "namespace N2 {} // decoy\n"; - expectedSource = - "#include \"file.h\"\n" - "namespace N2 {} // decoy\n\n\n" - "namespace N1 {\n" - "namespace N2 {\n" - "int Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n\n" - "}\n" - "}\n"; - QTest::addRow("insert new namespaces (with decoy)") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n" - "\n" - "\n" - "namespace N1 {\n" - "namespace N2 {\n" - "int Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n" - "\n" - "}\n" - "}\n"; - QTest::addRow("insert inner namespace (with decoy and unnamed)") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - const QByteArray unnamedOriginalHeader = "namespace {\n" + originalHeader + "}\n"; - const QByteArray unnamedExpectedHeader = "namespace {\n" + expectedHeader + "}\n"; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "\n" - "namespace N2 {\n" - "int Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n" - "\n" - "}\n" - "\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - QTest::addRow("insert inner namespace in unnamed (with decoy)") - << QByteArrayList{unnamedOriginalHeader, unnamedExpectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "#include \"file.h\"\n" - "namespace N1 {\n" - "namespace N2 {\n" - "namespace N3 {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = - "#include \"file.h\"\n" - "namespace N1 {\n" - "namespace N2 {\n" - "namespace N3 {\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\n" - "}\n" - "}\n"; - QTest::addRow("all namespaces already present") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "namespace N1 {\n" - "using namespace N2::N3;\n" - "using namespace N2;\n" - "using namespace N2;\n" - "using namespace N3;\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N1 {\n" - "using namespace N2::N3;\n" - "using namespace N2;\n" - "using namespace N2;\n" - "using namespace N3;\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" - "}\n"; - QTest::addRow("namespaces present and using namespace") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "using namespace N1::N2::N3;\n" - "using namespace N1::N2;\n" - "namespace N1 {\n" - "using namespace N3;\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "using namespace N1::N2::N3;\n" - "using namespace N1::N2;\n" - "namespace N1 {\n" - "using namespace N3;\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" - "}\n"; - QTest::addRow("namespaces present and outer using namespace") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "using namespace N1;\n" - "using namespace N2;\n" - "namespace N3 {\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "using namespace N1;\n" - "using namespace N2;\n" - "namespace N3 {\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"; - QTest::addRow("namespaces present and outer using namespace") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingCreate() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", headers.at(0), headers.at(1)), - CppTestDocument::create("file.cpp", sources.at(0), sources.at(1))}); - - QuickFixSettings s; - s->cppFileNamespaceHandling = CppQuickFixSettings::MissingNamespaceHandling::CreateMissing; - s->setterParameterNameTemplate = "value"; - s->getterNameTemplate = "get<Name>"; - s->setterInCppFileFrom = 1; - s->getterInCppFileFrom = 1; - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 2); -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingAddUsing_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - - QByteArray originalSource; - QByteArray expectedSource; - - const QByteArray originalHeader = "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int @it;\n" - "};\n" - "}\n" - "}\n"; - const QByteArray expectedHeader = "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int it;\n" - "\n" - "public:\n" - " void setIt(int value);\n" - "};\n" - "}\n" - "}\n"; - - originalSource = "#include \"file.h\"\n"; - expectedSource = "#include \"file.h\"\n\n" - "using namespace N1::N2;\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("add using namespaces") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - const QByteArray unnamedOriginalHeader = "namespace {\n" + originalHeader + "}\n"; - const QByteArray unnamedExpectedHeader = "namespace {\n" + expectedHeader + "}\n"; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "using namespace N2;\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - QTest::addRow("insert using namespace into unnamed nested (with decoy)") - << QByteArrayList{unnamedOriginalHeader, unnamedExpectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n"; - expectedSource = "#include \"file.h\"\n\n" - "using namespace N1::N2;\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("insert using namespace into unnamed") - << QByteArrayList{unnamedOriginalHeader, unnamedExpectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n" - "\n" - "using namespace N1::N2;\n" - "void Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("insert using namespace (with decoy)") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingAddUsing() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", headers.at(0), headers.at(1)), - CppTestDocument::create("file.cpp", sources.at(0), sources.at(1))}); - - QuickFixSettings s; - s->cppFileNamespaceHandling = CppQuickFixSettings::MissingNamespaceHandling::AddUsingDirective; - s->setterParameterNameTemplate = "value"; - s->setterInCppFileFrom = 1; - - if (std::strstr(QTest::currentDataTag(), "unnamed nested") != nullptr) - QSKIP("TODO"); // FIXME - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingFullyQualify_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - - QByteArray originalSource; - QByteArray expectedSource; - - const QByteArray originalHeader = "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int @it;\n" - "};\n" - "}\n" - "}\n"; - const QByteArray expectedHeader = "namespace N1 {\n" - "namespace N2 {\n" - "class Something\n" - "{\n" - " int it;\n" - "\n" - "public:\n" - " void setIt(int value);\n" - "};\n" - "}\n" - "}\n"; - - originalSource = "#include \"file.h\"\n"; - expectedSource = "#include \"file.h\"\n\n" - "void N1::N2::Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("fully qualify") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "\n" - "void N1::N2::Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("fully qualify (with decoy)") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n" - "\n" - "void N1::N2::Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("qualify in inner namespace (with decoy)") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - const QByteArray unnamedOriginalHeader = "namespace {\n" + originalHeader + "}\n"; - const QByteArray unnamedExpectedHeader = "namespace {\n" + expectedHeader + "}\n"; - - originalSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - expectedSource = "#include \"file.h\"\n" - "namespace N2 {} // decoy\n" - "namespace {\n" - "namespace N1 {\n" - "void N2::Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n" - "namespace {\n" - "}\n" - "}\n" - "}\n"; - QTest::addRow("qualify in inner namespace unnamed nested (with decoy)") - << QByteArrayList{unnamedOriginalHeader, unnamedExpectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = "#include \"file.h\"\n"; - expectedSource = "#include \"file.h\"\n\n" - "void N1::N2::Something::setIt(int value)\n" - "{\n" - " it = value;\n" - "}\n"; - QTest::addRow("qualify in unnamed namespace") - << QByteArrayList{unnamedOriginalHeader, unnamedExpectedHeader} - << QByteArrayList{originalSource, expectedSource}; -} - -void QuickfixTest::testGenerateGetterSetterNamespaceHandlingFullyQualify() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", headers.at(0), headers.at(1)), - CppTestDocument::create("file.cpp", sources.at(0), sources.at(1))}); - - QuickFixSettings s; - s->cppFileNamespaceHandling = CppQuickFixSettings::MissingNamespaceHandling::RewriteType; - s->setterParameterNameTemplate = "value"; - s->setterInCppFileFrom = 1; - - if (std::strstr(QTest::currentDataTag(), "unnamed nested") != nullptr) - QSKIP("TODO"); // FIXME - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testGenerateGetterSetterCustomNames_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<int>("operation"); - - QByteArray originalSource; - QByteArray expectedSource; - - // Check if right names are created - originalSource = R"-( -class Test { - int m_fooBar_test@; -}; -)-"; - expectedSource = R"-( -class Test { - int m_fooBar_test; - -public: - int give_me_foo_bar_test() const - { - return m_fooBar_test; - } - void Seet_FooBar_test(int New_Foo_Bar_Test) - { - if (m_fooBar_test == New_Foo_Bar_Test) - return; - m_fooBar_test = New_Foo_Bar_Test; - emit newFooBarTestValue(); - } - void set_fooBarTest_toDefault() - { - Seet_FooBar_test({}); // TODO: Adapt to use your actual default value - } - -signals: - void newFooBarTestValue(); - -private: - Q_PROPERTY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) -}; -)-"; - QTest::addRow("create right names") << QByteArrayList{originalSource, expectedSource} << 4; - - // Check if not triggered with custom names - originalSource = R"-( -class Test { - int m_fooBar_test@; - -public: - int give_me_foo_bar_test() const - { - return m_fooBar_test; - } - void Seet_FooBar_test(int New_Foo_Bar_Test) - { - if (m_fooBar_test == New_Foo_Bar_Test) - return; - m_fooBar_test = New_Foo_Bar_Test; - emit newFooBarTestValue(); - } - void set_fooBarTest_toDefault() - { - Seet_FooBar_test({}); // TODO: Adapt to use your actual default value - } - -signals: - void newFooBarTestValue(); - -private: - Q_PROPERTY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) -}; -)-"; - expectedSource = ""; - QTest::addRow("everything already exists") << QByteArrayList{originalSource, expectedSource} << 4; - - // create from Q_PROPERTY with custom names - originalSource = R"-( -class Test { - Q_PROPER@TY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) - -public: - int give_me_foo_bar_test() const - { - return mem_fooBar_test; - } - void Seet_FooBar_test(int New_Foo_Bar_Test) - { - if (mem_fooBar_test == New_Foo_Bar_Test) - return; - mem_fooBar_test = New_Foo_Bar_Test; - emit newFooBarTestValue(); - } - void set_fooBarTest_toDefault() - { - Seet_FooBar_test({}); // TODO: Adapt to use your actual default value - } - -signals: - void newFooBarTestValue(); -}; -)-"; - expectedSource = R"-( -class Test { - Q_PROPERTY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) - -public: - int give_me_foo_bar_test() const - { - return mem_fooBar_test; - } - void Seet_FooBar_test(int New_Foo_Bar_Test) - { - if (mem_fooBar_test == New_Foo_Bar_Test) - return; - mem_fooBar_test = New_Foo_Bar_Test; - emit newFooBarTestValue(); - } - void set_fooBarTest_toDefault() - { - Seet_FooBar_test({}); // TODO: Adapt to use your actual default value - } - -signals: - void newFooBarTestValue(); -private: - int mem_fooBar_test; -}; -)-"; - QTest::addRow("create only member variable") - << QByteArrayList{originalSource, expectedSource} << 0; - - // create from Q_PROPERTY with custom names - originalSource = R"-( -class Test { - Q_PROPE@RTY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) - int mem_fooBar_test; -public: -}; -)-"; - expectedSource = R"-( -class Test { - Q_PROPERTY(int fooBar_test READ give_me_foo_bar_test WRITE Seet_FooBar_test RESET set_fooBarTest_toDefault NOTIFY newFooBarTestValue FINAL) - int mem_fooBar_test; -public: - int give_me_foo_bar_test() const - { - return mem_fooBar_test; - } - void Seet_FooBar_test(int New_Foo_Bar_Test) - { - if (mem_fooBar_test == New_Foo_Bar_Test) - return; - mem_fooBar_test = New_Foo_Bar_Test; - emit newFooBarTestValue(); - } - void set_fooBarTest_toDefault() - { - Seet_FooBar_test({}); // TODO: Adapt to use your actual default value - } -signals: - void newFooBarTestValue(); -}; -)-"; - QTest::addRow("create methods with given member variable") - << QByteArrayList{originalSource, expectedSource} << 0; -} - -void QuickfixTest::testGenerateGetterSetterCustomNames() -{ - QFETCH(QByteArrayList, headers); - QFETCH(int, operation); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", headers.at(0), headers.at(1))}); - - QuickFixSettings s; - s->setterInCppFileFrom = 0; - s->getterInCppFileFrom = 0; - s->setterNameTemplate = "Seet_<Name>"; - s->getterNameTemplate = "give_me_<snake>"; - s->signalNameTemplate = "new<Camel>Value"; - s->setterParameterNameTemplate = "New_<Snake>"; - s->resetNameTemplate = "set_<camel>_toDefault"; - s->memberVariableNameTemplate = "mem_<name>"; - if (operation == 0) { - InsertQtPropertyMembers factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), operation); - } else { - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), operation); - } -} - -void QuickfixTest::testGenerateGetterSetterValueTypes_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<int>("operation"); - - QByteArray originalSource; - QByteArray expectedSource; - - // int should be a value type - originalSource = R"-( -class Test { - int i@; -}; -)-"; - expectedSource = R"-( -class Test { - int i; - -public: - int getI() const - { - return i; - } -}; -)-"; - QTest::addRow("int") << QByteArrayList{originalSource, expectedSource} << 1; - - // return type should be only int without const - originalSource = R"-( -class Test { - const int i@; -}; -)-"; - expectedSource = R"-( -class Test { - const int i; - -public: - int getI() const - { - return i; - } -}; -)-"; - QTest::addRow("const int") << QByteArrayList{originalSource, expectedSource} << 0; - - // float should be a value type - originalSource = R"-( -class Test { - float f@; -}; -)-"; - expectedSource = R"-( -class Test { - float f; - -public: - float getF() const - { - return f; - } -}; -)-"; - QTest::addRow("float") << QByteArrayList{originalSource, expectedSource} << 1; - - // pointer should be a value type - originalSource = R"-( -class Test { - void* v@; -}; -)-"; - expectedSource = R"-( -class Test { - void* v; - -public: - void *getV() const - { - return v; - } -}; -)-"; - QTest::addRow("pointer") << QByteArrayList{originalSource, expectedSource} << 1; - - // reference should be a value type (setter is const ref) - originalSource = R"-( -class Test { - int& r@; -}; -)-"; - expectedSource = R"-( -class Test { - int& r; - -public: - int &getR() const - { - return r; - } - void setR(const int &newR) - { - r = newR; - } -}; -)-"; - QTest::addRow("reference to value type") << QByteArrayList{originalSource, expectedSource} << 2; - - // reference should be a value type - originalSource = R"-( -using bar = int; -class Test { - bar i@; -}; -)-"; - expectedSource = R"-( -using bar = int; -class Test { - bar i; - -public: - bar getI() const - { - return i; - } -}; -)-"; - QTest::addRow("value type through using") << QByteArrayList{originalSource, expectedSource} << 1; - - // enum should be a value type - originalSource = R"-( -enum Foo{V1, V2}; -class Test { - Foo e@; -}; -)-"; - expectedSource = R"-( -enum Foo{V1, V2}; -class Test { - Foo e; - -public: - Foo getE() const - { - return e; - } -}; -)-"; - QTest::addRow("enum") << QByteArrayList{originalSource, expectedSource} << 1; - - // class should not be a value type - originalSource = R"-( -class NoVal{}; -class Test { - NoVal n@; -}; -)-"; - expectedSource = R"-( -class NoVal{}; -class Test { - NoVal n; - -public: - const NoVal &getN() const - { - return n; - } -}; -)-"; - QTest::addRow("class") << QByteArrayList{originalSource, expectedSource} << 1; - - // custom classes can be a value type - originalSource = R"-( -class Value{}; -class Test { - Value v@; -}; -)-"; - expectedSource = R"-( -class Value{}; -class Test { - Value v; - -public: - Value getV() const - { - return v; - } -}; -)-"; - QTest::addRow("value class") << QByteArrayList{originalSource, expectedSource} << 1; - - // custom classes (in namespace) can be a value type - originalSource = R"-( -namespace N1{ -class Value{}; -} -class Test { - N1::Value v@; -}; -)-"; - expectedSource = R"-( -namespace N1{ -class Value{}; -} -class Test { - N1::Value v; - -public: - N1::Value getV() const - { - return v; - } -}; -)-"; - QTest::addRow("value class in namespace") << QByteArrayList{originalSource, expectedSource} << 1; - - // custom template class can be a value type - originalSource = R"-( -template<typename T> -class Value{}; -class Test { - Value<int> v@; -}; -)-"; - expectedSource = R"-( -template<typename T> -class Value{}; -class Test { - Value<int> v; - -public: - Value<int> getV() const - { - return v; - } -}; -)-"; - QTest::addRow("value template class") << QByteArrayList{originalSource, expectedSource} << 1; -} - -void QuickfixTest::testGenerateGetterSetterValueTypes() -{ - QFETCH(QByteArrayList, headers); - QFETCH(int, operation); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", headers.at(0), headers.at(1))}); - - QuickFixSettings s; - s->setterInCppFileFrom = 0; - s->getterInCppFileFrom = 0; - s->getterNameTemplate = "get<Name>"; - s->valueTypes << "Value"; - s->returnByConstRef = true; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), operation); -} - -/// Checks: Use template for a custom type -void QuickfixTest::testGenerateGetterSetterCustomTemplate() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - const _ customTypeDecl = R"--( -namespace N1 { -namespace N2 { -struct test{}; -} -template<typename T> -struct custom { - void assign(const custom<T>&); - bool equals(const custom<T>&); - T* get(); -}; -)--"; - // Header File - original = customTypeDecl + R"--( -class Foo -{ -public: - custom<N2::test> bar@; -}; -})--"; - expected = customTypeDecl + R"--( -class Foo -{ -public: - custom<N2::test> bar@; - N2::test *getBar() const; - void setBar(const custom<N2::test> &newBar); -signals: - void barChanged(N2::test *bar); -private: - Q_PROPERTY(N2::test *bar READ getBar NOTIFY barChanged FINAL) -}; -})--"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = ""; - expected = R"-( -using namespace N1; -N2::test *Foo::getBar() const -{ - return bar.get(); -} - -void Foo::setBar(const custom<N2::test> &newBar) -{ - if (bar.equals(newBar)) - return; - bar.assign(newBar); - emit barChanged(bar.get()); -} -)-"; - - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - QuickFixSettings s; - s->cppFileNamespaceHandling = CppQuickFixSettings::MissingNamespaceHandling::AddUsingDirective; - s->getterNameTemplate = "get<Name>"; - s->getterInCppFileFrom = 1; - s->signalWithNewValue = true; - CppQuickFixSettings::CustomTemplate t; - t.types.append("custom"); - t.equalComparison = "<cur>.equals(<new>)"; - t.returnExpression = "<cur>.get()"; - t.returnType = "<T> *"; - t.assignment = "<cur>.assign(<new>)"; - s->customTemplates.push_back(t); - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 5); -} - -/// Checks: if the setter parameter name is the same as the member variable name, this-> is needed -void QuickfixTest::testGenerateGetterSetterNeedThis() -{ - QList<TestDocumentPtr> testDocuments; - - // Header File - const QByteArray original = R"-( -class Foo { - int bar@; -public: -}; -)-"; - const QByteArray expected = R"-( -class Foo { - int bar@; -public: - void setBar(int bar) - { - this->bar = bar; - } -}; -)-"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - QuickFixSettings s; - s->setterParameterNameTemplate = "<name>"; - s->setterInCppFileFrom = 0; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 0); -} - -void QuickfixTest::testGenerateGetterSetterOfferedFixes_data() -{ - QTest::addColumn<QByteArray>("header"); - QTest::addColumn<QStringList>("offered"); - - QByteArray header; - QStringList offered; - const QString setter = QStringLiteral("Generate Setter"); - const QString getter = QStringLiteral("Generate Getter"); - const QString getset = QStringLiteral("Generate Getter and Setter"); - const QString constQandMissing = QStringLiteral( - "Generate Constant Q_PROPERTY and Missing Members"); - const QString qAndResetAndMissing = QStringLiteral( - "Generate Q_PROPERTY and Missing Members with Reset Function"); - const QString qAndMissing = QStringLiteral("Generate Q_PROPERTY and Missing Members"); - const QStringList all{setter, getter, getset, constQandMissing, qAndResetAndMissing, qAndMissing}; - - header = R"-( -class Foo { - static int bar@; -}; -)-"; - offered = QStringList{setter, getter, getset, constQandMissing}; - QTest::addRow("static") << header << offered; - - header = R"-( -class Foo { - static const int bar@; -}; -)-"; - offered = QStringList{getter, constQandMissing}; - QTest::addRow("const static") << header << offered; - - header = R"-( -class Foo { - const int bar@; -}; -)-"; - offered = QStringList{getter, constQandMissing}; - QTest::addRow("const") << header << offered; - - header = R"-( -class Foo { - const int bar@; - int getBar() const; -}; -)-"; - offered = QStringList{constQandMissing}; - QTest::addRow("const + getter") << header << offered; - - header = R"-( -class Foo { - const int bar@; - int getBar() const; - void setBar(int value); -}; -)-"; - offered = QStringList{}; - QTest::addRow("const + getter + setter") << header << offered; - - header = R"-( -class Foo { - const int* bar@; -}; -)-"; - offered = all; - QTest::addRow("pointer to const") << header << offered; - - header = R"-( -class Foo { - int bar@; -public: - int bar(); -}; -)-"; - offered = QStringList{setter, constQandMissing, qAndResetAndMissing, qAndMissing}; - QTest::addRow("existing getter") << header << offered; - - header = R"-( -class Foo { - int bar@; -public: - set setBar(int); -}; -)-"; - offered = QStringList{getter}; - QTest::addRow("existing setter") << header << offered; - - header = R"-( -class Foo { - int bar@; -signals: - void barChanged(int); -}; -)-"; - offered = QStringList{setter, getter, getset, qAndResetAndMissing, qAndMissing}; - QTest::addRow("existing signal (no const Q_PROPERTY)") << header << offered; - - header = R"-( -class Foo { - int m_bar@; - Q_PROPERTY(int bar) -}; -)-"; - offered = QStringList{}; // user should use "InsertQPropertyMembers", no duplicated code - QTest::addRow("existing Q_PROPERTY") << header << offered; -} - -void QuickfixTest::testGenerateGetterSetterOfferedFixes() -{ - QFETCH(QByteArray, header); - QFETCH(QStringList, offered); - - QList<TestDocumentPtr> testDocuments( - {CppTestDocument::create("file.h", header, header)}); - - GenerateGetterSetter factory; - QuickFixOfferedOperationsTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), offered); -} - -void QuickfixTest::testGenerateGetterSetterGeneralTests_data() -{ - QTest::addColumn<int>("operation"); - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QTest::newRow("GenerateGetterSetter_referenceToNonConst") - << 2 - << _("\n" - "class Something\n" - "{\n" - " int &it@;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " int ⁢\n" - "\n" - "public:\n" - " int &getIt() const;\n" - " void setIt(const int &it);\n" - "};\n" - "\n" - "int &Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(const int &it)\n" - "{\n" - " this->it = it;\n" - "}\n"); - - // Checks: No special treatment for reference to const. - QTest::newRow("GenerateGetterSetter_referenceToConst") - << 2 - << _("\n" - "class Something\n" - "{\n" - " const int &it@;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " const int ⁢\n" - "\n" - "public:\n" - " const int &getIt() const;\n" - " void setIt(const int &it);\n" - "};\n" - "\n" - "const int &Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(const int &it)\n" - "{\n" - " this->it = it;\n" - "}\n"); - - // Checks: - // 1. Setter: Setter is a static function. - // 2. Getter: Getter is a static, non const function. - QTest::newRow("GenerateGetterSetter_staticMember") - << 2 - << _("\n" - "class Something\n" - "{\n" - " static int @m_member;\n" - "};\n") - << _("\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"); - - // Check: Check if it works on the second declarator - // clang-format off - QTest::newRow("GenerateGetterSetter_secondDeclarator") << 2 - << _("\n" - "class Something\n" - "{\n" - " int *foo, @it;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " int *foo, it;\n" - "\n" - "public:\n" - " int getIt() const;\n" - " void setIt(int it);\n" - "};\n" - "\n" - "int Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int it)\n" - "{\n" - " this->it = it;\n" - "}\n"); - // clang-format on - - // Check: Quick fix is offered for "int *@it;" ('@' denotes the text cursor position) - QTest::newRow("GenerateGetterSetter_triggeringRightAfterPointerSign") - << 2 - << _("\n" - "class Something\n" - "{\n" - " int *@it;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " int *it;\n" - "\n" - "public:\n" - " int *getIt() const;\n" - " void setIt(int *it);\n" - "};\n" - "\n" - "int *Something::getIt() const\n" - "{\n" - " return it;\n" - "}\n" - "\n" - "void Something::setIt(int *it)\n" - "{\n" - " this->it = it;\n" - "}\n"); - - // Checks if "m_" is recognized as "m" with the postfix "_" and not simply as "m_" prefix. - QTest::newRow("GenerateGetterSetter_recognizeMasVariableName") - << 2 - << _("\n" - "class Something\n" - "{\n" - " int @m_;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " int m_;\n" - "\n" - "public:\n" - " int m() const;\n" - " void setM(int m);\n" - "};\n" - "\n" - "int Something::m() const\n" - "{\n" - " return m_;\n" - "}\n" - "\n" - "void Something::setM(int m)\n" - "{\n" - " m_ = m;\n" - "}\n"); - - // Checks if "m" followed by an upper character is recognized as a prefix - QTest::newRow("GenerateGetterSetter_recognizeMFollowedByCapital") - << 2 - << _("\n" - "class Something\n" - "{\n" - " int @mFoo;\n" - "};\n") - << _("\n" - "class Something\n" - "{\n" - " int mFoo;\n" - "\n" - "public:\n" - " int foo() const;\n" - " void setFoo(int foo);\n" - "};\n" - "\n" - "int Something::foo() const\n" - "{\n" - " return mFoo;\n" - "}\n" - "\n" - "void Something::setFoo(int foo)\n" - "{\n" - " mFoo = foo;\n" - "}\n"); -} -void QuickfixTest::testGenerateGetterSetterGeneralTests() -{ - QFETCH(int, operation); - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QuickFixSettings s; - s->setterParameterNameTemplate = "<name>"; - s->getterInCppFileFrom = 1; - s->setterInCppFileFrom = 1; - - GenerateGetterSetter factory; - QuickFixOperationTest(singleDocument(original, expected), - &factory, - ProjectExplorer::HeaderPaths(), - operation); -} -/// Checks: Only generate getter -void QuickfixTest::testGenerateGetterSetterOnlyGetter() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - "};\n"; - expected = - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - " int getBar() const;\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original.resize(0); - expected = - "\n" - "int Foo::getBar() const\n" - "{\n" - " return bar;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - QuickFixSettings s; - s->getterInCppFileFrom = 1; - s->getterNameTemplate = "get<Name>"; - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 1); -} - -/// Checks: Only generate setter -void QuickfixTest::testGenerateGetterSetterOnlySetter() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - QuickFixSettings s; - s->setterAsSlot = true; // To be ignored, as we don't have QObjects here. - - // Header File - original = - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - "};\n"; - expected = - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - " void setBar(int value);\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original.resize(0); - expected = - "\n" - "void Foo::setBar(int value)\n" - "{\n" - " bar = value;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - s->setterInCppFileFrom = 1; - s->setterParameterNameTemplate = "value"; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 0); -} - -void QuickfixTest::testGenerateGetterSetterAnonymousClass() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - QuickFixSettings s; - s->setterInCppFileFrom = 1; - s->setterParameterNameTemplate = "value"; - - // Header File - original = R"( - class { - int @m_foo; - } bar; -)"; - expected = R"( - class { - int m_foo; - - public: - int foo() const - { - return m_foo; - } - void setFoo(int value) - { - if (m_foo == value) - return; - m_foo = value; - emit fooChanged(); - } - void resetFoo() - { - setFoo({}); // TODO: Adapt to use your actual default defaultValue - } - - signals: - void fooChanged(); - - private: - Q_PROPERTY(int foo READ foo WRITE setFoo RESET resetFoo NOTIFY fooChanged FINAL) - } bar; -)"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - testDocuments << CppTestDocument::create("file.cpp", {}, {}); - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 4); -} - -void QuickfixTest::testGenerateGetterSetterInlineInHeaderFile() -{ - QList<TestDocumentPtr> testDocuments; - const QByteArray original = R"-( -class Foo { -public: - int bar@; -}; -)-"; - const QByteArray expected = R"-( -class Foo { -public: - int bar; - int getBar() const; - void setBar(int value); - void resetBar(); -signals: - void barChanged(); -private: - Q_PROPERTY(int bar READ getBar WRITE setBar RESET resetBar NOTIFY barChanged FINAL) -}; - -inline int Foo::getBar() const -{ - return bar; -} - -inline void Foo::setBar(int value) -{ - if (bar == value) - return; - bar = value; - emit barChanged(); -} - -inline void Foo::resetBar() -{ - setBar({}); // TODO: Adapt to use your actual default defaultValue -} -)-"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - QuickFixSettings s; - s->setterOutsideClassFrom = 1; - s->getterOutsideClassFrom = 1; - s->setterParameterNameTemplate = "value"; - s->getterNameTemplate = "get<Name>"; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 4); -} - -void QuickfixTest::testGenerateGetterSetterOnlySetterHeaderFileWithIncludeGuard() -{ - QList<TestDocumentPtr> testDocuments; - const QByteArray original = - "#ifndef FILE__H__DECLARED\n" - "#define FILE__H__DECLARED\n" - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - "};\n" - "#endif\n"; - const QByteArray expected = - "#ifndef FILE__H__DECLARED\n" - "#define FILE__H__DECLARED\n" - "class Foo\n" - "{\n" - "public:\n" - " int bar@;\n" - " void setBar(int value);\n" - "};\n\n" - "inline void Foo::setBar(int value)\n" - "{\n" - " bar = value;\n" - "}\n" - "#endif\n"; - - testDocuments << CppTestDocument::create("file.h", original, expected); - - QuickFixSettings s; - s->setterOutsideClassFrom = 1; - s->setterParameterNameTemplate = "value"; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 0); -} - -void QuickfixTest::testGenerateGetterFunctionAsTemplateArg() -{ - QList<TestDocumentPtr> testDocuments; - const QByteArray original = R"( -template<typename T> class TS {}; -template<typename T, typename U> class TS<T(U)> {}; - -class S2 { - TS<int(int)> @member; -}; -)"; - const QByteArray expected = R"( -template<typename T> class TS {}; -template<typename T, typename U> class TS<T(U)> {}; - -class S2 { - TS<int(int)> member; - -public: - const TS<int (int)> &getMember() const - { - return member; - } -}; -)"; - - testDocuments << CppTestDocument::create("file.h", original, expected); - - QuickFixSettings s; - s->getterOutsideClassFrom = 0; - s->getterInCppFileFrom = 0; - s->getterNameTemplate = "get<Name>"; - s->returnByConstRef = true; - - GenerateGetterSetter factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 1); -} - -class CppCodeStyleSettingsChanger { -public: - CppCodeStyleSettingsChanger(const CppCodeStyleSettings &settings); - ~CppCodeStyleSettingsChanger(); // Restore original - - static CppCodeStyleSettings currentSettings(); - -private: - void setSettings(const CppCodeStyleSettings &settings); - - CppCodeStyleSettings m_originalSettings; -}; - -CppCodeStyleSettingsChanger::CppCodeStyleSettingsChanger(const CppCodeStyleSettings &settings) -{ - m_originalSettings = currentSettings(); - setSettings(settings); -} - -CppCodeStyleSettingsChanger::~CppCodeStyleSettingsChanger() -{ - setSettings(m_originalSettings); -} - -void CppCodeStyleSettingsChanger::setSettings(const CppCodeStyleSettings &settings) -{ - QVariant variant; - variant.setValue(settings); - - CppToolsSettings::cppCodeStyle()->currentDelegate()->setValue(variant); -} - -CppCodeStyleSettings CppCodeStyleSettingsChanger::currentSettings() -{ - return CppToolsSettings::cppCodeStyle()->currentDelegate()->value().value<CppCodeStyleSettings>(); -} - -void QuickfixTest::testGenerateGettersSetters_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - const QByteArray onlyReset = R"( -class Foo { -public: - int bar() const; - void setBar(int bar); -private: - int m_bar; -@};)"; - - const QByteArray onlyResetAfter = R"( -class @Foo { -public: - int bar() const; - void setBar(int bar); - void resetBar(); - -private: - int m_bar; -}; -inline void Foo::resetBar() -{ - setBar({}); // TODO: Adapt to use your actual default defaultValue -} -)"; - QTest::addRow("only reset") << onlyReset << onlyResetAfter; - - const QByteArray withCandidates = R"( -class @Foo { -public: - int bar() const; - void setBar(int bar) { m_bar = bar; } - - int getBar2() const; - - int m_alreadyPublic; - -private: - friend void distraction(); - class AnotherDistraction {}; - enum EvenMoreDistraction { val1, val2 }; - - int m_bar; - int bar2_; - QString bar3; -};)"; - const QByteArray after = R"( -class Foo { -public: - int bar() const; - void setBar(int bar) { m_bar = bar; } - - int getBar2() const; - - int m_alreadyPublic; - - void resetBar(); - void setBar2(int value); - void resetBar2(); - const QString &getBar3() const; - void setBar3(const QString &value); - void resetBar3(); - -signals: - void bar2Changed(); - void bar3Changed(); - -private: - friend void distraction(); - class AnotherDistraction {}; - enum EvenMoreDistraction { val1, val2 }; - - int m_bar; - int bar2_; - QString bar3; - Q_PROPERTY(int bar2 READ getBar2 WRITE setBar2 RESET resetBar2 NOTIFY bar2Changed FINAL) - Q_PROPERTY(QString bar3 READ getBar3 WRITE setBar3 RESET resetBar3 NOTIFY bar3Changed FINAL) -}; -inline void Foo::resetBar() -{ - setBar({}); // TODO: Adapt to use your actual default defaultValue -} - -inline void Foo::setBar2(int value) -{ - if (bar2_ == value) - return; - bar2_ = value; - emit bar2Changed(); -} - -inline void Foo::resetBar2() -{ - setBar2({}); // TODO: Adapt to use your actual default defaultValue -} - -inline const QString &Foo::getBar3() const -{ - return bar3; -} - -inline void Foo::setBar3(const QString &value) -{ - if (bar3 == value) - return; - bar3 = value; - emit bar3Changed(); -} - -inline void Foo::resetBar3() -{ - setBar3({}); // TODO: Adapt to use your actual default defaultValue -} -)"; - QTest::addRow("with candidates") << withCandidates << after; -} - -void QuickfixTest::testGenerateGettersSetters() -{ - class TestFactory : public GenerateGettersSettersForClass - { - public: - TestFactory() { setTest(); } - }; - - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QuickFixSettings s; - s->getterNameTemplate = "get<Name>"; - s->setterParameterNameTemplate = "value"; - s->setterOutsideClassFrom = 1; - s->getterOutsideClassFrom = 1; - s->returnByConstRef = true; - - TestFactory factory; - QuickFixOperationTest({CppTestDocument::create("file.h", original, expected)}, &factory); -} - -void QuickfixTest::testInsertQtPropertyMembers_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QTest::newRow("InsertQtPropertyMembers") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " @Q_PROPERTY(int it READ getIt WRITE setIt RESET resetIt NOTIFY itChanged)\n" - "};\n") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " Q_PROPERTY(int it READ getIt WRITE setIt RESET resetIt NOTIFY itChanged)\n" - "\n" - "public:\n" - " int getIt() const;\n" - "\n" - "public slots:\n" - " void setIt(int it)\n" - " {\n" - " if (m_it == it)\n" - " return;\n" - " m_it = it;\n" - " emit itChanged(m_it);\n" - " }\n" - " void resetIt()\n" - " {\n" - " setIt({}); // TODO: Adapt to use your actual default value\n" - " }\n" - "\n" - "signals:\n" - " void itChanged(int it);\n" - "\n" - "private:\n" - " int m_it;\n" - "};\n" - "\n" - "int XmarksTheSpot::getIt() const\n" - "{\n" - " return m_it;\n" - "}\n"); - - QTest::newRow("InsertQtPropertyMembersResetWithoutSet") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " @Q_PROPERTY(int it READ getIt RESET resetIt NOTIFY itChanged)\n" - "};\n") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " Q_PROPERTY(int it READ getIt RESET resetIt NOTIFY itChanged)\n" - "\n" - "public:\n" - " int getIt() const;\n" - "\n" - "public slots:\n" - " void resetIt()\n" - " {\n" - " static int defaultValue{}; // TODO: Adapt to use your actual default " - "value\n" - " if (m_it == defaultValue)\n" - " return;\n" - " m_it = defaultValue;\n" - " emit itChanged(m_it);\n" - " }\n" - "\n" - "signals:\n" - " void itChanged(int it);\n" - "\n" - "private:\n" - " int m_it;\n" - "};\n" - "\n" - "int XmarksTheSpot::getIt() const\n" - "{\n" - " return m_it;\n" - "}\n"); - - QTest::newRow("InsertQtPropertyMembersResetWithoutSetAndNotify") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " @Q_PROPERTY(int it READ getIt RESET resetIt)\n" - "};\n") - << _("struct QObject { void connect(); }\n" - "struct XmarksTheSpot : public QObject {\n" - " Q_PROPERTY(int it READ getIt RESET resetIt)\n" - "\n" - "public:\n" - " int getIt() const;\n" - "\n" - "public slots:\n" - " void resetIt()\n" - " {\n" - " static int defaultValue{}; // TODO: Adapt to use your actual default " - "value\n" - " m_it = defaultValue;\n" - " }\n" - "\n" - "private:\n" - " int m_it;\n" - "};\n" - "\n" - "int XmarksTheSpot::getIt() const\n" - "{\n" - " return m_it;\n" - "}\n"); - - QTest::newRow("InsertQtPropertyMembersPrivateBeforePublic") - << _("struct QObject { void connect(); }\n" - "class XmarksTheSpot : public QObject {\n" - "private:\n" - " @Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n" - "public:\n" - " void find();\n" - "};\n") - << _("struct QObject { void connect(); }\n" - "class XmarksTheSpot : public QObject {\n" - "private:\n" - " Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n" - " int m_it;\n" - "\n" - "public:\n" - " void find();\n" - " int getIt() const;\n" - "public slots:\n" - " void setIt(int it)\n" - " {\n" - " if (m_it == it)\n" - " return;\n" - " m_it = it;\n" - " emit itChanged(m_it);\n" - " }\n" - "signals:\n" - " void itChanged(int it);\n" - "};\n" - "\n" - "int XmarksTheSpot::getIt() const\n" - "{\n" - " return m_it;\n" - "}\n"); -} - -void QuickfixTest::testInsertQtPropertyMembers() -{ - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QuickFixSettings s; - s->setterAsSlot = true; - s->setterInCppFileFrom = 0; - s->setterParameterNameTemplate = "<name>"; - s->signalWithNewValue = true; - - InsertQtPropertyMembers factory; - QuickFixOperationTest({CppTestDocument::create("file.cpp", original, expected)}, &factory); -} - -void QuickfixTest::testInsertMemberFromUse_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QByteArray original; - QByteArray expected; - - original = - "class C {\n" - "public:\n" - " C(int x) : @m_x(x) {}\n" - "private:\n" - " int m_y;\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " C(int x) : m_x(x) {}\n" - "private:\n" - " int m_y;\n" - " int m_x;\n" - "};\n"; - QTest::addRow("inline constructor") << original << expected; - - original = - "class C {\n" - "public:\n" - " C(int x, double d);\n" - "private:\n" - " int m_x;\n" - "};\n" - "C::C(int x, double d) : m_x(x), @m_d(d)\n"; - expected = - "class C {\n" - "public:\n" - " C(int x, double d);\n" - "private:\n" - " int m_x;\n" - " double m_d;\n" - "};\n" - "C::C(int x, double d) : m_x(x), m_d(d)\n"; - QTest::addRow("out-of-line constructor") << original << expected; - - original = - "class C {\n" - "public:\n" - " C(int x) : @m_x(x) {}\n" - "private:\n" - " int m_x;\n" - "};\n"; - expected = ""; - QTest::addRow("member already present") << original << expected; - - original = - "int func() { return 0; }\n" - "class C {\n" - "public:\n" - " C() : @m_x(func()) {}\n" - "private:\n" - " int m_y;\n" - "};\n"; - expected = - "int func() { return 0; }\n" - "class C {\n" - "public:\n" - " C() : m_x(func()) {}\n" - "private:\n" - " int m_y;\n" - " int m_x;\n" - "};\n"; - QTest::addRow("initialization via function call") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.@value = v; }\n" - "private:\n" - " S m_s;\n" - "};\n"; - expected = - "struct S {\n\n" - " int value;\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.value = v; }\n" - "private:\n" - " S m_s;\n" - "};\n"; - QTest::addRow("add member to other struct") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { S::@value = v; }\n" - "};\n"; - expected = - "struct S {\n\n" - " static int value;\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { S::value = v; }\n" - "};\n"; - QTest::addRow("add static member to other struct (explicit)") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.@value = v; }\n" - "private:\n" - " static S m_s;\n" - "};\n"; - expected = - "struct S {\n\n" - " static int value;\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.value = v; }\n" - "private:\n" - " static S m_s;\n" - "};\n"; - QTest::addRow("add static member to other struct (implicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " void setValue(int v);\n" - "};\n" - "void C::setValue(int v) { this->@m_value = v; }\n"; - expected = - "class C {\n" - "public:\n" - " void setValue(int v);\n" - "private:\n" - " int m_value;\n" - "};\n" - "void C::setValue(int v) { this->@m_value = v; }\n"; - QTest::addRow("add member to this (explicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " void setValue(int v) { @m_value = v; }\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " void setValue(int v) { m_value = v; }\n" - "private:\n" - " int m_value;\n" - "};\n"; - QTest::addRow("add member to this (implicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " static void setValue(int v) { @m_value = v; }\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " static void setValue(int v) { m_value = v; }\n" - "private:\n" - " static int m_value;\n" - "};\n"; - QTest::addRow("add static member to this (inline)") << original << expected; - - original = - "class C {\n" - "public:\n" - " static void setValue(int v);\n" - "};\n" - "void C::setValue(int v) { @m_value = v; }\n"; - expected = - "class C {\n" - "public:\n" - " static void setValue(int v);\n" - "private:\n" - " static int m_value;\n" - "};\n" - "void C::setValue(int v) { @m_value = v; }\n"; - QTest::addRow("add static member to this (non-inline)") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.@setValue(v); }\n" - "private:\n" - " S m_s;\n" - "};\n"; - expected = - "struct S {\n\n" - " void setValue(int);\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.setValue(v); }\n" - "private:\n" - " S m_s;\n" - "};\n"; - QTest::addRow("add member function to other struct") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { S::@setValue(v); }\n" - "};\n"; - expected = - "struct S {\n\n" - " static void setValue(int);\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { S::setValue(v); }\n" - "};\n"; - QTest::addRow("add static member function to other struct (explicit)") << original << expected; - - original = - "struct S {\n\n};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.@setValue(v); }\n" - "private:\n" - " static S m_s;\n" - "};\n"; - expected = - "struct S {\n\n" - " static void setValue(int);\n" - "};\n" - "class C {\n" - "public:\n" - " void setValue(int v) { m_s.setValue(v); }\n" - "private:\n" - " static S m_s;\n" - "};\n"; - QTest::addRow("add static member function to other struct (implicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " void setValue(int v);\n" - "};\n" - "void C::setValue(int v) { this->@setValueInternal(v); }\n"; - expected = - "class C {\n" - "public:\n" - " void setValue(int v);\n" - "private:\n" - " void setValueInternal(int);\n" - "};\n" - "void C::setValue(int v) { this->setValueInternal(v); }\n"; - QTest::addRow("add member function to this (explicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " void setValue(int v) { @setValueInternal(v); }\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " void setValue(int v) { setValueInternal(v); }\n" - "private:\n" - " void setValueInternal(int);\n" - "};\n"; - QTest::addRow("add member function to this (implicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " int value() const { return @valueInternal(); }\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " int value() const { return valueInternal(); }\n" - "private:\n" - " int valueInternal() const;\n" - "};\n"; - QTest::addRow("add const member function to this (implicit)") << original << expected; - - original = - "class C {\n" - "public:\n" - " static int value() { int i = @valueInternal(); return i; }\n" - "};\n"; - expected = - "class C {\n" - "public:\n" - " static int value() { int i = @valueInternal(); return i; }\n" - "private:\n" - " static int valueInternal();\n" - "};\n"; - QTest::addRow("add static member function to this (inline)") << original << expected; - - original = - "class C {\n" - "public:\n" - " static int value();\n" - "};\n" - "int C::value() { return @valueInternal(); }\n"; - expected = - "class C {\n" - "public:\n" - " static int value();\n" - "private:\n" - " static int valueInternal();\n" - "};\n" - "int C::value() { return valueInternal(); }\n"; - QTest::addRow("add static member function to this (non-inline)") << original << expected; -} - -void QuickfixTest::testInsertMemberFromUse() -{ - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QList<TestDocumentPtr> testDocuments({ - CppTestDocument::create("file.h", original, expected) - }); - - AddDeclarationForUndeclaredIdentifier factory; - factory.setMembersOnly(); - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check if definition is inserted right after class for insert definition outside -void QuickfixTest::testInsertDefFromDeclAfterClass() -{ - QList<TestDocumentPtr> testDocuments; - 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" - "inline void Foo::a()\n" - "{\n\n}\n" - "\n" - "class Bar {};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 1); -} - -/// Check from header file: If there is a source file, insert the definition in the source file. -/// Case: Source file is empty. -void QuickfixTest::testInsertDefFromDeclHeaderSourceBasic1() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "struct Foo\n" - "{\n" - " Foo()@;\n" - "};\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original.resize(0); - expected = - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check from header file: If there is a source file, insert the definition in the source file. -/// Case: Source file is not empty. -void QuickfixTest::testInsertDefFromDeclHeaderSourceBasic2() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = "void f(const std::vector<int> &v)@;\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "\n" - "int x;\n" - ; - expected = - "#include \"file.h\"\n" - "\n" - "int x;\n" - "\n" - "void f(const std::vector<int> &v)\n" - "{\n" - "\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check from source file: Insert in source file, not header file. -void QuickfixTest::testInsertDefFromDeclHeaderSourceBasic3() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Empty Header File - testDocuments << CppTestDocument::create("file.h", "", ""); - - // Source File - original = - "struct Foo\n" - "{\n" - " Foo()@;\n" - "};\n"; - expected = original + - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check from header file: If the class is in a namespace, the added function definition -/// name must be qualified accordingly. -void QuickfixTest::testInsertDefFromDeclHeaderSourceNamespace1() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace N {\n" - "struct Foo\n" - "{\n" - " Foo()@;\n" - "};\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original.resize(0); - expected = - "\n" - "N::Foo::Foo()\n" - "{\n\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check from header file: If the class is in namespace N and the source file has a -/// "using namespace N" line, the function definition name must be qualified accordingly. -void QuickfixTest::testInsertDefFromDeclHeaderSourceNamespace2() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace N {\n" - "struct Foo\n" - "{\n" - " Foo()@;\n" - "};\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "using namespace N;\n" - ; - expected = original + - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check definition insert inside class -void QuickfixTest::testInsertDefFromDeclInsideClass() -{ - const QByteArray original = - "class Foo {\n" - " void b@ar();\n" - "};"; - const QByteArray expected = - "class Foo {\n" - " void bar()\n" - " {\n\n" - " }\n" - "};"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, ProjectExplorer::HeaderPaths(), - 1); -} - -/// Check not triggering when definition exists -void QuickfixTest::testInsertDefFromDeclNotTriggeringWhenDefinitionExists() -{ - const QByteArray original = - "class Foo {\n" - " void b@ar();\n" - "};\n" - "void Foo::bar() {}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, ""), &factory, ProjectExplorer::HeaderPaths(), 1); -} - -/// Find right implementation file. -void QuickfixTest::testInsertDefFromDeclFindRightImplementationFile() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "struct Foo\n" - "{\n" - " Foo();\n" - " void a();\n" - " void b@();\n" - "};\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File #1 - original = - "#include \"file.h\"\n" - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - - // Source File #2 - original = - "#include \"file.h\"\n" - "\n" - "void Foo::a()\n" - "{\n\n" - "}\n"; - expected = original + - "\n" - "void Foo::b()\n" - "{\n\n" - "}\n"; - testDocuments << CppTestDocument::create("file2.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Ignore generated functions declarations when looking at the surrounding -/// functions declarations in order to find the right implementation file. -void QuickfixTest::testInsertDefFromDeclIgnoreSurroundingGeneratedDeclarations() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "#define DECLARE_HIDDEN_FUNCTION void hidden();\n" - "struct Foo\n" - "{\n" - " void a();\n" - " DECLARE_HIDDEN_FUNCTION\n" - " void b@();\n" - "};\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File #1 - original = - "#include \"file.h\"\n" - "\n" - "void Foo::a()\n" - "{\n\n" - "}\n"; - expected = - "#include \"file.h\"\n" - "\n" - "void Foo::a()\n" - "{\n\n" - "}\n" - "\n" - "void Foo::b()\n" - "{\n\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - // Source File #2 - original = - "#include \"file.h\"\n" - "\n" - "void Foo::hidden()\n" - "{\n\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file2.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check if whitespace is respected for operator functions -void QuickfixTest::testInsertDefFromDeclRespectWsInOperatorNames1() -{ - QByteArray original = - "class Foo\n" - "{\n" - " Foo &opera@tor =();\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " Foo &operator =();\n" - "};\n" - "\n" - "Foo &Foo::operator =()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check if whitespace is respected for operator functions -void QuickfixTest::testInsertDefFromDeclRespectWsInOperatorNames2() -{ - QByteArray original = - "class Foo\n" - "{\n" - " Foo &opera@tor=();\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " Foo &operator=();\n" - "};\n" - "\n" - "Foo &Foo::operator=()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check that the noexcept exception specifier is transferred -void QuickfixTest::testInsertDefFromDeclNoexceptSpecifier() -{ - QByteArray original = - "class Foo\n" - "{\n" - " void @foo() noexcept(false);\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " void foo() noexcept(false);\n" - "};\n" - "\n" - "void Foo::foo() noexcept(false)\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check if a function like macro use is not separated by the function to insert -/// Case: Macro preceded by preproceesor directives and declaration. -void QuickfixTest::testInsertDefFromDeclMacroUsesAtEndOfFile1() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = "void f()@;\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "#define MACRO(X) X x;\n" - "int lala;\n" - "\n" - "MACRO(int)\n" - ; - expected = - "#include \"file.h\"\n" - "#define MACRO(X) X x;\n" - "int lala;\n" - "\n" - "\n" - "\n" - "void f()\n" - "{\n" - "\n" - "}\n" - "\n" - "MACRO(int)\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check if a function like macro use is not separated by the function to insert -/// Case: Marco preceded only by preprocessor directives. -void QuickfixTest::testInsertDefFromDeclMacroUsesAtEndOfFile2() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = "void f()@;\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "#define MACRO(X) X x;\n" - "\n" - "MACRO(int)\n" - ; - expected = - "#include \"file.h\"\n" - "#define MACRO(X) X x;\n" - "\n" - "\n" - "\n" - "void f()\n" - "{\n" - "\n" - "}\n" - "\n" - "MACRO(int)\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check if insertion happens before syntactically erroneous statements at end of file. -void QuickfixTest::testInsertDefFromDeclErroneousStatementAtEndOfFile() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = "void f()@;\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "\n" - "MissingSemicolon(int)\n" - ; - expected = - "#include \"file.h\"\n" - "\n" - "\n" - "\n" - "void f()\n" - "{\n" - "\n" - "}\n" - "\n" - "MissingSemicolon(int)\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Respect rvalue references -void QuickfixTest::testInsertDefFromDeclRvalueReference() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = "void f(Foo &&)@;\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = ""; - expected = - "\n" - "void f(Foo &&)\n" - "{\n" - "\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclFunctionTryBlock() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = R"( -struct Foo { - void tryCatchFunc(); - void @otherFunc(); -}; -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" - -void Foo::tryCatchFunc() try {} catch (...) {} -)"; - expected = R"( -#include "file.h" - -void Foo::tryCatchFunc() try {} catch (...) {} - -void Foo::otherFunc() -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclUsingDecl() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = R"( -namespace N { struct S; } -using N::S; - -void @func(const S &s); -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -void func(const S &s) -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); - - testDocuments.clear(); - original = R"( -namespace N1 { -namespace N2 { struct S; } -using N2::S; -} - -void @func(const N1::S &s); -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -void func(const N1::S &s) -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QuickFixOperationTest(testDocuments, &factory); - - // No using declarations here, but the code model has one. No idea why. - testDocuments.clear(); - original = R"( -class B {}; -class D : public B { - @D(); -}; -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -D::D() -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QuickFixOperationTest(testDocuments, &factory); - - testDocuments.clear(); - original = R"( -namespace ns1 { template<typename T> class span {}; } - -namespace ns { -using ns1::span; -class foo -{ - void @bar(ns::span<int>); -}; -} -)"; - expected = R"( -namespace ns1 { template<typename T> class span {}; } - -namespace ns { -using ns1::span; -class foo -{ - void bar(ns::span<int>); -}; - -void foo::bar(ns::span<int>) -{ - -} - -} -)"; - // TODO: Unneeded namespace gets inserted in RewriteName::visit(const QualifiedNameId *) - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QuickFixOperationTest(testDocuments, &factory); -} - -/// Find right implementation file. (QTCREATORBUG-10728) -void QuickfixTest::testInsertDefFromDeclFindImplementationFile() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - " void bar();\n" - " void ba@z();\n" - "};\n" - "\n" - "void Foo::bar()\n" - "{}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - ; - expected = - "#include \"file.h\"\n" - "\n" - "void Foo::baz()\n" - "{\n" - "\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclUnicodeIdentifier() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // - // The following "non-latin1" code points are used in the tests: - // - // U+00FC - 2 code units in UTF8, 1 in UTF16 - LATIN SMALL LETTER U WITH DIAERESIS - // U+4E8C - 3 code units in UTF8, 1 in UTF16 - CJK UNIFIED IDEOGRAPH-4E8C - // U+10302 - 4 code units in UTF8, 2 in UTF16 - OLD ITALIC LETTER KE - // - -#define UNICODE_U00FC "\xc3\xbc" -#define UNICODE_U4E8C "\xe4\xba\x8c" -#define UNICODE_U10302 "\xf0\x90\x8c\x82" -#define TEST_UNICODE_IDENTIFIER UNICODE_U00FC UNICODE_U4E8C UNICODE_U10302 - - original = - "class Foo {\n" - " void @" TEST_UNICODE_IDENTIFIER "();\n" - "};\n"; - ; - expected = original; - expected += - "\n" - "void Foo::" TEST_UNICODE_IDENTIFIER "()\n" - "{\n" - "\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - -#undef UNICODE_U00FC -#undef UNICODE_U4E8C -#undef UNICODE_U10302 -#undef TEST_UNICODE_IDENTIFIER - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclTemplateClass() -{ - QByteArray original = - "template<class T>\n" - "class Foo\n" - "{\n" - " void fun@c1();\n" - " void func2();\n" - "};\n\n" - "template<class T>\n" - "void Foo<T>::func2() {}\n"; - QByteArray expected = - "template<class T>\n" - "class Foo\n" - "{\n" - " void func1();\n" - " void func2();\n" - "};\n\n" - "template<class T>\n" - "void Foo<T>::func1()\n" - "{\n" - "\n" - "}\n\n" - "template<class T>\n" - "void Foo<T>::func2() {}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testInsertDefFromDeclTemplateClassWithValueParam() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original = - "template<typename T, int size> struct MyArray {};\n" - "MyArray<int, 1> @foo();"; - QByteArray expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - original = "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n\n" - "MyArray<int, 1> foo()\n" - "{\n\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclTemplateFunction() -{ - QByteArray original = - "class Foo\n" - "{\n" - " template<class T>\n" - " void fun@c();\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " template<class T>\n" - " void fun@c();\n" - "};\n" - "\n" - "template<class T>\n" - "void Foo::func()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testInsertDefFromDeclTemplateClassAndTemplateFunction() -{ - QByteArray original = - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " T fun@c(U u);\n" - "};\n"; - QByteArray expected = - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " T fun@c(U u);\n" - "};\n" - "\n" - "template<class T>\n" - "template<class U>\n" - "T Foo<T>::func(U u)\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testInsertDefFromDeclTemplateClassAndFunctionInsideNamespace() -{ - QByteArray original = - "namespace N {\n" - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " T fun@c(U u);\n" - "};\n" - "}\n"; - QByteArray expected = - "namespace N {\n" - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " T fun@c(U u);\n" - "};\n" - "\n" - "template<class T>\n" - "template<class U>\n" - "T Foo<T>::func(U u)\n" - "{\n" - "\n" - "}\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testInsertDefFromDeclFunctionWithSignedUnsignedArgument() -{ - QByteArray original; - QByteArray expected; - InsertDefFromDecl factory; - - original =R"--( -class myclass -{ - myc@lass(QVector<signed> g); - myclass(QVector<unsigned> g); -} -)--"; - expected =R"--( -class myclass -{ - myclass(QVector<signed> g); - myclass(QVector<unsigned> g); -} - -myclass::myclass(QVector<signed int> g) -{ - -} -)--"; - - QuickFixOperationTest(singleDocument(original, expected), &factory); - - original =R"--( -class myclass -{ - myclass(QVector<signed> g); - myc@lass(QVector<unsigned> g); -} -)--"; - expected =R"--( -class myclass -{ - myclass(QVector<signed> g); - myclass(QVector<unsigned> g); -} - -myclass::myclass(QVector<unsigned int> g) -{ - -} -)--"; - - QuickFixOperationTest(singleDocument(original, expected), &factory); - - original =R"--( -class myclass -{ - unsigned f@oo(unsigned); -} -)--"; - expected =R"--( -class myclass -{ - unsigned foo(unsigned); -} - -unsigned int myclass::foo(unsigned int) -{ - -} -)--"; - QuickFixOperationTest(singleDocument(original, expected), &factory); - - original =R"--( -class myclass -{ - signed f@oo(signed); -} -)--"; - expected =R"--( -class myclass -{ - signed foo(signed); -} - -signed int myclass::foo(signed int) -{ - -} -)--"; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testInsertDefFromDeclNotTriggeredForFriendFunc() -{ - const QByteArray contents = - "class Foo\n" - "{\n" - " friend void f@unc();\n" - "};\n" - "\n"; - - InsertDefFromDecl factory; - QuickFixOperationTest(singleDocument(contents, ""), &factory); -} - -void QuickfixTest::testInsertDefFromDeclMinimalFunctionParameterType() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = R"( -class C { - typedef int A; - A @foo(A); -}; -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -C::A C::foo(A) -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); - - testDocuments.clear(); - // Header File - original = R"( -namespace N { - struct S; - S @foo(const S &s); -}; -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -N::S N::foo(const S &s) -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefFromDeclAliasTemplateAsReturnType() -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - - // Header File - original = R"( -struct foo { - struct foo2 { - template <typename T> using MyType = T; - MyType<int> @bar(); - }; -}; -)"; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = R"( -#include "file.h" -)"; - expected = R"( -#include "file.h" - -foo::foo2::MyType<int> foo::foo2::bar() -{ - -} -)"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDefFromDecl factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertDefsFromDecls_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - QTest::addColumn<int>("mode"); - - QByteArray origHeader = R"( -namespace N { -class @C -{ -public: - friend void ignoredFriend(); - void ignoredImplemented() {}; - void ignoredImplemented2(); // Below - void ignoredImplemented3(); // In cpp file - void funcNotSelected(); - void funcInline(); - void funcBelow(); - void funcCppFile(); - -signals: - void ignoredSignal(); -}; - -inline void C::ignoredImplemented2() {} - -} // namespace N)"; - QByteArray origSource = R"( -#include "file.h" - -namespace N { - -void C::ignoredImplemented3() {} - -} // namespace N)"; - - QByteArray expectedHeader = R"( -namespace N { -class C -{ -public: - friend void ignoredFriend(); - void ignoredImplemented() {}; - void ignoredImplemented2(); // Below - void ignoredImplemented3(); // In cpp file - void funcNotSelected(); - void funcInline() - { - - } - void funcBelow(); - void funcCppFile(); - -signals: - void ignoredSignal(); -}; - -inline void C::ignoredImplemented2() {} - -inline void C::funcBelow() -{ - -} - -} // namespace N)"; - QByteArray expectedSource = R"( -#include "file.h" - -namespace N { - -void C::ignoredImplemented3() {} - -void C::funcCppFile() -{ - -} - -} // namespace N)"; - QTest::addRow("normal case") - << QByteArrayList{origHeader, expectedHeader} - << QByteArrayList{origSource, expectedSource} - << int(InsertDefsFromDecls::Mode::Alternating); - QTest::addRow("aborted dialog") - << QByteArrayList{origHeader, origHeader} - << QByteArrayList{origSource, origSource} - << int(InsertDefsFromDecls::Mode::Off); - - origHeader = R"( - namespace N { - class @C - { - public: - friend void ignoredFriend(); - void ignoredImplemented() {}; - void ignoredImplemented2(); // Below - void ignoredImplemented3(); // In cpp file - - signals: - void ignoredSignal(); - }; - - inline void C::ignoredImplemented2() {} - - } // namespace N)"; - QTest::addRow("no candidates") - << QByteArrayList{origHeader, origHeader} - << QByteArrayList{origSource, origSource} - << int(InsertDefsFromDecls::Mode::Alternating); - - origHeader = R"( - namespace N { - class @C - { - public: - friend void ignoredFriend(); - void ignoredImplemented() {}; - - signals: - void ignoredSignal(); - }; - } // namespace N)"; - QTest::addRow("no member functions") - << QByteArrayList{origHeader, ""} - << QByteArrayList{origSource, ""} - << int(InsertDefsFromDecls::Mode::Alternating); -} - -void QuickfixTest::testInsertDefsFromDecls() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - QFETCH(int, mode); - - QList<TestDocumentPtr> testDocuments({ - CppTestDocument::create("file.h", headers.at(0), headers.at(1)), - CppTestDocument::create("file.cpp", sources.at(0), sources.at(1))}); - InsertDefsFromDecls factory; - factory.setMode(static_cast<InsertDefsFromDecls::Mode>(mode)); - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testInsertAndFormatDefsFromDecls() -{ - if (!isClangFormatPresent()) - QSKIP("This test reqires ClangFormat"); - - const QByteArray origHeader = R"( -class @C -{ -public: - void func1 (int const &i); - void func2 (double const d); -}; -)"; - const QByteArray origSource = R"( -#include "file.h" -)"; - - const QByteArray expectedSource = R"( -#include "file.h" - -void C::func1 (int const &i) -{ - -} - -void C::func2 (double const d) -{ - -} -)"; - - const QByteArray clangFormatSettings = R"( -BreakBeforeBraces: Allman -QualifierAlignment: Right -SpaceBeforeParens: Always -)"; - - const QList<TestDocumentPtr> testDocuments({ - CppTestDocument::create("file.h", origHeader, origHeader), - CppTestDocument::create("file.cpp", origSource, expectedSource)}); - InsertDefsFromDecls factory; - factory.setMode(InsertDefsFromDecls::Mode::Impl); - CppCodeStylePreferences * const prefs = CppToolsSettings::cppCodeStyle(); - const CppCodeStyleSettings settings = prefs->codeStyleSettings(); - CppCodeStyleSettings tempSettings = settings; - tempSettings.forceFormatting = true; - prefs->setCodeStyleSettings(tempSettings); - QuickFixOperationTest(testDocuments, &factory, {}, {}, {}, clangFormatSettings); - prefs->setCodeStyleSettings(settings); -} - -QList<TestDocumentPtr> singleHeader(const QByteArray &original, const QByteArray &expected) -{ - return {CppTestDocument::create("file.h", original, expected)}; -} - -void QuickfixTest::testInsertDefOutsideFromDeclTemplateClassAndTemplateFunction() -{ - QByteArray original = - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " void fun@c();\n" - "};\n"; - QByteArray expected = - "template<class T>" - "class Foo\n" - "{\n" - " template<class U>\n" - " void fun@c();\n" - "};\n" - "\n" - "template<class T>\n" - "template<class U>\n" - "inline void Foo<T>::func()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - factory.m_defPosOutsideClass = true; - QuickFixOperationTest(singleHeader(original, expected), &factory); -} - -void QuickfixTest::testInsertDefOutsideFromDeclTemplateClass() -{ - QByteArray original = - "template<class T>" - "class Foo\n" - "{\n" - " void fun@c();\n" - "};\n"; - QByteArray expected = - "template<class T>" - "class Foo\n" - "{\n" - " void fun@c();\n" - "};\n" - "\n" - "template<class T>\n" - "inline void Foo<T>::func()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - factory.m_defPosOutsideClass = true; - QuickFixOperationTest(singleHeader(original, expected), &factory); -} - -void QuickfixTest::testInsertDefOutsideFromDeclTemplateFunction() -{ - QByteArray original = - "class Foo\n" - "{\n" - " template<class U>\n" - " void fun@c();\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " template<class U>\n" - " void fun@c();\n" - "};\n" - "\n" - "template<class U>\n" - "inline void Foo::func()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - factory.m_defPosOutsideClass = true; - QuickFixOperationTest(singleHeader(original, expected), &factory); -} - -void QuickfixTest::testInsertDefOutsideFromDeclFunction() -{ - QByteArray original = - "class Foo\n" - "{\n" - " void fun@c();\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " void fun@c();\n" - "};\n" - "\n" - "inline void Foo::func()\n" - "{\n" - "\n" - "}\n"; - - InsertDefFromDecl factory; - factory.m_defPosOutsideClass = true; - QuickFixOperationTest(singleHeader(original, expected), &factory); -} - -// Function for one of InsertDeclDef section cases -void insertToSectionDeclFromDef(const QByteArray §ion, int sectionIndex) -{ - QList<TestDocumentPtr> testDocuments; - - QByteArray original; - QByteArray expected; - QByteArray sectionString = section + ":\n"; - if (sectionIndex == 4) - sectionString.clear(); - - // Header File - original = - "class Foo\n" - "{\n" - "};\n"; - expected = - "class Foo\n" - "{\n" - + sectionString + - " Foo();\n" - "@};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "\n" - "Foo::Foo@()\n" - "{\n" - "}\n" - ; - expected = original; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - InsertDeclFromDef factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), sectionIndex); -} - -/// Check from source file: Insert in header file. -void QuickfixTest::testInsertDeclFromDef() -{ - insertToSectionDeclFromDef("public", 0); - insertToSectionDeclFromDef("public slots", 1); - insertToSectionDeclFromDef("protected", 2); - insertToSectionDeclFromDef("protected slots", 3); - insertToSectionDeclFromDef("private", 4); - insertToSectionDeclFromDef("private slots", 5); -} - -void QuickfixTest::testInsertDeclFromDefTemplateFuncTypename() -{ - QByteArray original = - "class Foo\n" - "{\n" - "};\n" - "\n" - "template<class T>\n" - "void Foo::fu@nc() {}\n"; - - QByteArray expected = - "class Foo\n" - "{\n" - "public:\n" - " template<class T>\n" - " void func();\n" - "};\n" - "\n" - "template<class T>\n" - "void Foo::fu@nc() {}\n"; - - InsertDeclFromDef factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, {}, 0); -} - -void QuickfixTest::testInsertDeclFromDefTemplateFuncInt() -{ - QByteArray original = - "class Foo\n" - "{\n" - "};\n" - "\n" - "template<int N>\n" - "void Foo::fu@nc() {}\n"; - - QByteArray expected = - "class Foo\n" - "{\n" - "public:\n" - " template<int N>\n" - " void func();\n" - "};\n" - "\n" - "template<int N>\n" - "void Foo::fu@nc() {}\n"; - - InsertDeclFromDef factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, {}, 0); -} - -void QuickfixTest::testInsertDeclFromDefTemplateReturnType() -{ - QByteArray original = - "class Foo\n" - "{\n" - "};\n" - "\n" - "std::vector<int> Foo::fu@nc() const {}\n"; - - QByteArray expected = - "class Foo\n" - "{\n" - "public:\n" - " std::vector<int> func() const;\n" - "};\n" - "\n" - "std::vector<int> Foo::func() const {}\n"; - - InsertDeclFromDef factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, {}, 0); -} - -void QuickfixTest::testInsertDeclFromDefNotTriggeredForTemplateFunc() -{ - QByteArray contents = - "class Foo\n" - "{\n" - " template<class T>\n" - " void func();\n" - "};\n" - "\n" - "template<class T>\n" - "void Foo::fu@nc() {}\n"; - - InsertDeclFromDef factory; - QuickFixOperationTest(singleDocument(contents, ""), &factory); -} - -void QuickfixTest::testAddIncludeForUndefinedIdentifier_data() -{ - QTest::addColumn<QString>("headerPath"); - QTest::addColumn<QuickFixTestDocuments>("testDocuments"); - QTest::addColumn<int>("refactoringOperationIndex"); - QTest::addColumn<QString>("includeForTestFactory"); - - const int firstRefactoringOperation = 0; - const int secondRefactoringOperation = 1; - - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "class Foo {};\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " Fo@o foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " Foo foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onSimpleName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "namespace N { class Foo {}; }\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Fo@o foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Foo foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onNameOfQualifiedName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "namespace N { class Foo {}; }\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " @N::Foo foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Foo foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onBaseOfQualifiedName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "class Foo { static void bar() {} };\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " @Foo::bar();\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " Foo::bar();\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onBaseOfQualifiedClassName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "template <typename T> class Foo { static void bar() {} };\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " @Foo<int>::bar();\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " Foo<int>::bar();\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onBaseOfQualifiedTemplateClassName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "namespace N { template <typename T> class Foo {}; }\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " @N::Foo<Bar> foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Foo<Bar> foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onTemplateName") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "namespace N { template <typename T> class Foo {}; }\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Bar<@Foo> foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " N::Bar<Foo> foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("onTemplateNameInsideArguments") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "class Foo {};\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "class Foo;\n" - "\n" - "void f()\n" - "{\n" - " @Foo foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "class Foo;\n" - "\n" - "void f()\n" - "{\n" - " Foo foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("withForwardDeclaration") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "template<class T> class Foo {};\n"; - expected = original; - testDocuments << CppTestDocument::create("afile.h", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "template<class T> class Foo;\n" - "\n" - "void f()\n" - "{\n" - " @Foo foo;\n" - "}\n" - ; - expected = - "#include \"afile.h\"\n" - "#include \"header.h\"\n" - "\n" - "template<class T> class Foo;\n" - "\n" - "void f()\n" - "{\n" - " Foo foo;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("withForwardDeclaration2") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - // Header File - original = "template<class T> class QMyClass {};\n"; - expected = original; - testDocuments << CppTestDocument::create("qmyclass.h", original, expected); - - // Forward Header File - original = "#include \"qmyclass.h\"\n"; - expected = original; - testDocuments << CppTestDocument::create("QMyClass", original, expected); - - // Source File - original = - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " @QMyClass c;\n" - "}\n" - ; - expected = - "#include \"QMyClass\"\n" - "#include \"header.h\"\n" - "\n" - "void f()\n" - "{\n" - " QMyClass c;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("afile.cpp", original, expected); - QTest::newRow("withForwardHeader") - << TestIncludePaths::globalIncludePath() - << testDocuments << secondRefactoringOperation << ""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "void @f();\n" - "#include \"file.moc\";\n" - ; - expected = - "#include \"file.h\"\n" - "\n" - "void f();\n" - "#include \"file.moc\";\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("insertingIgnoreMoc") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"y.h\"\n" - "#include \"z.h\"\n" - "\n@" - ; - expected = - "#include \"file.h\"\n" - "#include \"y.h\"\n" - "#include \"z.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("insertingSortingTop") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"a.h\"\n" - "#include \"z.h\"\n" - "\n@" - ; - expected = - "#include \"a.h\"\n" - "#include \"file.h\"\n" - "#include \"z.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("insertingSortingMiddle") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "\n@" - ; - expected = - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"file.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("insertingSortingBottom") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"b.h\"\n" - "#include \"a.h\"\n" - "\n@" - ; - expected = - "#include \"b.h\"\n" - "#include \"a.h\"\n" - "#include \"file.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_appendToUnsorted") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include <a.h>\n" - "#include <b.h>\n" - "\n@" - ; - expected = - "#include \"file.h\"\n" - "\n" - "#include <a.h>\n" - "#include <b.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_firstLocalIncludeAtFront") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "\n" - "void @f();\n" - ; - expected = - "#include \"a.h\"\n" - "#include \"b.h\"\n" - "\n" - "#include <file.h>\n" - "\n" - "void f();\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("firstGlobalIncludeAtBack") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "<file.h>"; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"prefixa.h\"\n" - "#include \"prefixb.h\"\n" - "\n" - "#include \"foo.h\"\n" - "\n@" - ; - expected = - "#include \"prefixa.h\"\n" - "#include \"prefixb.h\"\n" - "#include \"prefixc.h\"\n" - "\n" - "#include \"foo.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_preferGroupWithLongerMatchingPrefix") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"prefixc.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"lib/file.h\"\n" - "#include \"lib/fileother.h\"\n" - "\n@" - ; - expected = - "#include \"lib/file.h\"\n" - "#include \"lib/fileother.h\"\n" - "\n" - "#include \"file.h\"\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_newGroupIfOnlyDifferentIncludeDirs") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include <lib/file.h>\n" - "#include <otherlib/file.h>\n" - "#include <utils/file.h>\n" - "\n@" - ; - expected = - "#include <firstlib/file.h>\n" - "#include <lib/file.h>\n" - "#include <otherlib/file.h>\n" - "#include <utils/file.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedDirsSorted") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "<firstlib/file.h>"; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include <otherlib/file.h>\n" - "#include <lib/file.h>\n" - "#include <utils/file.h>\n" - "\n@" - ; - expected = - "#include <otherlib/file.h>\n" - "#include <lib/file.h>\n" - "#include <utils/file.h>\n" - "#include <lastlib/file.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedDirsUnsorted") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "<lastlib/file.h>"; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"a.h\"\n" - "#include <global.h>\n" - "\n@" - ; - expected = - "#include \"a.h\"\n" - "#include \"z.h\"\n" - "#include <global.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedIncludeTypes1") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"z.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"z.h\"\n" - "#include <global.h>\n" - "\n@" - ; - expected = - "#include \"a.h\"\n" - "#include \"z.h\"\n" - "#include <global.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedIncludeTypes2") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"a.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"z.h\"\n" - "#include <global.h>\n" - "\n@" - ; - expected = - "#include \"z.h\"\n" - "#include \"lib/file.h\"\n" - "#include <global.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedIncludeTypes3") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"lib/file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#include \"z.h\"\n" - "#include <global.h>\n" - "\n@" - ; - expected = - "#include \"z.h\"\n" - "#include <global.h>\n" - "#include <lib/file.h>\n" - "\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_mixedIncludeTypes4") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "<lib/file.h>"; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "void @f();\n" - ; - expected = - "#include \"file.h\"\n" - "\n" - "void f();\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_noinclude") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "#ifndef FOO_H\n" - "#define FOO_H\n" - "void @f();\n" - "#endif\n" - ; - expected = - "#ifndef FOO_H\n" - "#define FOO_H\n" - "\n" - "#include \"file.h\"\n" - "\n" - "void f();\n" - "#endif\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_onlyIncludeGuard") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "\n" - "// comment\n" - "\n" - "void @f();\n" - ; - expected = - "\n" - "// comment\n" - "\n" - "#include \"file.h\"\n" - "\n" - "void @f();\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_veryFirstIncludeCppStyleCommentOnTop") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "\n" - "/*\n" - " comment\n" - " */\n" - "\n" - "void @f();\n" - ; - expected = - "\n" - "/*\n" - " comment\n" - " */\n" - "\n" - "#include \"file.h\"\n" - "\n" - "void @f();\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_veryFirstIncludeCStyleCommentOnTop") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << "\"file.h\""; - testDocuments.clear(); - - // ------------------------------------------------------------------------------------------- - - original = - "@QDir dir;\n" - ; - expected = - "#include <QDir>\n" - "\n" - "QDir dir;\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_checkQSomethingInQtIncludePaths") - << TestIncludePaths::globalQtCoreIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - original = - "std::s@tring s;\n" - ; - expected = - "#include <string>\n" - "\n" - "std::string s;\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - QTest::newRow("inserting_std::string") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - original = "class A{};"; - testDocuments << CppTestDocument::create("a.h", original, original); - original = "class B{};"; - testDocuments << CppTestDocument::create("b.h", original, original); - original = - "#include \"b.h\"\n" - "@A a;\n" - "B b;"; - expected = - "#include \"b.h\"\n\n" - "#include \"a.h\"\n" - "A a;\n" - "B b;"; - testDocuments << CppTestDocument::create("b.cpp", original, expected); - QTest::newRow("preserve first header") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); - - original = "class C{};"; - testDocuments << CppTestDocument::create("c.h", original, original); - original = "class B{};"; - testDocuments << CppTestDocument::create("b.h", original, original); - original = - "#include \"c.h\"\n" - "C c;\n" - "@B b;"; - expected = - "#include \"b.h\"\n" - "#include \"c.h\"\n" - "C c;\n" - "B b;"; - testDocuments << CppTestDocument::create("x.cpp", original, expected); - QTest::newRow("do not preserve first header") - << TestIncludePaths::globalIncludePath() - << testDocuments << firstRefactoringOperation << ""; - testDocuments.clear(); -} - -void QuickfixTest::testAddIncludeForUndefinedIdentifier() -{ - QFETCH(QString, headerPath); - QFETCH(QuickFixTestDocuments, testDocuments); - QFETCH(int, refactoringOperationIndex); - QFETCH(QString, includeForTestFactory); - - TemporaryDir temporaryDir; - QVERIFY(temporaryDir.isValid()); - for (const TestDocumentPtr &testDocument : std::as_const(testDocuments)) - testDocument->setBaseDirectory(temporaryDir.path()); - - QScopedPointer<CppQuickFixFactory> factory; - if (includeForTestFactory.isEmpty()) - factory.reset(new AddIncludeForUndefinedIdentifier); - else - factory.reset(new AddIncludeForUndefinedIdentifierTestFactory(includeForTestFactory)); - - QuickFixOperationTest::run(testDocuments, factory.data(), headerPath, - refactoringOperationIndex); -} - -void QuickfixTest::testAddIncludeForUndefinedIdentifierNoDoubleQtHeaderInclude() -{ - TemporaryDir temporaryDir; - QVERIFY(temporaryDir.isValid()); - - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - const QByteArray base = temporaryDir.path().toUtf8(); - - // This file makes the QDir definition available so that locator finds it. - original = expected = "#include <QDir>\n" - "void avoidBeingRecognizedAsForwardingHeader();"; - testDocuments << CppTestDocument::create(base + "/fileUsingQDir.cpp", original, expected); - - original = expected = "@QDir dir;\n"; - testDocuments << CppTestDocument::create(base + "/fileWantsToUseQDir.cpp", original, expected); - - AddIncludeForUndefinedIdentifier factory; - const QStringList expectedOperations = QStringList("Add #include <QDir>"); - QuickFixOfferedOperationsTest(testDocuments, &factory, ProjectExplorer::toUserHeaderPaths( - QStringList{TestIncludePaths::globalQtCoreIncludePath()}), expectedOperations); -} - -void QuickfixTest::testAddForwardDeclForUndefinedIdentifier_data() -{ - QTest::addColumn<QuickFixTestDocuments>("testDocuments"); - QTest::addColumn<QString>("symbol"); - QTest::addColumn<int>("symbolPos"); - - QByteArray original; - QByteArray expected; - - original = - "#pragma once\n" - "\n" - "void f(const Blu@bb &b)\n" - "{\n" - "}\n" - ; - expected = - "#pragma once\n" - "\n" - "\n" - "class Blubb;\n" - "void f(const Blubb &b)\n" - "{\n" - "}\n" - ; - QTest::newRow("unqualified symbol") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "Blubb" << original.indexOf('@'); - - original = - "#pragma once\n" - "\n" - "namespace NS {\n" - "class C;\n" - "}\n" - "void f(const NS::Blu@bb &b)\n" - "{\n" - "}\n" - ; - expected = - "#pragma once\n" - "\n" - "namespace NS {\n" - "\n" - "class Blubb;\n" - "class C;\n" - "}\n" - "void f(const NS::Blubb &b)\n" - "{\n" - "}\n" - ; - QTest::newRow("qualified symbol, full namespace present") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "NS::Blubb" << original.indexOf('@'); - - original = - "#pragma once\n" - "\n" - "namespace NS {\n" - "class C;\n" - "}\n" - "void f(const NS::NS2::Blu@bb &b)\n" - "{\n" - "}\n" - ; - expected = - "#pragma once\n" - "\n" - "namespace NS {\n" - "\n" - "namespace NS2 { class Blubb; }\n" - "class C;\n" - "}\n" - "void f(const NS::NS2::Blubb &b)\n" - "{\n" - "}\n" - ; - QTest::newRow("qualified symbol, partial namespace present") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "NS::NS2::Blubb" << original.indexOf('@'); - - original = - "#pragma once\n" - "\n" - "namespace NS {\n" - "class C;\n" - "}\n" - "void f(const NS2::Blu@bb &b)\n" - "{\n" - "}\n" - ; - expected = - "#pragma once\n" - "\n" - "\n" - "namespace NS2 { class Blubb; }\n" - "namespace NS {\n" - "class C;\n" - "}\n" - "void f(const NS2::Blubb &b)\n" - "{\n" - "}\n" - ; - QTest::newRow("qualified symbol, other namespace present") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "NS2::Blubb" << original.indexOf('@'); - - original = - "#pragma once\n" - "\n" - "void f(const NS2::Blu@bb &b)\n" - "{\n" - "}\n" - ; - expected = - "#pragma once\n" - "\n" - "\n" - "namespace NS2 { class Blubb; }\n" - "void f(const NS2::Blubb &b)\n" - "{\n" - "}\n" - ; - QTest::newRow("qualified symbol, no namespace present") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "NS2::Blubb" << original.indexOf('@'); - - original = - "#pragma once\n" - "\n" - "void f(const NS2::Blu@bb &b)\n" - "{\n" - "}\n" - "namespace NS2 {}\n" - ; - expected = - "#pragma once\n" - "\n" - "\n" - "namespace NS2 { class Blubb; }\n" - "void f(const NS2::Blubb &b)\n" - "{\n" - "}\n" - "namespace NS2 {}\n" - ; - QTest::newRow("qualified symbol, existing namespace after symbol") - << QuickFixTestDocuments{CppTestDocument::create("theheader.h", original, expected)} - << "NS2::Blubb" << original.indexOf('@'); -} - -void QuickfixTest::testAddForwardDeclForUndefinedIdentifier() -{ - QFETCH(QuickFixTestDocuments, testDocuments); - QFETCH(QString, symbol); - QFETCH(int, symbolPos); - - TemporaryDir temporaryDir; - QVERIFY(temporaryDir.isValid()); - testDocuments.first()->setBaseDirectory(temporaryDir.path()); - - QScopedPointer<CppQuickFixFactory> factory( - new AddForwardDeclForUndefinedIdentifierTestFactory(symbol, symbolPos)); - QuickFixOperationTest::run({testDocuments}, factory.data(), ".", 0); -} - -/// Check: Move definition from header to cpp. -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCpp() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - " inline int numbe@r() const\n" - " {\n" - " return 5;\n" - " }\n" - "\n" - " void bar();\n" - "};\n"; - expected = - "class Foo {\n" - " int number() const;\n" - "\n" - " void bar();\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int Foo::number() const\n" - "{\n" - " return 5;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCppStatic() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - " static inline int numbe@r() const\n" - " {\n" - " return 5;\n" - " }\n" - "\n" - " void bar();\n" - "};\n"; - expected = - "class Foo {\n" - " static int number() const;\n" - "\n" - " void bar();\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int Foo::number() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCppWithInlinePartOfName() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - " static inline int numbe@r_inline () const\n" - " {\n" - " return 5;\n" - " }\n" - "\n" - " void bar();\n" - "};\n"; - expected = - "class Foo {\n" - " static int number_inline () const;\n" - "\n" - " void bar();\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int Foo::number_inline() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMixedQualifiers() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = R"( -struct Base { - virtual auto func() const && noexcept -> void = 0; -}; -struct Derived : public Base { - auto @func() const && noexcept -> void override {} -};)"; - expected = R"( -struct Base { - virtual auto func() const && noexcept -> void = 0; -}; -struct Derived : public Base { - auto func() const && noexcept -> void override; -};)"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = "#include \"file.h\"\n"; - expected = R"DELIM(#include "file.h" - -auto Derived::func() const && noexcept -> void {} -)DELIM"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCppInsideNS() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace SomeNamespace {\n" - "class Foo {\n" - " int ba@r()\n" - " {\n" - " return 5;\n" - " }\n" - "};\n" - "}\n"; - expected = - "namespace SomeNamespace {\n" - "class Foo {\n" - " int ba@r();\n" - "};\n" - "}\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "namespace SomeNamespace {\n" - "\n" - "}\n"; - expected = - "#include \"file.h\"\n" - "namespace SomeNamespace {\n" - "\n" - "int Foo::bar()\n" - "{\n" - " return 5;\n" - "}\n" - "\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move definition outside class -void QuickfixTest::testMoveFuncDefOutsideMemberFuncOutside1() -{ - QByteArray original = - "class Foo {\n" - " void f1();\n" - " inline int f2@() const\n" - " {\n" - " return 1;\n" - " }\n" - " void f3();\n" - " void f4();\n" - "};\n" - "\n" - "void Foo::f4() {}\n"; - QByteArray expected = - "class Foo {\n" - " void f1();\n" - " int f2@() const;\n" - " void f3();\n" - " void f4();\n" - "};\n" - "\n" - "int Foo::f2() const\n" - "{\n" - " return 1;\n" - "}\n" - "\n" - "void Foo::f4() {}\n"; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check: Move definition outside class -void QuickfixTest::testMoveFuncDefOutsideMemberFuncOutside2() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - " void f1();\n" - " int f2@()\n" - " {\n" - " return 1;\n" - " }\n" - " void f3();\n" - "};\n"; - expected = - "class Foo {\n" - " void f1();\n" - " int f2();\n" - " void f3();\n" - "};\n" - "\n" - "inline int Foo::f2()\n" - "{\n" - " return 1;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "void Foo::f1() {}\n" - "void Foo::f3() {}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 1); -} - -/// Check: Move definition from header to cpp (with namespace). -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCppNS() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace MyNs {\n" - "class Foo {\n" - " inline int numbe@r() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n" - "}\n"; - expected = - "namespace MyNs {\n" - "class Foo {\n" - " int number() const;\n" - "};\n" - "}\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int MyNs::Foo::number() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move definition from header to cpp (with namespace + using). -void QuickfixTest::testMoveFuncDefOutsideMemberFuncToCppNSUsing() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace MyNs {\n" - "class Foo {\n" - " inline int numbe@r() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n" - "}\n"; - expected = - "namespace MyNs {\n" - "class Foo {\n" - " int number() const;\n" - "};\n" - "}\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "using namespace MyNs;\n"; - expected = - "#include \"file.h\"\n" - "using namespace MyNs;\n" - "\n" - "int Foo::number() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move definition outside class with Namespace -void QuickfixTest::testMoveFuncDefOutsideMemberFuncOutsideWithNs() -{ - QByteArray original = - "namespace MyNs {\n" - "class Foo {\n" - " inline int numbe@r() const\n" - " {\n" - " return 5;\n" - " }\n" - "};}\n"; - QByteArray expected = - "namespace MyNs {\n" - "class Foo {\n" - " int number() const;\n" - "};\n" - "\n" - "int Foo::number() const\n" - "{\n" - " return 5;\n" - "}\n" - "\n}\n"; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check: Move free function from header to cpp. -void QuickfixTest::testMoveFuncDefOutsideFreeFuncToCpp() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "int numbe@r() const\n" - "{\n" - " return 5;\n" - "}\n"; - expected = - "int number() const;\n" - ; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int number() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move free function from header to cpp (with namespace). -void QuickfixTest::testMoveFuncDefOutsideFreeFuncToCppNS() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "namespace MyNamespace {\n" - "int numbe@r() const\n" - "{\n" - " return 5;\n" - "}\n" - "}\n"; - expected = - "namespace MyNamespace {\n" - "int number() const;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int MyNamespace::number() const\n" - "{\n" - " return 5;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move Ctor with member initialization list (QTCREATORBUG-9157). -void QuickfixTest::testMoveFuncDefOutsideCtorWithInitialization1() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {\n" - "public:\n" - " Fo@o() : a(42), b(3.141) {}\n" - "private:\n" - " int a;\n" - " float b;\n" - "};\n"; - expected = - "class Foo {\n" - "public:\n" - " Foo();\n" - "private:\n" - " int a;\n" - " float b;\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original ="#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "Foo::Foo() : a(42), b(3.141) {}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move Ctor with member initialization list (QTCREATORBUG-9462). -void QuickfixTest::testMoveFuncDefOutsideCtorWithInitialization2() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo\n" - "{\n" - "public:\n" - " Fo@o() : member(2)\n" - " {\n" - " }\n" - "\n" - " int member;\n" - "};\n"; - - expected = - "class Foo\n" - "{\n" - "public:\n" - " Foo();\n" - "\n" - " int member;\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original ="#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "Foo::Foo() : member(2)\n" - "{\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check if definition is inserted right after class for move definition outside -void QuickfixTest::testMoveFuncDefOutsideAfterClass() -{ - QList<TestDocumentPtr> testDocuments; - 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" - "inline void Foo::a() {}\n" - "\n" - "class Bar {};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "\n" - "Foo::Foo()\n" - "{\n\n" - "}\n"; - expected = original; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 1); -} - -/// Check if whitespace is respected for operator functions -void QuickfixTest::testMoveFuncDefOutsideRespectWsInOperatorNames1() -{ - QByteArray original = - "class Foo\n" - "{\n" - " Foo &opera@tor =() {}\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " Foo &operator =();\n" - "};\n" - "\n" - "Foo &Foo::operator =() {}\n" - ; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check if whitespace is respected for operator functions -void QuickfixTest::testMoveFuncDefOutsideRespectWsInOperatorNames2() -{ - QByteArray original = - "class Foo\n" - "{\n" - " Foo &opera@tor=() {}\n" - "};\n"; - QByteArray expected = - "class Foo\n" - "{\n" - " Foo &operator=();\n" - "};\n" - "\n" - "Foo &Foo::operator=() {}\n" - ; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMacroUses() -{ - QByteArray original = - "#define CONST const\n" - "#define VOLATILE volatile\n" - "class Foo\n" - "{\n" - " int fu@nc(int a, int b) CONST VOLATILE\n" - " {\n" - " return 42;\n" - " }\n" - "};\n"; - QByteArray expected = - "#define CONST const\n" - "#define VOLATILE volatile\n" - "class Foo\n" - "{\n" - " int func(int a, int b) CONST VOLATILE;\n" - "};\n" - "\n" - "\n" - // const volatile become lowercase: QTCREATORBUG-12620 - "int Foo::func(int a, int b) const volatile\n" - "{\n" - " return 42;\n" - "}\n" - ; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, - ProjectExplorer::HeaderPaths(), 0, "QTCREATORBUG-12314"); -} - -void QuickfixTest::testMoveFuncDefOutsideTemplate() -{ - QByteArray original = - "template<class T>\n" - "class Foo { void fu@nc() {} };\n"; - QByteArray expected = - "template<class T>\n" - "class Foo { void fu@nc(); };\n" - "\n" - "template<class T>\n" - "void Foo<T>::func() {}\n"; - ; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideMemberFunctionTemplate() -{ - const QByteArray original = R"( -struct S { - template<typename In> - void @foo(In in) { (void)in; } -}; -)"; - const QByteArray expected = R"( -struct S { - template<typename In> - void foo(In in); -}; - -template<typename In> -void S::foo(In in) { (void)in; } -)"; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideTemplateSpecializedClass() -{ - QByteArray original = R"( -template<typename T> class base {}; -template<> -class base<int> -{ -public: - void @bar() {} -}; -)"; - QByteArray expected = R"( -template<typename T> class base {}; -template<> -class base<int> -{ -public: - void bar(); -}; - -void base<int>::bar() {} -)"; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testMoveFuncDefOutsideUnnamedTemplate() -{ - QByteArray original = - "template<typename T, typename>\n" - "class Foo { void fu@nc() {} };\n"; - QByteArray expected = - "template<typename T, typename>\n" - "class Foo { void fu@nc(); };\n" - "\n" - "template<typename T, typename T2>\n" - "void Foo<T, T2>::func() {}\n"; - ; - - MoveFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testMoveFuncDefToDecl_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - - QByteArray originalHeader; - QByteArray expectedHeader; - QByteArray originalSource; - QByteArray expectedSource; - - originalHeader = - "class Foo {\n" - " inline int @number() const;\n" - "};\n"; - expectedHeader = - "class Foo {\n" - " inline int number() const {return 5;}\n" - "};\n"; - originalSource = - "#include \"file.h\"\n" - "\n" - "int Foo::num@ber() const {return 5;}\n"; - expectedSource = - "#include \"file.h\"\n" - "\n\n"; - QTest::newRow("member function, two files") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "class Foo {\n" - " inline int @number() const;\n" - "};\n" - "\n" - "int Foo::num@ber() const\n" - "{\n" - " return 5;\n" - "}\n"; - - expectedSource = - "class Foo {\n" - " inline int number() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n\n\n"; - QTest::newRow("member function, one file") << QByteArrayList() - << QByteArrayList{originalSource, expectedSource}; - - originalHeader = - "namespace MyNs {\n" - "class Foo {\n" - " inline int @number() const;\n" - "};\n" - "}\n"; - expectedHeader = - "namespace MyNs {\n" - "class Foo {\n" - " inline int number() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n" - "}\n"; - originalSource = - "#include \"file.h\"\n" - "\n" - "int MyNs::Foo::num@ber() const\n" - "{\n" - " return 5;\n" - "}\n"; - expectedSource = "#include \"file.h\"\n\n\n"; - QTest::newRow("member function, two files, namespace") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalHeader = - "namespace MyNs {\n" - "class Foo {\n" - " inline int numbe@r() const;\n" - "};\n" - "}\n"; - expectedHeader = - "namespace MyNs {\n" - "class Foo {\n" - " inline int number() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n" - "}\n"; - originalSource = - "#include \"file.h\"\n" - "using namespace MyNs;\n" - "\n" - "int Foo::num@ber() const\n" - "{\n" - " return 5;\n" - "}\n"; - expectedSource = - "#include \"file.h\"\n" - "using namespace MyNs;\n" - "\n\n"; - QTest::newRow("member function, two files, namespace with using-directive") - << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "namespace MyNs {\n" - "class Foo {\n" - " inline int @number() const;\n" - "};\n" - "\n" - "int Foo::numb@er() const\n" - "{\n" - " return 5;\n" - "}" - "\n}\n"; - expectedSource = - "namespace MyNs {\n" - "class Foo {\n" - " inline int number() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n\n\n}\n"; - - QTest::newRow("member function, one file, namespace") - << QByteArrayList() << QByteArrayList{originalSource, expectedSource}; - - originalHeader = "int nu@mber() const;\n"; - expectedHeader = - "inline int number() const\n" - "{\n" - " return 5;\n" - "}\n"; - originalSource = - "#include \"file.h\"\n" - "\n" - "\n" - "int numb@er() const\n" - "{\n" - " return 5;\n" - "}\n"; - expectedSource = "#include \"file.h\"\n\n\n\n"; - QTest::newRow("free function") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalHeader = - "namespace MyNamespace {\n" - "int n@umber() const;\n" - "}\n"; - expectedHeader = - "namespace MyNamespace {\n" - "inline int number() const\n" - "{\n" - " return 5;\n" - "}\n" - "}\n"; - originalSource = - "#include \"file.h\"\n" - "\n" - "int MyNamespace::nu@mber() const\n" - "{\n" - " return 5;\n" - "}\n"; - expectedSource = - "#include \"file.h\"\n" - "\n\n"; - QTest::newRow("free function, namespace") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalHeader = - "class Foo {\n" - "public:\n" - " Fo@o();\n" - "private:\n" - " int a;\n" - " float b;\n" - "};\n"; - expectedHeader = - "class Foo {\n" - "public:\n" - " Foo() : a(42), b(3.141) {}\n" - "private:\n" - " int a;\n" - " float b;\n" - "};\n"; - originalSource = - "#include \"file.h\"\n" - "\n" - "Foo::F@oo() : a(42), b(3.141) {}" - ; - expectedSource ="#include \"file.h\"\n\n"; - QTest::newRow("constructor") << QByteArrayList{originalHeader, expectedHeader} - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "struct Foo\n" - "{\n" - " void f@oo();\n" - "} bar;\n" - "void Foo::fo@o()\n" - "{\n" - " return;\n" - "}"; - expectedSource = - "struct Foo\n" - "{\n" - " void foo()\n" - " {\n" - " return;\n" - " }\n" - "} bar;\n"; - QTest::newRow("QTCREATORBUG-10303") << QByteArrayList() - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "struct Base {\n" - " virtual int foo() = 0;\n" - "};\n" - "struct Derived : Base {\n" - " int @foo() override;\n" - "};\n" - "\n" - "int Derived::fo@o()\n" - "{\n" - " return 5;\n" - "}\n"; - expectedSource = - "struct Base {\n" - " virtual int foo() = 0;\n" - "};\n" - "struct Derived : Base {\n" - " int foo() override\n" - " {\n" - " return 5;\n" - " }\n" - "};\n\n\n"; - QTest::newRow("overridden virtual") << QByteArrayList() - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "template<class T>\n" - "class Foo { void @func(); };\n" - "\n" - "template<class T>\n" - "void Foo<T>::fu@nc() {}\n"; - expectedSource = - "template<class T>\n" - "class Foo { void fu@nc() {} };\n\n\n"; - QTest::newRow("class template") << QByteArrayList() - << QByteArrayList{originalSource, expectedSource}; - - originalSource = - "class Foo\n" - "{\n" - " template<class T>\n" - " void @func();\n" - "};\n" - "\n" - "template<class T>\n" - "void Foo::fu@nc() {}\n"; - expectedSource = - "class Foo\n" - "{\n" - " template<class T>\n" - " void func() {}\n" - "};\n\n\n"; - QTest::newRow("function template") << QByteArrayList() - << QByteArrayList{originalSource, expectedSource}; -} - -void QuickfixTest::testMoveFuncDefToDecl() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - - QVERIFY(headers.isEmpty() || headers.size() == 2); - QVERIFY(sources.size() == 2); - - QByteArray &declDoc = !headers.empty() ? headers.first() : sources.first(); - const int declCursorPos = declDoc.indexOf('@'); - QVERIFY(declCursorPos != -1); - const int defCursorPos = sources.first().lastIndexOf('@'); - QVERIFY(defCursorPos != -1); - QVERIFY(declCursorPos != defCursorPos); - - declDoc.remove(declCursorPos, 1); - QList<TestDocumentPtr> testDocuments; - if (!headers.isEmpty()) - testDocuments << CppTestDocument::create("file.h", headers.first(), headers.last()); - testDocuments << CppTestDocument::create("file.cpp", sources.first(), sources.last()); - - MoveFuncDefToDeclPush pushFactory; - QuickFixOperationTest(testDocuments, &pushFactory); - - declDoc.insert(declCursorPos, '@'); - sources.first().remove(defCursorPos, 1); - testDocuments.clear(); - if (!headers.isEmpty()) - testDocuments << CppTestDocument::create("file.h", headers.first(), headers.last()); - testDocuments << CppTestDocument::create("file.cpp", sources.first(), sources.last()); - - MoveFuncDefToDeclPull pullFactory; - QuickFixOperationTest(testDocuments, &pullFactory); -} - -void QuickfixTest::testMoveFuncDefToDeclMacroUses() -{ - QByteArray original = - "#define CONST const\n" - "#define VOLATILE volatile\n" - "class Foo\n" - "{\n" - " int func(int a, int b) CONST VOLATILE;\n" - "};\n" - "\n" - "\n" - "int Foo::fu@nc(int a, int b) CONST VOLATILE" - "{\n" - " return 42;\n" - "}\n"; - QByteArray expected = - "#define CONST const\n" - "#define VOLATILE volatile\n" - "class Foo\n" - "{\n" - " int func(int a, int b) CONST VOLATILE\n" - " {\n" - " return 42;\n" - " }\n" - "};\n\n\n\n"; - - MoveFuncDefToDeclPush factory; - QuickFixOperationTest(singleDocument(original, expected), &factory, - ProjectExplorer::HeaderPaths(), 0, "QTCREATORBUG-12314"); -} - -/// Check: Move all definitions from header to cpp. -void QuickfixTest::testMoveAllFuncDefOutsideMemberFuncToCpp() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Foo {@\n" - " int numberA() const\n" - " {\n" - " return 5;\n" - " }\n" - " int numberB() const\n" - " {\n" - " return 5;\n" - " }\n" - "};\n"; - expected = - "class Foo {\n" - " int numberA() const;\n" - " int numberB() const;\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n"; - expected = - "#include \"file.h\"\n" - "\n" - "int Foo::numberA() const\n" - "{\n" - " return 5;\n" - "}\n" - "\n" - "int Foo::numberB() const\n" - "{\n" - " return 5;\n" - "}\n" - ; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - MoveAllFuncDefOutside factory; - QuickFixOperationTest(testDocuments, &factory); -} - -/// Check: Move all definition outside class -void QuickfixTest::testMoveAllFuncDefOutsideMemberFuncOutside() -{ - QByteArray original = - "class F@oo {\n" - " int f1()\n" - " {\n" - " return 1;\n" - " }\n" - " int f2() const\n" - " {\n" - " return 2;\n" - " }\n" - "};\n"; - QByteArray expected = - "class Foo {\n" - " int f1();\n" - " int f2() const;\n" - "};\n" - "\n" - "int Foo::f1()\n" - "{\n" - " return 1;\n" - "}\n" - "\n" - "int Foo::f2() const\n" - "{\n" - " return 2;\n" - "}\n"; - - MoveAllFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check: Move all definition outside class -void QuickfixTest::testMoveAllFuncDefOutsideDoNotTriggerOnBaseClass() -{ - QByteArray original = - "class Bar;\n" - "class Foo : public Ba@r {\n" - " int f1()\n" - " {\n" - " return 1;\n" - " }\n" - "};\n"; - - MoveAllFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, ""), &factory); -} - -/// Check: Move all definition outside class -void QuickfixTest::testMoveAllFuncDefOutsideClassWithBaseClass() -{ - QByteArray original = - "class Bar;\n" - "class Fo@o : public Bar {\n" - " int f1()\n" - " {\n" - " return 1;\n" - " }\n" - "};\n"; - QByteArray expected = - "class Bar;\n" - "class Foo : public Bar {\n" - " int f1();\n" - "};\n" - "\n" - "int Foo::f1()\n" - "{\n" - " return 1;\n" - "}\n"; - - MoveAllFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -/// Check: Do not take macro expanded code into account (QTCREATORBUG-13900) -void QuickfixTest::testMoveAllFuncDefOutsideIgnoreMacroCode() -{ - QByteArray original = - "#define FAKE_Q_OBJECT int bar() {return 5;}\n" - "class Fo@o {\n" - " FAKE_Q_OBJECT\n" - " int f1()\n" - " {\n" - " return 1;\n" - " }\n" - "};\n"; - QByteArray expected = - "#define FAKE_Q_OBJECT int bar() {return 5;}\n" - "class Foo {\n" - " FAKE_Q_OBJECT\n" - " int f1();\n" - "};\n" - "\n" - "int Foo::f1()\n" - "{\n" - " return 1;\n" - "}\n"; - - MoveAllFuncDefOutside factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testAssignToLocalVariableTemplates() -{ - - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "template <typename T>\n" - "class List {\n" - "public:\n" - " T first();" - "};\n" - ; - expected = original; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n" - "void foo() {\n" - " List<int> list;\n" - " li@st.first();\n" - "}\n"; - expected = - "#include \"file.h\"\n" - "void foo() {\n" - " List<int> list;\n" - " auto localFirst = list.first();\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - AssignToLocalVariable factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testExtractFunction_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QTest::newRow("basic") - << _("// Documentation for f\n" - "void f()\n" - "{\n" - " @{start}g();@{end}\n" - "}\n") - << _("inline void extracted()\n" - "{\n" - " g();\n" - "}\n" - "\n" - "// Documentation for f\n" - "void f()\n" - "{\n" - " extracted();\n" - "}\n"); - - QTest::newRow("class function") - << _("class Foo\n" - "{\n" - "private:\n" - " void bar();\n" - "};\n\n" - "void Foo::bar()\n" - "{\n" - " @{start}g();@{end}\n" - "}\n") - << _("class Foo\n" - "{\n" - "public:\n" - " void extracted();\n\n" - "private:\n" - " void bar();\n" - "};\n\n" - "inline void Foo::extracted()\n" - "{\n" - " g();\n" - "}\n\n" - "void Foo::bar()\n" - "{\n" - " extracted();\n" - "}\n"); - - QTest::newRow("class in namespace") - << _("namespace NS {\n" - "class C {\n" - " void f(C &c);\n" - "};\n" - "}\n" - "void NS::C::f(NS::C &c)\n" - "{\n" - " @{start}C *c2 = &c;@{end}\n" - "}\n") - << _("namespace NS {\n" - "class C {\n" - " void f(C &c);\n" - "\n" - "public:\n" - " void extracted(NS::C &c);\n" // TODO: Remove non-required qualification - "};\n" - "}\n" - "inline void NS::C::extracted(NS::C &c)\n" - "{\n" - " C *c2 = &c;\n" - "}\n" - "\n" - "void NS::C::f(NS::C &c)\n" - "{\n" - " extracted(c);\n" - "}\n"); - - QTest::newRow("if-block") - << _("inline void func()\n" - "{\n" - " int dummy = 0;\n" - " @{start}if@{end} (dummy < 10) {\n" - " ++dummy;\n" - " }\n" - "}\n") - << _("inline void extracted(int dummy)\n" - "{\n" - " if (dummy < 10) {\n" - " ++dummy;\n" - " }\n" - "}\n\n" - "inline void func()\n" - "{\n" - " int dummy = 0;\n" - " extracted(dummy);\n" - "}\n"); -} - -void QuickfixTest::testExtractFunction() -{ - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.h", original, expected); - - ExtractFunction factory([]() { return QLatin1String("extracted"); }); - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testExtractLiteralAsParameterTypeDeduction_data() -{ - QTest::addColumn<QByteArray>("typeString"); - QTest::addColumn<QByteArray>("literal"); - QTest::newRow("int") - << QByteArray("int ") << QByteArray("156"); - QTest::newRow("unsigned int") - << QByteArray("unsigned int ") << QByteArray("156u"); - QTest::newRow("long") - << QByteArray("long ") << QByteArray("156l"); - QTest::newRow("unsigned long") - << QByteArray("unsigned long ") << QByteArray("156ul"); - QTest::newRow("long long") - << QByteArray("long long ") << QByteArray("156ll"); - QTest::newRow("unsigned long long") - << QByteArray("unsigned long long ") << QByteArray("156ull"); - QTest::newRow("float") - << QByteArray("float ") << QByteArray("3.14159f"); - QTest::newRow("double") - << QByteArray("double ") << QByteArray("3.14159"); - QTest::newRow("long double") - << QByteArray("long double ") << QByteArray("3.14159L"); - QTest::newRow("bool") - << QByteArray("bool ") << QByteArray("true"); - QTest::newRow("bool") - << QByteArray("bool ") << QByteArray("false"); - QTest::newRow("char") - << QByteArray("char ") << QByteArray("'X'"); - QTest::newRow("wchar_t") - << QByteArray("wchar_t ") << QByteArray("L'X'"); - QTest::newRow("char16_t") - << QByteArray("char16_t ") << QByteArray("u'X'"); - QTest::newRow("char32_t") - << QByteArray("char32_t ") << QByteArray("U'X'"); - QTest::newRow("const char *") - << QByteArray("const char *") << QByteArray("\"narf\""); - QTest::newRow("const wchar_t *") - << QByteArray("const wchar_t *") << QByteArray("L\"narf\""); - QTest::newRow("const char16_t *") - << QByteArray("const char16_t *") << QByteArray("u\"narf\""); - QTest::newRow("const char32_t *") - << QByteArray("const char32_t *") << QByteArray("U\"narf\""); -} - -void QuickfixTest::testExtractLiteralAsParameterTypeDeduction() -{ - QFETCH(QByteArray, typeString); - QFETCH(QByteArray, literal); - const QByteArray original = QByteArray("void foo() {return @") + literal + QByteArray(";}\n"); - const QByteArray expected = QByteArray("void foo(") + typeString + QByteArray("newParameter = ") - + literal + QByteArray(") {return newParameter;}\n"); - - if (literal == "3.14159") { - qWarning("Literal 3.14159 is wrongly reported as int. Skipping."); - return; - } else if (literal == "3.14159L") { - qWarning("Literal 3.14159L is wrongly reported as long. Skipping."); - return; - } - - ExtractLiteralAsParameter factory; - QuickFixOperationTest(singleDocument(original, expected), &factory); -} - -void QuickfixTest::testExtractLiteralAsParameterFreeFunctionSeparateFiles() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "void foo(const char *a, long b = 1);\n"; - expected = - "void foo(const char *a, long b = 1, int newParameter = 156);\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "void foo(const char *a, long b)\n" - "{return 1@56 + 123 + 156;}\n"; - expected = - "void foo(const char *a, long b, int newParameter)\n" - "{return newParameter + 123 + newParameter;}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - ExtractLiteralAsParameter factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testExtractLiteralAsParameterMemberFunctionSeparateFiles() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - QByteArray expected; - - // Header File - original = - "class Narf {\n" - "public:\n" - " int zort();\n" - "};\n"; - expected = - "class Narf {\n" - "public:\n" - " int zort(int newParameter = 155);\n" - "};\n"; - testDocuments << CppTestDocument::create("file.h", original, expected); - - // Source File - original = - "#include \"file.h\"\n\n" - "int Narf::zort()\n" - "{ return 15@5 + 1; }\n"; - expected = - "#include \"file.h\"\n\n" - "int Narf::zort(int newParameter)\n" - "{ return newParameter + 1; }\n"; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - ExtractLiteralAsParameter factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testExtractLiteralAsParameterNotTriggeringForInvalidCode() -{ - QList<TestDocumentPtr> testDocuments; - QByteArray original; - original = - "T(\"test\")\n" - "{\n" - " const int i = @14;\n" - "}\n"; - testDocuments << CppTestDocument::create("file.cpp", original, ""); - - ExtractLiteralAsParameter factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testAddCurlyBraces_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QByteArray original = R"delim( -void MyObject::f() -{ - @if (true) - emit mySig(); -})delim"; - QByteArray expected = R"delim( -void MyObject::f() -{ - if (true) { - emit mySig(); - } -})delim"; - QTest::newRow("if") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (true) - emit mySig(); - else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - @if (true) { - emit mySig(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if with one else, unbraced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (true) { - emit mySig(); - } else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - @if (true) { - emit mySig(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if with one else, if braced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (true) - emit mySig(); - else { - emit otherSig(); - } -})delim"; - expected = R"delim( -void MyObject::f() -{ - @if (true) { - emit mySig(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if with one else, else braced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (true) { - emit mySig(); - } else { - emit otherSig(); - } -})delim"; - expected.clear(); - QTest::newRow("if with one else, both braced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) - emit sig2(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } -})delim"; - QTest::newRow("if-else chain without final else, unbraced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) { - emit sig1(); - } else if (x == 2) - emit sig2(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } -})delim"; - QTest::newRow("if-else chain without final else, partially braced 1") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) { - emit sig2(); - } -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } -})delim"; - QTest::newRow("if-else chain without final else, partially braced 2") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } -})delim"; - expected.clear(); - QTest::newRow("if-else chain without final else, fully braced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) - emit sig2(); - else if (x == 3) - emit sig3(); - else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if-else chain, unbraced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) { - emit sig1(); - } else if (x == 2) - emit sig2(); - else if (x == 3) - emit sig3(); - else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if-else chain, partially braced 1") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) { - emit sig2(); - } else if (x == 3) - emit sig3(); - else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if-else chain, partially braced 2") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) - emit sig2(); - else if (x == 3) { - emit sig3(); - } else - emit otherSig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if-else chain, partially braced 3") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) - emit sig1(); - else if (x == 2) - emit sig2(); - else if (x == 3) - emit sig3(); - else { - emit otherSig(); - } -})delim"; - expected = R"delim( -void MyObject::f() -{ - if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - QTest::newRow("if-else chain, partially braced 4") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @if (x == 1) { - emit sig1(); - } else if (x == 2) { - emit sig2(); - } else if (x == 3) { - emit sig3(); - } else { - emit otherSig(); - } -})delim"; - expected.clear(); - QTest::newRow("if-else chain, fully braced") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @while (true) - emit mySig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - while (true) { - emit mySig(); - } -})delim"; - QTest::newRow("while") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @for (int i = 0; i < 10; ++i) - emit mySig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - for (int i = 0; i < 10; ++i) { - emit mySig(); - } -})delim"; - QTest::newRow("for") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @for (int i : list) - emit mySig(); -})delim"; - expected = R"delim( -void MyObject::f() -{ - for (int i : list) { - emit mySig(); - } -})delim"; - QTest::newRow("range-based for") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @do - emit mySig(); - while (true); -})delim"; - expected = R"delim( -void MyObject::f() -{ - do { - emit mySig(); - } while (true); -})delim"; - QTest::newRow("do") << original << expected; - - original = R"delim( -void MyObject::f() -{ - @do { - emit mySig(); - } while (true); -})delim"; - expected.clear(); - QTest::newRow("already has braces") << original << expected; -} - -void QuickfixTest::testAddCurlyBraces() -{ - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - AddBracesToControlStatement factory; - QuickFixOperationTest({CppTestDocument::create("file.cpp", original, expected)}, &factory); -} - -void QuickfixTest::testConvertQt4ConnectConnectOutOfClass() -{ - QByteArray prefix = - "class QObject {};\n" - "class TestClass : public QObject\n" - "{\n" - "public:\n" - " void setProp(int) {}\n" - " void sigFoo(int) {}\n" - "};\n" - "\n" - "int foo()\n" - "{\n"; - - QByteArray suffix = "\n}\n"; - - QByteArray original = prefix - + " TestClass obj;\n" - " conne@ct(&obj, SIGNAL(sigFoo(int)), &obj, SLOT(setProp(int)));" - + suffix; - - QByteArray expected = prefix - + " TestClass obj;\n" - " connect(&obj, &TestClass::sigFoo, &obj, &TestClass::setProp);" - + suffix; - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.cpp", original, expected); - - ConvertQt4Connect factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testConvertQt4ConnectConnectWithinClass_data() -{ - QTest::addColumn<QByteArray>("original"); - QTest::addColumn<QByteArray>("expected"); - - QTest::newRow("four-args-connect") - << QByteArray("conne@ct(this, SIGNAL(sigFoo(int)), this, SLOT(setProp(int)));") - << QByteArray("connect(this, &TestClass::sigFoo, this, &TestClass::setProp);"); - - QTest::newRow("four-args-disconnect") - << QByteArray("disconne@ct(this, SIGNAL(sigFoo(int)), this, SLOT(setProp(int)));") - << QByteArray("disconnect(this, &TestClass::sigFoo, this, &TestClass::setProp);"); - - QTest::newRow("three-args-connect") - << QByteArray("conne@ct(this, SIGNAL(sigFoo(int)), SLOT(setProp(int)));") - << QByteArray("connect(this, &TestClass::sigFoo, this, &TestClass::setProp);"); - - QTest::newRow("template-value") - << QByteArray("Pointer<TestClass> p;\n" - "conne@ct(p.t, SIGNAL(sigFoo(int)), p.t, SLOT(setProp(int)));") - << QByteArray("Pointer<TestClass> p;\n" - "connect(p.t, &TestClass::sigFoo, p.t, &TestClass::setProp);"); - - QTest::newRow("implicit-pointer") - << QByteArray("Pointer<TestClass> p;\n" - "conne@ct(p, SIGNAL(sigFoo(int)), p, SLOT(setProp(int)));") - << QByteArray("Pointer<TestClass> p;\n" - "connect(p.data(), &TestClass::sigFoo, p.data(), &TestClass::setProp);"); -} - -void QuickfixTest::testConvertQt4ConnectConnectWithinClass() -{ - QFETCH(QByteArray, original); - QFETCH(QByteArray, expected); - - QByteArray prefix = - "template<class T>\n" - "struct Pointer\n" - "{\n" - " T *t;\n" - " operator T*() const { return t; }\n" - " T *data() const { return t; }\n" - "};\n" - "class QObject {};\n" - "class TestClass : public QObject\n" - "{\n" - "public:\n" - " void setProp(int) {}\n" - " void sigFoo(int) {}\n" - " void setupSignals();\n" - "};\n" - "\n" - "int TestClass::setupSignals()\n" - "{\n"; - - QByteArray suffix = "\n}\n"; - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.cpp", - prefix + original + suffix, - prefix + expected + suffix); - - ConvertQt4Connect factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testConvertQt4ConnectDifferentNamespace() -{ - const QByteArray prefix = - "namespace NsA {\n" - "class ClassA : public QObject\n" - "{\n" - " static ClassA *instance();\n" - "signals:\n" - " void sig();\n" - "};\n" - "}\n" - "\n" - "namespace NsB {\n" - "class ClassB : public QObject\n" - "{\n" - " void slot();\n" - " void connector() {\n"; - - const QByteArray suffix = " }\n};\n}"; - - const QByteArray original = "co@nnect(NsA::ClassA::instance(), SIGNAL(sig()),\n" - " this, SLOT(slot()));\n"; - const QByteArray expected = "connect(NsA::ClassA::instance(), &NsA::ClassA::sig,\n" - " this, &ClassB::slot);\n"; - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.cpp", - prefix + original + suffix, - prefix + expected + suffix); - - ConvertQt4Connect factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testRemoveUsingNamespace_data() -{ - QTest::addColumn<QByteArray>("header1"); - QTest::addColumn<QByteArray>("header2"); - QTest::addColumn<QByteArray>("header3"); - QTest::addColumn<QByteArray>("expected1"); - QTest::addColumn<QByteArray>("expected2"); - QTest::addColumn<QByteArray>("expected3"); - QTest::addColumn<int>("operation"); - - const QByteArray header1 = "namespace std{\n" - " template<typename T>\n" - " class vector{};\n" - " namespace chrono{\n" - " using seconds = int;\n" - " }\n" - "}\n" - "using namespace std;\n" - "namespace test{\n" - " class vector{\n" - " std::vector<int> ints;\n" - " };\n" - "}\n"; - const QByteArray header2 = "#include \"header1.h\"\n" - "using foo = test::vector;\n" - "using namespace std;\n" - "using namespace test;\n" - "vector<int> others;\n"; - - const QByteArray header3 = "#include \"header2.h\"\n" - "using namespace std;\n" - "using namespace chrono;\n" - "namespace test{\n" - " vector vec;\n" - " seconds t;\n" - "}\n" - "void scope(){\n" - " for (;;) {\n" - " using namespace std;\n" - " vector<int> fori;\n" - " }\n" - " vector<int> no;\n" - " using namespace std;\n" - " vector<int> _no_change;\n" - "}\n" - "foo foos;\n"; - - QByteArray h3 = "#include \"header2.h\"\n" - "using namespace s@td;\n" - "using namespace chrono;\n" - "namespace test{\n" - " vector vec;\n" - " seconds t;\n" - "}\n" - "void scope(){\n" - " for (;;) {\n" - " using namespace std;\n" - " vector<int> fori;\n" - " }\n" - " vector<int> no;\n" - " using namespace std;\n" - " vector<int> _no_change;\n" - "}\n" - "foo foos;\n"; - - // like header1 but without "using namespace std;\n" - QByteArray expected1 = "namespace std{\n" - " template<typename T>\n" - " class vector{};\n" - " namespace chrono{\n" - " using seconds = int;\n" - " }\n" - "}\n" - "namespace test{\n" - " class vector{\n" - " std::vector<int> ints;\n" - " };\n" - "}\n"; - - // like header2 but without "using namespace std;\n" and with std::vector - QByteArray expected2 = "#include \"header1.h\"\n" - "using foo = test::vector;\n" - "using namespace test;\n" - "std::vector<int> others;\n"; - - QByteArray expected3 = "#include \"header2.h\"\n" - "using namespace std::chrono;\n" - "namespace test{\n" - " vector vec;\n" - " seconds t;\n" - "}\n" - "void scope(){\n" - " for (;;) {\n" - " using namespace std;\n" - " vector<int> fori;\n" - " }\n" - " std::vector<int> no;\n" - " using namespace std;\n" - " vector<int> _no_change;\n" - "}\n" - "foo foos;\n"; - - QTest::newRow("remove only in one file local") - << header1 << header2 << h3 << header1 << header2 << expected3 << 0; - QTest::newRow("remove only in one file globally") - << header1 << header2 << h3 << expected1 << expected2 << expected3 << 1; - - QByteArray h2 = "#include \"header1.h\"\n" - "using foo = test::vector;\n" - "using namespace s@td;\n" - "using namespace test;\n" - "vector<int> others;\n"; - - QTest::newRow("remove across two files only this") - << header1 << h2 << header3 << header1 << expected2 << header3 << 0; - QTest::newRow("remove across two files globally1") - << header1 << h2 << header3 << expected1 << expected2 << expected3 << 1; - - QByteArray h1 = "namespace std{\n" - " template<typename T>\n" - " class vector{};\n" - " namespace chrono{\n" - " using seconds = int;\n" - " }\n" - "}\n" - "using namespace s@td;\n" - "namespace test{\n" - " class vector{\n" - " std::vector<int> ints;\n" - " };\n" - "}\n"; - - QTest::newRow("remove across tree files only this") - << h1 << header2 << header3 << expected1 << header2 << header3 << 0; - QTest::newRow("remove across tree files globally") - << h1 << header2 << header3 << expected1 << expected2 << expected3 << 1; - - expected3 = "#include \"header2.h\"\n" - "using namespace std::chrono;\n" - "namespace test{\n" - " vector vec;\n" - " seconds t;\n" - "}\n" - "void scope(){\n" - " for (;;) {\n" - " using namespace s@td;\n" - " vector<int> fori;\n" - " }\n" - " std::vector<int> no;\n" - " using namespace std;\n" - " vector<int> _no_change;\n" - "}\n" - "foo foos;\n"; - - QByteArray expected3_new = "#include \"header2.h\"\n" - "using namespace std::chrono;\n" - "namespace test{\n" - " vector vec;\n" - " seconds t;\n" - "}\n" - "void scope(){\n" - " for (;;) {\n" - " std::vector<int> fori;\n" - " }\n" - " std::vector<int> no;\n" - " using namespace std;\n" - " vector<int> _no_change;\n" - "}\n" - "foo foos;\n"; - - QTest::newRow("scoped remove") - << expected1 << expected2 << expected3 << expected1 << expected2 << expected3_new << 0; - - h2 = "#include \"header1.h\"\n" - "using foo = test::vector;\n" - "using namespace std;\n" - "using namespace t@est;\n" - "vector<int> others;\n"; - expected2 = "#include \"header1.h\"\n" - "using foo = test::vector;\n" - "using namespace std;\n" - "vector<int> others;\n"; - - QTest::newRow("existing namespace") - << header1 << h2 << header3 << header1 << expected2 << header3 << 1; - - // test: remove using directive at global scope in every file - h1 = "using namespace tes@t;"; - h2 = "using namespace test;"; - h3 = "using namespace test;"; - - expected1 = expected2 = expected3 = ""; - QTest::newRow("global scope remove in every file") - << h1 << h2 << h3 << expected1 << expected2 << expected3 << 1; - - // test: dont print inline namespaces - h1 = R"--( -namespace test { - inline namespace test { - class Foo{ - void foo1(); - void foo2(); - }; - inline int TEST = 42; - } -} -)--"; - h2 = R"--( -#include "header1.h" -using namespace tes@t; -)--"; - h3 = R"--( -#include "header2.h" -Foo f1; -test::Foo f2; -using T1 = Foo; -using T2 = test::Foo; -int i1 = TEST; -int i2 = test::TEST; -void Foo::foo1(){}; -void test::Foo::foo2(){}; -)--"; - - expected1 = h1; - expected2 = R"--( -#include "header1.h" -)--"; - expected3 = R"--( -#include "header2.h" -test::Foo f1; -test::Foo f2; -using T1 = test::Foo; -using T2 = test::Foo; -int i1 = test::TEST; -int i2 = test::TEST; -void test::Foo::foo1(){}; -void test::Foo::foo2(){}; -)--"; - QTest::newRow("don't insert inline namespaces") - << h1 << h2 << h3 << expected1 << expected2 << expected3 << 0; -} - -void QuickfixTest::testRemoveUsingNamespace() -{ - QFETCH(QByteArray, header1); - QFETCH(QByteArray, header2); - QFETCH(QByteArray, header3); - QFETCH(QByteArray, expected1); - QFETCH(QByteArray, expected2); - QFETCH(QByteArray, expected3); - QFETCH(int, operation); - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("header1.h", header1, expected1); - testDocuments << CppTestDocument::create("header2.h", header2, expected2); - testDocuments << CppTestDocument::create("header3.h", header3, expected3); - - RemoveUsingNamespace factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), operation); -} - -void QuickfixTest::testRemoveUsingNamespaceSimple_data() -{ - QTest::addColumn<QByteArray>("header"); - QTest::addColumn<QByteArray>("expected"); - - const QByteArray common = R"--( -namespace N{ - template<typename T> - struct vector{ - using iterator = T*; - }; - using int_vector = vector<int>; -} -)--"; - const QByteArray header = common + R"--( -using namespace N@; -int_vector ints; -int_vector::iterator intIter; -using vec = vector<int>; -vec::iterator it; -)--"; - const QByteArray expected = common + R"--( -N::int_vector ints; -N::int_vector::iterator intIter; -using vec = N::vector<int>; -vec::iterator it; -)--"; - - QTest::newRow("nested typedefs with Namespace") << header << expected; -} - -void QuickfixTest::testRemoveUsingNamespaceSimple() -{ - QFETCH(QByteArray, header); - QFETCH(QByteArray, expected); - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("header.h", header, expected); - - RemoveUsingNamespace factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths()); -} - -void QuickfixTest::testRemoveUsingNamespaceDifferentSymbols() -{ - QByteArray header = "namespace test{\n" - " struct foo{\n" - " foo();\n" - " void bar();\n" - " };\n" - " void func();\n" - " enum E {E1, E2};\n" - " int bar;\n" - "}\n" - "using namespace t@est;\n" - "foo::foo(){}\n" - "void foo::bar(){}\n" - "void test(){\n" - " int i = bar * 4;\n" - " E val = E1;\n" - " auto p = &foo::bar;\n" - " func()\n" - "}\n"; - QByteArray expected = "namespace test{\n" - " struct foo{\n" - " foo();\n" - " void bar();\n" - " };\n" - " void func();\n" - " enum E {E1, E2};\n" - " int bar;\n" - "}\n" - "test::foo::foo(){}\n" - "void test::foo::bar(){}\n" - "void test(){\n" - " int i = test::bar * 4;\n" - " test::E val = test::E1;\n" - " auto p = &test::foo::bar;\n" - " test::func()\n" - "}\n"; - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.h", header, expected); - RemoveUsingNamespace factory; - QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 0); -} - -enum ConstructorLocation { Inside, Outside, CppGenNamespace, CppGenUsingDirective, CppRewriteType }; - -void QuickfixTest::testGenerateConstructor_data() -{ - QTest::addColumn<QByteArray>("original_header"); - QTest::addColumn<QByteArray>("expected_header"); - QTest::addColumn<QByteArray>("original_source"); - QTest::addColumn<QByteArray>("expected_source"); - QTest::addColumn<int>("location"); - const int Inside = ConstructorLocation::Inside; - const int Outside = ConstructorLocation::Outside; - const int CppGenNamespace = ConstructorLocation::CppGenNamespace; - const int CppGenUsingDirective = ConstructorLocation::CppGenUsingDirective; - const int CppRewriteType = ConstructorLocation::CppRewriteType; - - QByteArray header = R"--( -class@ Foo{ - int test; - static int s; -}; -)--"; - QByteArray expected = R"--( -class Foo{ - int test; - static int s; -public: - Foo(int test) : test(test) - {} -}; -)--"; - QTest::newRow("ignore static") << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - CustomType test; -}; -)--"; - expected = R"--( -class Foo{ - CustomType test; -public: - Foo(CustomType test) : test(std::move(test)) - {} -}; -)--"; - QTest::newRow("Move custom value types") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test; -protected: - Foo() = default; -}; -)--"; - expected = R"--( -class Foo{ - int test; -public: - Foo(int test) : test(test) - {} - -protected: - Foo() = default; -}; -)--"; - - QTest::newRow("new section before existing") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test; -}; -)--"; - expected = R"--( -class Foo{ - int test; -public: - Foo(int test) : test(test) - {} -}; -)--"; - QTest::newRow("new section at end") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test; -public: - /** - * Random comment - */ - Foo(int i, int i2); -}; -)--"; - expected = R"--( -class Foo{ - int test; -public: - Foo(int test) : test(test) - {} - /** - * Random comment - */ - Foo(int i, int i2); -}; -)--"; - QTest::newRow("in section before") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test; -public: - Foo() = default; -}; -)--"; - expected = R"--( -class Foo{ - int test; -public: - Foo() = default; - Foo(int test) : test(test) - {} -}; -)--"; - QTest::newRow("in section after") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test1; - int test2; - int test3; -public: -}; -)--"; - expected = R"--( -class Foo{ - int test1; - int test2; - int test3; -public: - Foo(int test2, int test3, int test1) : test1(test1), - test2(test2), - test3(test3) - {} -}; -)--"; - // No worry, that is not the default behavior. - // Move first member to the back when testing with 3 or more members - QTest::newRow("changed parameter order") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -class@ Foo{ - int test; - int di_test; -public: -}; -)--"; - expected = R"--( -class Foo{ - int test; - int di_test; -public: - Foo(int test, int di_test = 42) : test(test), - di_test(di_test) - {} -}; -)--"; - QTest::newRow("default parameters") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -struct Bar{ - Bar(int i); -}; -class@ Foo : public Bar{ - int test; -public: -}; -)--"; - expected = R"--( -struct Bar{ - Bar(int i); -}; -class Foo : public Bar{ - int test; -public: - Foo(int test, int i) : Bar(i), - test(test) - {} -}; -)--"; - QTest::newRow("parent constructor") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -struct Bar{ - Bar(int use_i = 6); -}; -class@ Foo : public Bar{ - int test; -public: -}; -)--"; - expected = R"--( -struct Bar{ - Bar(int use_i = 6); -}; -class Foo : public Bar{ - int test; -public: - Foo(int test, int use_i = 6) : Bar(use_i), - test(test) - {} -}; -)--"; - QTest::newRow("parent constructor with default") - << header << expected << QByteArray() << QByteArray() << Inside; - - header = R"--( -struct Bar{ - Bar(int use_i = L'A', int use_i2 = u8"B"); -}; -class@ Foo : public Bar{ -public: -}; -)--"; - expected = R"--( -struct Bar{ - Bar(int use_i = L'A', int use_i2 = u8"B"); -}; -class Foo : public Bar{ -public: - Foo(int use_i = L'A', int use_i2 = u8"B") : Bar(use_i, use_i2) - {} -}; -)--"; - QTest::newRow("parent constructor with char/string default value") - << header << expected << QByteArray() << QByteArray() << Inside; - - const QByteArray common = R"--( -namespace N{ - template<typename T> - struct vector{ - }; -} -)--"; - header = common + R"--( -namespace M{ -enum G{g}; -class@ Foo{ - N::vector<G> g; - enum E{e}e; -public: -}; -} -)--"; - - expected = common + R"--( -namespace M{ -enum G{g}; -class@ Foo{ - N::vector<G> g; - enum E{e}e; -public: - Foo(const N::vector<G> &g, E e); -}; - -Foo::Foo(const N::vector<G> &g, Foo::E e) : g(g), - e(e) -{} - -} -)--"; - QTest::newRow("source: right type outside class ") - << QByteArray() << QByteArray() << header << expected << Outside; - expected = common + R"--( -namespace M{ -enum G{g}; -class@ Foo{ - N::vector<G> g; - enum E{e}e; -public: - Foo(const N::vector<G> &g, E e); -}; -} - - -inline M::Foo::Foo(const N::vector<M::G> &g, M::Foo::E e) : g(g), - e(e) -{} - -)--"; - QTest::newRow("header: right type outside class ") - << header << expected << QByteArray() << QByteArray() << Outside; - - expected = common + R"--( -namespace M{ -enum G{g}; -class@ Foo{ - N::vector<G> g; - enum E{e}e; -public: - Foo(const N::vector<G> &g, E e); -}; -} -)--"; - const QByteArray source = R"--( -#include "file.h" -)--"; - QByteArray expected_source = R"--( -#include "file.h" - - -namespace M { -Foo::Foo(const N::vector<G> &g, Foo::E e) : g(g), - e(e) -{} - -} -)--"; - QTest::newRow("source: right type inside namespace") - << header << expected << source << expected_source << CppGenNamespace; - - expected_source = R"--( -#include "file.h" - -using namespace M; -Foo::Foo(const N::vector<G> &g, Foo::E e) : g(g), - e(e) -{} -)--"; - QTest::newRow("source: right type with using directive") - << header << expected << source << expected_source << CppGenUsingDirective; - - expected_source = R"--( -#include "file.h" - -M::Foo::Foo(const N::vector<M::G> &g, M::Foo::E e) : g(g), - e(e) -{} -)--"; - QTest::newRow("source: right type while rewritung types") - << header << expected << source << expected_source << CppRewriteType; -} - -void QuickfixTest::testGenerateConstructor() -{ - class TestFactory : public GenerateConstructor - { - public: - TestFactory() { setTest(); } - }; - - QFETCH(QByteArray, original_header); - QFETCH(QByteArray, expected_header); - QFETCH(QByteArray, original_source); - QFETCH(QByteArray, expected_source); - QFETCH(int, location); - - QuickFixSettings s; - s->valueTypes << "CustomType"; - using L = ConstructorLocation; - if (location == L::Inside) { - s->setterInCppFileFrom = -1; - s->setterOutsideClassFrom = -1; - } else if (location == L::Outside) { - s->setterInCppFileFrom = -1; - s->setterOutsideClassFrom = 1; - } else if (location >= L::CppGenNamespace && location <= L::CppRewriteType) { - s->setterInCppFileFrom = 1; - s->setterOutsideClassFrom = -1; - using Handling = CppQuickFixSettings::MissingNamespaceHandling; - if (location == L::CppGenNamespace) - s->cppFileNamespaceHandling = Handling::CreateMissing; - else if (location == L::CppGenUsingDirective) - s->cppFileNamespaceHandling = Handling::AddUsingDirective; - else if (location == L::CppRewriteType) - s->cppFileNamespaceHandling = Handling::RewriteType; - } else { - QFAIL("location is none of the values of the ConstructorLocation enum"); - } - - QList<TestDocumentPtr> testDocuments; - testDocuments << CppTestDocument::create("file.h", original_header, expected_header); - testDocuments << CppTestDocument::create("file.cpp", original_source, expected_source); - TestFactory factory; - QuickFixOperationTest(testDocuments, &factory); -} - -void QuickfixTest::testChangeCommentType_data() -{ - QTest::addColumn<QString>("input"); - QTest::addColumn<QString>("expectedOutput"); - - QTest::newRow("C -> C++ / no selection / single line") << R"( -int var1; -/* Other comment, unaffected */ -/* Our @comment */ -/* Another unaffected comment */ -int var2;)" << R"( -int var1; -/* Other comment, unaffected */ -// Our comment -/* Another unaffected comment */ -int var2;)"; - - QTest::newRow("C -> C++ / no selection / multi-line / preserved header and footer") << R"( -/**************************************************** - * some info - * more @info - ***************************************************/)" << R"( -///////////////////////////////////////////////////// -// some info -// more info -/////////////////////////////////////////////////////)"; - - QTest::newRow("C -> C++ / no selection / multi-line / non-preserved header and footer") << R"( -/* - * some info - * more @info - */)" << R"( -// some info -// more info -)"; - - QTest::newRow("C -> C++ / no selection / qdoc") << R"( -/*! - \qmlproperty string Type::element.name - \qmlproperty int Type::element.id - - \brief Holds the @element name and id. -*/)" << R"( -//! \qmlproperty string Type::element.name -//! \qmlproperty @int Type::element.id -//! -//! \brief Holds the element name and id. -)"; - - QTest::newRow("C -> C++ / no selection / doxygen") << R"( -/*! \class Test - \brief A test class. - - A more detailed @class description. -*/)" << R"( -//! \class Test -//! \brief A test class. -//! -//! A more detailed class description. -)"; - - QTest::newRow("C -> C++ / selection / single line") << R"( -int var1; -/* Other comment, unaffected */ -@{start}/* Our comment */@{end} -/* Another unaffected comment */ -int var2;)" << R"( -int var1; -/* Other comment, unaffected */ -// Our comment -/* Another unaffected comment */ -int var2;)"; - - QTest::newRow("C -> C++ / selection / multi-line / preserved header and footer") << R"( -/**************************************************** - * @{start}some info - * more info@{end} - ***************************************************/)" << R"( -///////////////////////////////////////////////////// -// some info -// more info -/////////////////////////////////////////////////////)"; - - QTest::newRow("C -> C++ / selection / multi-line / non-preserved header and footer") << R"( -/*@{start} - * some in@{end}fo - * more info - */)" << R"( -// some info -// more info -)"; - - QTest::newRow("C -> C++ / selection / qdoc") << R"( -/*!@{start} - \qmlproperty string Type::element.name - \qmlproperty int Type::element.id - - \brief Holds the element name and id. -*/@{end})" << R"( -//! \qmlproperty string Type::element.name -//! \qmlproperty int Type::element.id -//! -//! \brief Holds the element name and id. -)"; - - QTest::newRow("C -> C++ / selection / doxygen") << R"( -/** Expand envi@{start}ronment variables in a string. - * - * Environment variables are accepted in the @{end}following forms: - * $SOMEVAR, ${SOMEVAR} on Unix and %SOMEVAR% on Windows. - * No escapes and quoting are supported. - * If a variable is not found, it is not substituted. - */)" << R"( -//! Expand environment variables in a string. -//! -//! Environment variables are accepted in the following forms: -//! $SOMEVAR, ${SOMEVAR} on Unix and %SOMEVAR% on Windows. -//! No escapes and quoting are supported. -//! If a variable is not found, it is not substituted. -)"; - - QTest::newRow("C -> C++ / selection / multiple comments") << R"( -@{start}/* Affected comment */ -/* Another affected comment */ -/* A third affected comment */@{end} -/* An unaffected comment */)" << R"( -// Affected comment -// Another affected comment -// A third affected comment -/* An unaffected comment */)"; - - // FIXME: Remove adjacent newline along with last block - // FIXME: Use CppRefactoringFile to auto-indent continuation lines? - QTest::newRow("C -> C++, indented") << R"( -struct S { - /* - * @This is an - * indented comment. - */ - void func(); -)" << R"( -struct S { - // This is an -// indented comment. - - void func(); -)"; - - QTest::newRow("C++ -> C / no selection / single line") << R"( -// Other comment, unaffected -// Our @comment -// Another unaffected comment)" << R"( -// Other comment, unaffected -/* Our comment */ -// Another unaffected comment)"; - - QTest::newRow("C++ -> C / selection / single line") << R"( -// Other comment, unaffected -@{start}// Our comment@{end} -// Another unaffected comment)" << R"( -// Other comment, unaffected -/* Our comment */ -// Another unaffected comment)"; - - QTest::newRow("C++ -> C / selection / multi-line / preserved header and footer") << R"( -@{start}///////////////////////////////////////////////////// -// some info -// more info -/////////////////////////////////////////////////////@{end})" << R"( -/****************************************************/ -/* some info */ -/* more info */ -/****************************************************/)"; - - QTest::newRow("C++ -> C / selection / qdoc") << R"( -@{start}//! \qmlproperty string Type::element.name -//! \qmlproperty int Type::element.id -//! -//! \brief Holds the element name and id.@{end} -)" << R"( -/*! - \qmlproperty string Type::element.name - \qmlproperty int Type::element.id - - \brief Holds the element name and id. -*/ -)"; - - QTest::newRow("C++ -> C / selection / doxygen") << R"( -@{start}//! \class Test -//! \brief A test class. -//! -//! A more detailed class description.@{end} -)" << R"( -/*! - \class Test - \brief A test class. - - A more detailed class description. -*/ -)"; -} - -void QuickfixTest::testChangeCommentType() -{ - QFETCH(QString, input); - QFETCH(QString, expectedOutput); - - ConvertCommentStyle factory; - QuickFixOperationTest( - {CppTestDocument::create("file.h", input.toUtf8(), expectedOutput.toUtf8())}, - &factory); -} - -void QuickfixTest::testMoveComments_data() -{ - QTest::addColumn<QByteArrayList>("headers"); - QTest::addColumn<QByteArrayList>("sources"); - - const QByteArrayList headersFuncDecl2Def{R"( -// Function comment -void @aFunction(); -)", R"( -void aFunction(); -)"}; - const QByteArrayList sourcesFuncDecl2Def{R"( -#include "file.h" - -void aFunction() {} -)", R"( -#include "file.h" - -// Function comment -void aFunction() {} -)"}; - QTest::newRow("function: from decl to def") << headersFuncDecl2Def << sourcesFuncDecl2Def; - - const QByteArrayList headersFuncDef2Decl{R"( -void aFunction(); -)", R"( -/* function */ -/* comment */ -void aFunction(); -)"}; - const QByteArrayList sourcesFuncDef2Decl{R"( -#include "file.h" - -/* function */ -/* comment */ -void a@Function() {} -)", R"( -#include "file.h" - -void aFunction() {} -)"}; - QTest::newRow("function: from def to decl") << headersFuncDef2Decl << sourcesFuncDef2Decl; - - const QByteArrayList headersFuncNoDef{R"( -// Function comment -void @aFunction(); -)", R"( -// Function comment -void aFunction(); -)"}; - QTest::newRow("function: no def") << headersFuncNoDef << QByteArrayList(); - - const QByteArrayList headersFuncNoDecl{R"( -// Function comment -inline void @aFunction() {} -)", R"( -// Function comment -inline void aFunction() {} -)"}; - QTest::newRow("function: no decl") << headersFuncNoDecl << QByteArrayList(); - - const QByteArrayList headersFuncTemplateDecl2Def{R"( -// Function comment -template<typename T> T @aFunction(); - -template<typename T> inline T aFunction() { return T(); } -)", R"( -template<typename T> T aFunction(); - -// Function comment -template<typename T> inline T aFunction() { return T(); } -)"}; - QTest::newRow("function template: from decl to def") << headersFuncTemplateDecl2Def - << QByteArrayList(); - - const QByteArrayList headersFuncTemplateDef2Decl{R"( -template<typename T> T aFunction(); - -// Function comment -template<typename T> inline T @aFunction() { return T(); } -)", R"( -// Function comment -template<typename T> T aFunction(); - -template<typename T> inline T aFunction() { return T(); } -)"}; - QTest::newRow("function template: from def to decl") << headersFuncTemplateDef2Decl - << QByteArrayList(); - - const QByteArrayList headersMemberDecl2Def{R"( -class C { - /** - * \brief Foo::aMember - */ - void @aMember(); -)", R"( -class C { - void aMember(); -)"}; - const QByteArrayList sourcesMemberDecl2Def{R"( -#include "file.h" - -void C::aMember() {} -)", R"( -#include "file.h" - -/** - * \brief Foo::aMember - */ -void C::aMember() {} -)"}; - QTest::newRow("member function: from decl to def") << headersMemberDecl2Def - << sourcesMemberDecl2Def; - - const QByteArrayList headersMemberDef2Decl{R"( -class C { - void aMember(); -)", R"( -class C { - /** - * \brief Foo::aMember - */ - void aMember(); -)"}; - const QByteArrayList sourcesMemberDef2Decl{R"( -#include "file.h" - -/** - * \brief Foo::aMember - */ -void C::aMember() {@} -)", R"( -#include "file.h" - -void C::aMember() {} -)"}; - QTest::newRow("member function: from def to decl") << headersMemberDef2Decl - << sourcesMemberDef2Decl; -} - -void QuickfixTest::testMoveComments() -{ - QFETCH(QByteArrayList, headers); - QFETCH(QByteArrayList, sources); - - QList<TestDocumentPtr> documents; - QCOMPARE(headers.size(), 2); - documents << CppTestDocument::create("file.h", headers.at(0), headers.at(1)); - if (!sources.isEmpty()) { - QCOMPARE(sources.size(), 2); - documents << CppTestDocument::create("file.cpp", sources.at(0), sources.at(1)); - } - MoveFunctionComments factory; - QByteArray failMessage; - if (QByteArray(QTest::currentDataTag()) == "function template: from def to decl") - failMessage = "decl/def switch doesn't work for templates"; - QuickFixOperationTest(documents, &factory, {}, {}, failMessage); -} - -void QuickfixTest::testConvertToMetaMethodInvocation_data() -{ - QTest::addColumn<QByteArray>("input"); - QTest::addColumn<QByteArray>("expected"); - - // ^ marks the cursor locations. - // $ marks the replacement regions. - // The quoted string in the comment is the data tag. - // The rest of the comment is the replacement string. - const QByteArray allCases = R"( -class C { -public: - C() { - $this->^aSignal()$; // "signal from region on pointer to object" QMetaObject::invokeMethod(this, "aSignal") - C c; - $c.^aSignal()$; // "signal from region on object value" QMetaObject::invokeMethod(&c, "aSignal") - $(new C)->^aSignal()$; // "signal from region on expression" QMetaObject::invokeMethod((new C), "aSignal") - $emit this->^aSignal()$; // "signal from region, with emit" QMetaObject::invokeMethod(this, "aSignal") - $Q_EMIT this->^aSignal()$; // "signal from region, with Q_EMIT" QMetaObject::invokeMethod(this, "aSignal") - $this->^aSlot()$; // "slot from region" QMetaObject::invokeMethod(this, "aSlot") - $this->^noArgs()$; // "Q_SIGNAL, no arguments" QMetaObject::invokeMethod(this, "noArgs") - $this->^oneArg(0)$; // "Q_SLOT, one argument" QMetaObject::invokeMethod(this, "oneArg", Q_ARG(int, 0)) - $this->^twoArgs(0, c)$; // "Q_INVOKABLE, two arguments" QMetaObject::invokeMethod(this, "twoArgs", Q_ARG(int, 0), Q_ARG(C, c)) - this->^notInvokable(); // "not invokable" - } - -signals: - void aSignal(); - -private slots: - void aSlot(); - -private: - Q_SIGNAL void noArgs(); - Q_SLOT void oneArg(int index); - Q_INVOKABLE void twoArgs(int index, const C &value); - void notInvokable(); -}; -)"; - - qsizetype nextCursor = allCases.indexOf('^'); - while (nextCursor != -1) { - const int commentStart = allCases.indexOf("//", nextCursor); - QVERIFY(commentStart != -1); - const int tagStart = allCases.indexOf('"', commentStart + 2); - QVERIFY(tagStart != -1); - const int tagEnd = allCases.indexOf('"', tagStart + 1); - QVERIFY(tagEnd != -1); - QByteArray input = allCases; - QByteArray output = allCases; - input.replace(nextCursor, 1, "@"); - const QByteArray tag = allCases.mid(tagStart + 1, tagEnd - tagStart - 1); - const int prevNewline = allCases.lastIndexOf('\n', nextCursor); - const int regionStart = allCases.lastIndexOf('$', nextCursor); - bool hasReplacement = false; - if (regionStart != -1 && regionStart > prevNewline) { - const int regionEnd = allCases.indexOf('$', regionStart + 1); - QVERIFY(regionEnd != -1); - const int nextNewline = allCases.indexOf('\n', tagEnd); - QVERIFY(nextNewline != -1); - const QByteArray replacement - = allCases.mid(tagEnd + 1, nextNewline - tagEnd - 1).trimmed(); - output.replace(regionStart, regionEnd - regionStart, replacement); - hasReplacement = true; - } - static const auto matcher = [](char c) { return c == '^' || c == '$'; }; - input.removeIf(matcher); - if (hasReplacement) { - output.removeIf(matcher); - output.prepend("#include <QMetaObject>\n\n"); - } else { - output.clear(); - } - QTest::newRow(tag.data()) << input << output; - nextCursor = allCases.indexOf('^', nextCursor + 1); - } -} - -void QuickfixTest::testConvertToMetaMethodInvocation() -{ - QFETCH(QByteArray, input); - QFETCH(QByteArray, expected); - - ConvertToMetaMethodCall factory; - QuickFixOperationTest({CppTestDocument::create("file.cpp", input, expected)}, &factory); -} - -} // namespace CppEditor::Internal::Tests |