forked from qt-creator/qt-creator
ASTPath uses TranslationUnit::getPosition(), which returns reasonable results for: 1. non-expanded tokens 2. expanded but not generated tokens The expanded *and* generated tokens case is not handled since there is no reasonable mapping from generated tokens to a continuous line/column information. Consider: #define DECLARE_FOO int foo; // Multiple generated tokens DECLARE_FOO // ...can be mapped to this line, but to which columns? Since the result where not valid for the expanded and generated case, ASTPath took the wrong branches. Avoid this by skipping generated tokens. Change-Id: I33a2e0f62917f87d691b19feaeef67b09ea8d563 Task-number: QTCREATORBUG-13386 Task-number: QTCREATORBUG-13390 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
4754 lines
139 KiB
C++
4754 lines
139 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing
|
|
**
|
|
** This file is part of Qt Creator.
|
|
**
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
|
** use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "cppeditorplugin.h"
|
|
#include "cppeditortestcase.h"
|
|
#include "cppquickfixassistant.h"
|
|
#include "cppquickfixes.h"
|
|
#include "cppquickfix_test.h"
|
|
|
|
#include <cpptools/cppcodestylepreferences.h>
|
|
#include <cpptools/cppmodelmanager.h>
|
|
#include <cpptools/cppsourceprocessertesthelper.h>
|
|
#include <cpptools/cpptoolssettings.h>
|
|
|
|
#include <utils/fileutils.h>
|
|
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QtTest>
|
|
|
|
/*!
|
|
Tests for quick-fixes.
|
|
*/
|
|
using namespace Core;
|
|
using namespace CPlusPlus;
|
|
using namespace CppEditor::Internal::Tests;
|
|
using namespace TextEditor;
|
|
|
|
using CppTools::Tests::TestIncludePaths;
|
|
|
|
namespace CppEditor {
|
|
namespace Internal {
|
|
namespace Tests {
|
|
|
|
QuickFixTestDocument::Ptr QuickFixTestDocument::create(const QByteArray &fileName,
|
|
const QByteArray &source,
|
|
const QByteArray &expectedSource)
|
|
{
|
|
return Ptr(new QuickFixTestDocument(fileName, source, expectedSource));
|
|
}
|
|
|
|
|
|
QuickFixTestDocument::QuickFixTestDocument(const QByteArray &fileName,
|
|
const QByteArray &source,
|
|
const QByteArray &expectedSource)
|
|
: TestDocument(fileName, source)
|
|
, m_expectedSource(QString::fromUtf8(expectedSource))
|
|
{
|
|
removeMarkers();
|
|
}
|
|
|
|
void QuickFixTestDocument::removeMarkers()
|
|
{
|
|
// Remove selection markers
|
|
if (m_anchorPosition != -1) {
|
|
if (m_anchorPosition < m_cursorPosition) {
|
|
m_source.remove(m_anchorPosition, m_selectionStartMarker.size());
|
|
m_cursorPosition -= m_selectionStartMarker.size();
|
|
m_source.remove(m_cursorPosition, m_selectionEndMarker.size());
|
|
} else {
|
|
m_source.remove(m_cursorPosition, m_selectionEndMarker.size());
|
|
m_anchorPosition -= m_selectionEndMarker.size();
|
|
m_source.remove(m_anchorPosition, m_selectionStartMarker.size());
|
|
}
|
|
|
|
// Remove simple cursor marker
|
|
} else if (m_cursorPosition != -1) {
|
|
m_source.remove(m_cursorPosition, 1);
|
|
}
|
|
|
|
const int cursorPositionInExpectedSource
|
|
= m_expectedSource.indexOf(QLatin1Char(m_cursorMarker));
|
|
if (cursorPositionInExpectedSource > -1)
|
|
m_expectedSource.remove(cursorPositionInExpectedSource, 1);
|
|
}
|
|
|
|
QList<QuickFixTestDocument::Ptr> singleDocument(const QByteArray &original,
|
|
const QByteArray &expected)
|
|
{
|
|
return QList<QuickFixTestDocument::Ptr>()
|
|
<< QuickFixTestDocument::create("file.cpp", original, expected);
|
|
}
|
|
|
|
BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &testDocuments,
|
|
const ProjectPart::HeaderPaths &headerPaths)
|
|
: 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;
|
|
foreach (const QuickFixTestDocument::Ptr document, m_testDocuments) {
|
|
if (document->hasCursorMarker())
|
|
++cursorMarkersCount;
|
|
}
|
|
QVERIFY2(cursorMarkersCount == 1, "Exactly one cursor marker is allowed.");
|
|
|
|
// Write documents to disk
|
|
m_temporaryDirectory.reset(new CppTools::Tests::TemporaryDir);
|
|
QVERIFY(m_temporaryDirectory->isValid());
|
|
foreach (QuickFixTestDocument::Ptr document, m_testDocuments) {
|
|
if (QFileInfo(document->m_fileName).isRelative())
|
|
document->setBaseDirectory(m_temporaryDirectory->path());
|
|
document->writeToDisk();
|
|
}
|
|
|
|
// Set appropriate include paths
|
|
if (!headerPaths.isEmpty()) {
|
|
m_restoreHeaderPaths = true;
|
|
m_headerPathsToRestore = m_modelManager->headerPaths();
|
|
m_modelManager->setHeaderPaths(headerPaths);
|
|
}
|
|
|
|
// Update Code Model
|
|
QSet<QString> filePaths;
|
|
foreach (const QuickFixTestDocument::Ptr &document, m_testDocuments)
|
|
filePaths << document->filePath();
|
|
QVERIFY(parseFiles(filePaths));
|
|
|
|
// Open Files
|
|
foreach (QuickFixTestDocument::Ptr document, 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::instance()->cppCodeStyle();
|
|
QVERIFY(m_cppCodeStylePreferences);
|
|
m_cppCodeStylePreferencesOriginalDelegateId = m_cppCodeStylePreferences->currentDelegateId();
|
|
m_cppCodeStylePreferences->setCurrentDelegate("qt");
|
|
|
|
// Find the document having the cursor marker
|
|
foreach (const QuickFixTestDocument::Ptr document, 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)
|
|
m_modelManager->setHeaderPaths(m_headerPathsToRestore);
|
|
|
|
// Remove created files from file system
|
|
foreach (const QuickFixTestDocument::Ptr &testDocument, m_testDocuments)
|
|
QVERIFY(QFile::remove(testDocument->filePath()));
|
|
}
|
|
|
|
/// 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<QuickFixTestDocument::Ptr> &testDocuments,
|
|
CppQuickFixFactory *factory,
|
|
const ProjectPart::HeaderPaths &headerPaths,
|
|
int operationIndex,
|
|
const QByteArray &expectedFailMessage)
|
|
: BaseQuickFixTestCase(testDocuments, headerPaths)
|
|
{
|
|
QVERIFY(succeededSoFar());
|
|
|
|
// Perform operation if there is one
|
|
CppQuickFixInterface quickFixInterface(m_documentWithMarker->m_editorWidget, ExplicitlyInvoked);
|
|
QuickFixOperations operations;
|
|
factory->match(quickFixInterface, operations);
|
|
if (operations.isEmpty()) {
|
|
QVERIFY(testDocuments.first()->m_expectedSource.isEmpty());
|
|
return;
|
|
}
|
|
|
|
QVERIFY(operationIndex < operations.size());
|
|
const QuickFixOperation::Ptr operation = operations.at(operationIndex);
|
|
operation->perform();
|
|
|
|
// Compare all files
|
|
foreach (const QuickFixTestDocument::Ptr testDocument, m_testDocuments) {
|
|
// Check
|
|
QString result = testDocument->m_editorWidget->document()->toPlainText();
|
|
removeTrailingWhitespace(result);
|
|
if (!expectedFailMessage.isEmpty())
|
|
QEXPECT_FAIL("", expectedFailMessage.data(), Continue);
|
|
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<QuickFixTestDocument::Ptr> &testDocuments,
|
|
CppQuickFixFactory *factory,
|
|
const QString &headerPath,
|
|
int operationIndex)
|
|
{
|
|
ProjectPart::HeaderPaths headerPaths;
|
|
headerPaths += ProjectPart::HeaderPath(headerPath, ProjectPart::HeaderPath::IncludePath);
|
|
QuickFixOperationTest(testDocuments, factory, headerPaths, operationIndex);
|
|
}
|
|
|
|
QuickFixOfferedOperationsTest::QuickFixOfferedOperationsTest(
|
|
const QList<QuickFixTestDocument::Ptr> &testDocuments,
|
|
CppQuickFixFactory *factory,
|
|
const ProjectPart::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;
|
|
foreach (const QuickFixOperation::Ptr &operation, 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 match(const CppQuickFixInterface &cppQuickFixInterface, QuickFixOperations &result)
|
|
{
|
|
result.append(new AddIncludeForUndefinedIdentifierOp(cppQuickFixInterface, 0, m_include));
|
|
}
|
|
|
|
private:
|
|
const QString m_include;
|
|
};
|
|
|
|
} // namespace Tests
|
|
} // namespace Internal
|
|
|
|
typedef QSharedPointer<CppQuickFixFactory> CppQuickFixFactoryPtr;
|
|
|
|
} // namespace CppEditor
|
|
|
|
Q_DECLARE_METATYPE(CppEditor::CppQuickFixFactoryPtr)
|
|
|
|
namespace CppEditor {
|
|
namespace Internal {
|
|
|
|
void CppEditorPlugin::test_quickfix_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"
|
|
);
|
|
|
|
// 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"
|
|
);
|
|
|
|
// 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"
|
|
);
|
|
|
|
// 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"
|
|
);
|
|
|
|
// 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: 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"
|
|
);
|
|
|
|
// 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"
|
|
);
|
|
|
|
// Checks:
|
|
// 1. If the name does not start with ("m_" or "_") and does not
|
|
// end with "_", we are forced to prefix the getter with "get".
|
|
// 2. Setter: Use pass by value on integer/float and pointer types.
|
|
QTest::newRow("GenerateGetterSetter_basicGetterWithPrefix")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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 value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks: In addition to test_quickfix_GenerateGetterSetter_basicGetterWithPrefix
|
|
// generated definitions should fit in the namespace.
|
|
QTest::newRow("GenerateGetterSetter_basicGetterWithPrefixAndNamespace")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"namespace SomeNamespace {\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int @it;\n"
|
|
"};\n"
|
|
"}\n"
|
|
) << _(
|
|
"namespace SomeNamespace {\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int getIt() const;\n"
|
|
" void setIt(int value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
"\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks:
|
|
// 1. Getter: "get" prefix is not necessary.
|
|
// 2. Setter: Parameter name is base name.
|
|
QTest::newRow("GenerateGetterSetter_basicGetterWithoutPrefix")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int @m_it;\n"
|
|
"};\n"
|
|
) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int m_it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int it() const;\n"
|
|
" void setIt(int it);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::it() const\n"
|
|
"{\n"
|
|
" return m_it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int it)\n"
|
|
"{\n"
|
|
" m_it = it;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks if getter uses 'get' prefix if member function with such a prefix is found
|
|
QTest::newRow("GenerateGetterSetter_getterWithGetPrefix")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int getFoo();\n"
|
|
" int @m_it;\n"
|
|
"};\n"
|
|
) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int getFoo();\n"
|
|
" int m_it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int getIt() const;\n"
|
|
" void setIt(int it);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::getIt() const\n"
|
|
"{\n"
|
|
" return m_it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int it)\n"
|
|
"{\n"
|
|
" m_it = it;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Check: Setter: Use pass by reference for parameters which
|
|
// are not integer, float or pointers.
|
|
QTest::newRow("GenerateGetterSetter_customType")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" MyType @it;\n"
|
|
"};\n"
|
|
) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" MyType it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" MyType getIt() const;\n"
|
|
" void setIt(const MyType &value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"MyType Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(const MyType &value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks:
|
|
// 1. Setter: No setter is generated for const members.
|
|
// 2. Getter: Return a non-const type since it pass by value anyway.
|
|
QTest::newRow("GenerateGetterSetter_constMember")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" const int @it;\n"
|
|
"};\n"
|
|
) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" const int it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int getIt() const;\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks: No special treatment for pointer to non const.
|
|
QTest::newRow("GenerateGetterSetter_pointerToNonConst")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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 *value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int *Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int *value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks: No special treatment for pointer to const.
|
|
QTest::newRow("GenerateGetterSetter_pointerToConst")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" const int *it@;\n"
|
|
"};\n"
|
|
) << _(
|
|
"\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" const int *it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" const int *getIt() const;\n"
|
|
" void setIt(const int *value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"const int *Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(const int *value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Checks:
|
|
// 1. Setter: Setter is a static function.
|
|
// 2. Getter: Getter is a static, non const function.
|
|
QTest::newRow("GenerateGetterSetter_staticMember")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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
|
|
QTest::newRow("GenerateGetterSetter_secondDeclarator")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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 value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// Check: Quick fix is offered for "int *@it;" ('@' denotes the text cursor position)
|
|
QTest::newRow("GenerateGetterSetter_triggeringRightAfterPointerSign")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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 *value);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int *Something::getIt() const\n"
|
|
"{\n"
|
|
" return it;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setIt(int *value)\n"
|
|
"{\n"
|
|
" it = value;\n"
|
|
"}\n"
|
|
);
|
|
|
|
// 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") << _();
|
|
|
|
// Check: Do not offer the quick fix if there is a getter and the variable is const
|
|
QTest::newRow("GenerateGetterSetter_notTriggeringWhenGetterAndConstVariable")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" const int bar@;\n"
|
|
" int getBar() const;\n"
|
|
"};\n"
|
|
) << _();
|
|
|
|
// Check: Do not offer the quick fix if there is a getter and a setter
|
|
QTest::newRow("GenerateGetterSetter_notTriggeringWhenGetterAndConstVariable")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" const int bar@;\n"
|
|
" int getBar() const;\n"
|
|
" void setBar(int value);\n"
|
|
"};\n"
|
|
) << _();
|
|
|
|
// Checks if "m_" is recognized as "m" with the postfix "_" and not simply as "m_" prefix.
|
|
QTest::newRow("GenerateGetterSetter_recognizeMasVariableName")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"\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"
|
|
);
|
|
|
|
// Checks if the declaration inside Q_PROPERTY macro is ignored and a getter created
|
|
QTest::newRow("GenerateGetterSetter_ignoreQPropertiesMacro")
|
|
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
|
|
"class Something\n"
|
|
"{\n"
|
|
" Q_PROPERTY(int foo)\n"
|
|
" int @m_foo;\n"
|
|
"};\n"
|
|
) << _(
|
|
"class Something\n"
|
|
"{\n"
|
|
" Q_PROPERTY(int foo)\n"
|
|
" int m_foo;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int foo() const;\n"
|
|
" void setFoo(int foo);\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Something::foo() const\n"
|
|
"{\n"
|
|
" return m_foo;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void Something::setFoo(int foo)\n"
|
|
"{\n"
|
|
" m_foo = foo;\n"
|
|
"}\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() {int 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"
|
|
" int *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"
|
|
" int *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"
|
|
" int *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"
|
|
" int *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"
|
|
" Foo *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")
|
|
<< _();
|
|
|
|
QTest::newRow("InsertQtPropertyMembers")
|
|
<< CppQuickFixFactoryPtr(new InsertQtPropertyMembers)
|
|
<< _("struct XmarksTheSpot {\n"
|
|
" @Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n"
|
|
"};\n"
|
|
)
|
|
<< _("struct XmarksTheSpot {\n"
|
|
" Q_PROPERTY(int it READ getIt WRITE setIt NOTIFY itChanged)\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int getIt() const\n"
|
|
" {\n"
|
|
" return m_it;\n"
|
|
" }\n"
|
|
"\n"
|
|
"public slots:\n"
|
|
" void setIt(int it)\n"
|
|
" {\n"
|
|
" if (m_it == it)\n"
|
|
" return;\n"
|
|
"\n"
|
|
" m_it = it;\n"
|
|
" emit itChanged(it);\n"
|
|
" }\n"
|
|
"\n"
|
|
"signals:\n"
|
|
" void itChanged(int it);\n"
|
|
"\n"
|
|
"private:\n"
|
|
" int m_it;\n"
|
|
"};\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;\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;\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");
|
|
|
|
QTest::newRow("InsertQtPropertyMembers_noTriggerInvalidCode")
|
|
<< CppQuickFixFactoryPtr(new InsertQtPropertyMembers)
|
|
<< _("class C { @Q_PROPERTY(typeid foo READ foo) };\n")
|
|
<< _();
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix()
|
|
{
|
|
QFETCH(CppQuickFixFactoryPtr, factory);
|
|
QFETCH(QByteArray, original);
|
|
QFETCH(QByteArray, expected);
|
|
|
|
QuickFixOperationTest(singleDocument(original, expected), factory.data());
|
|
}
|
|
|
|
/// Checks: In addition to test_quickfix_GenerateGetterSetter_basicGetterWithPrefix
|
|
/// generated definitions should fit in the namespace.
|
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespaceToCpp()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace SomeNamespace {\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int @it;\n"
|
|
"};\n"
|
|
"}\n";
|
|
expected =
|
|
"namespace SomeNamespace {\n"
|
|
"class Something\n"
|
|
"{\n"
|
|
" int it;\n"
|
|
"\n"
|
|
"public:\n"
|
|
" int getIt() const;\n"
|
|
" void setIt(int value);\n"
|
|
"};\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"namespace SomeNamespace {\n"
|
|
"}\n";
|
|
expected =
|
|
"#include \"file.h\"\n"
|
|
"namespace SomeNamespace {\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";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
GenerateGetterSetter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Checks: Only generate getter
|
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_onlyGetter()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"int Foo::getBar() const\n"
|
|
"{\n"
|
|
" return bar;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
GenerateGetterSetter factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::HeaderPaths(), 1);
|
|
}
|
|
|
|
/// Checks: Only generate setter
|
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_onlySetter()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
" void setBar(int value);\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"void Foo::setBar(int value)\n"
|
|
"{\n"
|
|
" bar = value;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
GenerateGetterSetter factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::HeaderPaths(), 2);
|
|
}
|
|
|
|
/// Checks: Offer a "generate getter" quick fix if there is a setter
|
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_offerGetterWhenSetterPresent()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" int bar@;\n"
|
|
" void setBar(int value);\n"
|
|
"};\n";
|
|
expected =
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" int bar;\n"
|
|
" void setBar(int value);\n"
|
|
" int getBar() const;\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"int Foo::getBar() const\n"
|
|
"{\n"
|
|
" return bar;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
GenerateGetterSetter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Checks: Offer a "generate setter" quick fix if there is a getter
|
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_offerSetterWhenGetterPresent()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" int bar@;\n"
|
|
" int getBar() const;\n"
|
|
"};\n";
|
|
expected =
|
|
"class Foo\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" int bar;\n"
|
|
" int getBar() const;\n"
|
|
" void setBar(int value);\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"void Foo::setBar(int value)\n"
|
|
"{\n"
|
|
" bar = value;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
GenerateGetterSetter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check if definition is inserted right after class for insert definition outside
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_afterClass()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
"void Foo::a()\n"
|
|
"{\n\n}\n"
|
|
"\n"
|
|
"class Bar {};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic1()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" Foo()@;\n"
|
|
"};\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic2()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "void f()@;\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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()\n"
|
|
"{\n"
|
|
"\n"
|
|
"}\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check from source file: Insert in source file, not header file.
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic3()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Empty Header File
|
|
testDocuments << QuickFixTestDocument::create("file.h", "", "");
|
|
|
|
// Source File
|
|
original =
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" Foo()@;\n"
|
|
"};\n";
|
|
expected = original +
|
|
"\n"
|
|
"Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_namespace1()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace N {\n"
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" Foo()@;\n"
|
|
"};\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original.resize(0);
|
|
expected =
|
|
"\n"
|
|
"N::Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_namespace2()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace N {\n"
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" Foo()@;\n"
|
|
"};\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check definition insert inside class
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_insideClass()
|
|
{
|
|
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, ProjectPart::HeaderPaths(),
|
|
1);
|
|
}
|
|
|
|
/// Check not triggering when definition exists
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_notTriggeringWhenDefinitionExists()
|
|
{
|
|
const QByteArray original =
|
|
"class Foo {\n"
|
|
" void b@ar();\n"
|
|
"};\n"
|
|
"void Foo::bar() {}\n";
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, ""), &factory, ProjectPart::HeaderPaths(), 1);
|
|
}
|
|
|
|
/// Find right implementation file.
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_findRightImplementationFile()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File #1
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_ignoreSurroundingGeneratedDeclarations()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
// Source File #2
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"void Foo::hidden()\n"
|
|
"{\n\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file2.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check if whitespace is respected for operator functions
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_respectWsInOperatorNames1()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_respectWsInOperatorNames2()
|
|
{
|
|
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 a function like macro use is not separated by the function to insert
|
|
/// Case: Macro preceded by preproceesor directives and declaration.
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile1()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "void f()@;\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 CppEditorPlugin::test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile2()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "void f()@;\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check if insertion happens before syntactically erroneous statements at end of file.
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_erroneousStatementAtEndOfFile()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "void f()@;\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Respect rvalue references
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_rvalueReference()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "void f(Foo &&)@;\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original = "";
|
|
expected =
|
|
"\n"
|
|
"void f(Foo &&)\n"
|
|
"{\n"
|
|
"\n"
|
|
"}\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Find right implementation file. (QTCREATORBUG-10728)
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_findImplementationFile()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_unicodeIdentifier()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
#undef UNICODE_U00FC
|
|
#undef UNICODE_U4E8C
|
|
#undef UNICODE_U10302
|
|
#undef TEST_UNICODE_IDENTIFIER
|
|
|
|
InsertDefFromDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
// Function for one of InsertDeclDef section cases
|
|
void insertToSectionDeclFromDef(const QByteArray §ion, int sectionIndex)
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Foo\n"
|
|
"{\n"
|
|
"};\n";
|
|
expected =
|
|
"class Foo\n"
|
|
"{\n"
|
|
+ section + ":\n" +
|
|
" Foo();\n"
|
|
"@};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"Foo::Foo@()\n"
|
|
"{\n"
|
|
"}\n"
|
|
;
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
InsertDeclFromDef factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::HeaderPaths(), sectionIndex);
|
|
}
|
|
|
|
/// Check from source file: Insert in header file.
|
|
void CppEditorPlugin::test_quickfix_InsertDeclFromDef()
|
|
{
|
|
insertToSectionDeclFromDef("public", 0);
|
|
insertToSectionDeclFromDef("public slots", 1);
|
|
insertToSectionDeclFromDef("protected", 2);
|
|
insertToSectionDeclFromDef("protected slots", 3);
|
|
insertToSectionDeclFromDef("private", 4);
|
|
insertToSectionDeclFromDef("private slots", 5);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_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<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
|
|
// Header File
|
|
original = "class Foo {};\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("afile.cpp", original, expected);
|
|
QTest::newRow("onBaseOfQualifiedName")
|
|
<< TestIncludePaths::globalIncludePath()
|
|
<< testDocuments << firstRefactoringOperation << "";
|
|
testDocuments.clear();
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
|
|
// Header File
|
|
original = "namespace N { template <typename T> class Foo {}; }\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("afile.cpp", original, expected);
|
|
QTest::newRow("onTemplateNameInsideArguments")
|
|
<< TestIncludePaths::globalIncludePath()
|
|
<< testDocuments << firstRefactoringOperation << "";
|
|
testDocuments.clear();
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
|
|
// Header File
|
|
original = "class Foo {};\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("qmyclass.h", original, expected);
|
|
|
|
// Forward Header File
|
|
original = "#include \"qmyclass.h\"\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
QTest::newRow("inserting_checkQSomethingInQtIncludePaths")
|
|
<< TestIncludePaths::globalQtCoreIncludePath()
|
|
<< testDocuments << firstRefactoringOperation << "";
|
|
testDocuments.clear();
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier()
|
|
{
|
|
QFETCH(QString, headerPath);
|
|
QFETCH(QuickFixTestDocuments, testDocuments);
|
|
QFETCH(int, refactoringOperationIndex);
|
|
QFETCH(QString, includeForTestFactory);
|
|
|
|
CppTools::Tests::TemporaryDir temporaryDir;
|
|
QVERIFY(temporaryDir.isValid());
|
|
foreach (QuickFixTestDocument::Ptr testDocument, 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 CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_noDoubleQtHeaderInclude()
|
|
{
|
|
CppTools::Tests::TemporaryDir temporaryDir;
|
|
QVERIFY(temporaryDir.isValid());
|
|
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::create(base + "/fileUsingQDir.cpp", original, expected);
|
|
|
|
original = expected = "@QDir dir;\n";
|
|
testDocuments << QuickFixTestDocument::create(base + "/fileWantsToUseQDir.cpp", original, expected);
|
|
|
|
ProjectPart::HeaderPaths headerPaths;
|
|
headerPaths += ProjectPart::HeaderPath(TestIncludePaths::globalQtCoreIncludePath(),
|
|
ProjectPart::HeaderPath::IncludePath);
|
|
|
|
AddIncludeForUndefinedIdentifier factory;
|
|
const QStringList expectedOperations = QStringList() << QLatin1String("Add #include <QDir>");
|
|
QuickFixOfferedOperationsTest(testDocuments, &factory, headerPaths, expectedOperations);
|
|
}
|
|
|
|
/// Check: Move definition from header to cpp.
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCpp()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
" inline int number() const;\n"
|
|
"\n"
|
|
" void bar();\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppInsideNS()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move definition outside class
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside1()
|
|
{
|
|
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"
|
|
" inline 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 CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside2()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
"int Foo::f2()\n"
|
|
"{\n"
|
|
" return 1;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"void Foo::f1() {}\n"
|
|
"void Foo::f3() {}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::HeaderPaths(), 1);
|
|
}
|
|
|
|
/// Check: Move definition from header to cpp (with namespace).
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
" inline int number() const;\n"
|
|
"};\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move definition from header to cpp (with namespace + using).
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
" inline int number() const;\n"
|
|
"};\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move definition outside class with Namespace
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs()
|
|
{
|
|
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"
|
|
" inline 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 CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCpp()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"int numbe@r() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
expected =
|
|
"int number() const;\n"
|
|
;
|
|
testDocuments << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move free function from header to cpp (with namespace).
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move Ctor with member initialization list (QTCREATORBUG-9157).
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization1()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move Ctor with member initialization list (QTCREATORBUG-9462).
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization2()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check if definition is inserted right after class for move definition outside
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_afterClass()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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"
|
|
"void Foo::a() {}\n"
|
|
"\n"
|
|
"class Bar {};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"Foo::Foo()\n"
|
|
"{\n\n"
|
|
"}\n";
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory, ProjectPart::HeaderPaths(), 1);
|
|
}
|
|
|
|
/// Check if whitespace is respected for operator functions
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_respectWsInOperatorNames1()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_MoveFuncDefOutside_respectWsInOperatorNames2()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_MoveFuncDefOutside_macroUses()
|
|
{
|
|
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,
|
|
ProjectPart::HeaderPaths(), 0, "QTCREATORBUG-12314");
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncToCpp()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFunc()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Foo {\n"
|
|
" inline int number() const;\n"
|
|
"};\n";
|
|
expected =
|
|
"class Foo {\n"
|
|
" inline int number() const {return 5;}\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"int Foo::num@ber() const {return 5;}\n";
|
|
expected =
|
|
"#include \"file.h\"\n"
|
|
"\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncOutside()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncOutside()
|
|
{
|
|
QByteArray original =
|
|
"class Foo {\n"
|
|
" inline int number() const;\n"
|
|
"};\n"
|
|
"\n"
|
|
"int Foo::num@ber() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
|
|
QByteArray expected =
|
|
"class Foo {\n"
|
|
" inline int number() const\n"
|
|
" {\n"
|
|
" return 5;\n"
|
|
" }\n"
|
|
"};\n\n\n";
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, expected), &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNS()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace MyNs {\n"
|
|
"class Foo {\n"
|
|
" inline int number() const;\n"
|
|
"};\n"
|
|
"}\n";
|
|
expected =
|
|
"namespace MyNs {\n"
|
|
"class Foo {\n"
|
|
" inline int number() const\n"
|
|
" {\n"
|
|
" return 5;\n"
|
|
" }\n"
|
|
"};\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"int MyNs::Foo::num@ber() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
expected = "#include \"file.h\"\n\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncToCppNSUsing()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace MyNs {\n"
|
|
"class Foo {\n"
|
|
" inline int number() const;\n"
|
|
"};\n"
|
|
"}\n";
|
|
expected =
|
|
"namespace MyNs {\n"
|
|
"class Foo {\n"
|
|
" inline int number() const\n"
|
|
" {\n"
|
|
" return 5;\n"
|
|
" }\n"
|
|
"};\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"using namespace MyNs;\n"
|
|
"\n"
|
|
"int Foo::num@ber() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
expected =
|
|
"#include \"file.h\"\n"
|
|
"using namespace MyNs;\n"
|
|
"\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFuncOutsideWithNs()
|
|
{
|
|
QByteArray original =
|
|
"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";
|
|
QByteArray expected =
|
|
"namespace MyNs {\n"
|
|
"class Foo {\n"
|
|
" inline int number() const\n"
|
|
" {\n"
|
|
" return 5;\n"
|
|
" }\n"
|
|
"};\n\n\n}\n";
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, expected), &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_FreeFuncToCpp()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCpp()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original = "int number() const;\n";
|
|
expected =
|
|
"int number() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"\n"
|
|
"int numb@er() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
expected = "#include \"file.h\"\n\n\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCppNS()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"namespace MyNamespace {\n"
|
|
"int number() const;\n"
|
|
"}\n";
|
|
expected =
|
|
"namespace MyNamespace {\n"
|
|
"int number() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"int MyNamespace::nu@mber() const\n"
|
|
"{\n"
|
|
" return 5;\n"
|
|
"}\n";
|
|
expected =
|
|
"#include \"file.h\"\n"
|
|
"\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: revert test_quickfix_MoveFuncDefOutside_CtorWithInitialization()
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_CtorWithInitialization()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Foo {\n"
|
|
"public:\n"
|
|
" Foo();\n"
|
|
"private:\n"
|
|
" int a;\n"
|
|
" float b;\n"
|
|
"};\n";
|
|
expected =
|
|
"class Foo {\n"
|
|
"public:\n"
|
|
" Foo() : a(42), b(3.141) {}\n"
|
|
"private:\n"
|
|
" int a;\n"
|
|
" float b;\n"
|
|
"};\n";
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
// Source File
|
|
original =
|
|
"#include \"file.h\"\n"
|
|
"\n"
|
|
"Foo::F@oo() : a(42), b(3.141) {}"
|
|
;
|
|
expected ="#include \"file.h\"\n\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Definition should not be placed behind the variable. QTCREATORBUG-10303
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_structWithAssignedVariable()
|
|
{
|
|
QByteArray original =
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" void foo();\n"
|
|
"} bar;\n"
|
|
"void Foo::fo@o()\n"
|
|
"{\n"
|
|
" return;\n"
|
|
"}";
|
|
|
|
QByteArray expected =
|
|
"struct Foo\n"
|
|
"{\n"
|
|
" void foo()\n"
|
|
" {\n"
|
|
" return;\n"
|
|
" }\n"
|
|
"} bar;\n";
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, expected), &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_macroUses()
|
|
{
|
|
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";
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, expected), &factory,
|
|
ProjectPart::HeaderPaths(), 0, "QTCREATORBUG-12314");
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_override()
|
|
{
|
|
QByteArray original =
|
|
"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";
|
|
|
|
QByteArray expected =
|
|
"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";
|
|
|
|
MoveFuncDefToDecl factory;
|
|
QuickFixOperationTest(singleDocument(original, expected), &factory);
|
|
}
|
|
|
|
/// Check: Move all definitions from header to cpp.
|
|
void CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_MemberFuncToCpp()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"class Fo@o {\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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
MoveAllFuncDefOutside factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
/// Check: Move all definition outside class
|
|
void CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_MemberFuncOutside()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_DoNotTriggerOnBaseClass()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_classWithBaseClass()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_ignoreMacroCode()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_AssignToLocalVariable_templates()
|
|
{
|
|
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
QByteArray expected;
|
|
|
|
// Header File
|
|
original =
|
|
"template <typename T>\n"
|
|
"class List {\n"
|
|
"public:\n"
|
|
" T first();"
|
|
"};\n"
|
|
;
|
|
expected = original;
|
|
testDocuments << QuickFixTestDocument::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"
|
|
" int localFirst = list.first();\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
AssignToLocalVariable factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ExtractFunction_data()
|
|
{
|
|
QTest::addColumn<QByteArray>("original");
|
|
QTest::addColumn<QByteArray>("expected");
|
|
|
|
QTest::newRow("basic")
|
|
<< _("void f()\n"
|
|
"{\n"
|
|
" @{start}g();@{end}\n"
|
|
"}\n")
|
|
<< _("void extracted()\n"
|
|
"{\n"
|
|
" g();\n"
|
|
"}\n"
|
|
"\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"
|
|
"void Foo::extracted()\n"
|
|
"{\n"
|
|
" g();\n"
|
|
"}\n\n"
|
|
"void Foo::bar()\n"
|
|
"{\n"
|
|
" extracted();\n"
|
|
"}\n");
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ExtractFunction()
|
|
{
|
|
QFETCH(QByteArray, original);
|
|
QFETCH(QByteArray, expected);
|
|
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
|
|
|
ExtractFunction factory([]() { return QLatin1String("extracted"); });
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_typeDeduction_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 CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_typeDeduction()
|
|
{
|
|
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 CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_freeFunction_separateFiles()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
ExtractLiteralAsParameter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_memberFunction_separateFiles()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> 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 << QuickFixTestDocument::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 << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
ExtractLiteralAsParameter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_notTriggeringForInvalidCode()
|
|
{
|
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
|
QByteArray original;
|
|
original =
|
|
"T(\"test\")\n"
|
|
"{\n"
|
|
" const int i = @14;\n"
|
|
"}\n";
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, "");
|
|
|
|
ExtractLiteralAsParameter factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectOutOfClass()
|
|
{
|
|
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<QuickFixTestDocument::Ptr> testDocuments;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp", original, expected);
|
|
|
|
ConvertQt4Connect factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectWithinClass_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 CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectWithinClass()
|
|
{
|
|
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<QuickFixTestDocument::Ptr> testDocuments;
|
|
testDocuments << QuickFixTestDocument::create("file.cpp",
|
|
prefix + original + suffix,
|
|
prefix + expected + suffix);
|
|
|
|
ConvertQt4Connect factory;
|
|
QuickFixOperationTest(testDocuments, &factory);
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namespace CppEditor
|