CppEditor: Introduce testing infrastructure for symbol renaming

Also add two example tests.

Change-Id: Ia76c4d92e7643971c1f201081b3df1f77f1e89a5
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2023-08-24 14:12:32 +02:00
parent d7d78df9da
commit 098ddf11e8
7 changed files with 176 additions and 2 deletions

View File

@@ -129,6 +129,7 @@ extend_qtc_plugin(CppEditor
cppmodelmanager_test.cpp cppmodelmanager_test.h
cpppointerdeclarationformatter_test.cpp cpppointerdeclarationformatter_test.h
cppquickfix_test.cpp cppquickfix_test.h
cpprenaming_test.cpp cpprenaming_test.h
cppsourceprocessertesthelper.cpp cppsourceprocessertesthelper.h
cppsourceprocessor_test.cpp cppsourceprocessor_test.h
cpptoolstestcase.cpp cpptoolstestcase.h

View File

@@ -265,6 +265,8 @@ QtcPlugin {
"cpppointerdeclarationformatter_test.h",
"cppquickfix_test.cpp",
"cppquickfix_test.h",
"cpprenaming_test.cpp",
"cpprenaming_test.h",
"cppsourceprocessor_test.cpp",
"cppsourceprocessor_test.h",
"cppsourceprocessertesthelper.cpp",

View File

@@ -42,6 +42,7 @@
#include "cppmodelmanager_test.h"
#include "cpppointerdeclarationformatter_test.h"
#include "cppquickfix_test.h"
#include "cpprenaming_test.h"
#include "cppsourceprocessor_test.h"
#include "cppuseselections_test.h"
#include "fileandtokenactions_test.h"
@@ -509,6 +510,7 @@ void CppEditorPlugin::initialize()
addTest<Tests::IncludeHierarchyTest>();
addTest<Tests::InsertVirtualMethodsTest>();
addTest<Tests::QuickfixTest>();
addTest<Tests::GlobalRenamingTest>();
addTest<Tests::SelectionsTest>();
#endif
}

View File

@@ -576,8 +576,10 @@ static void displayResults(SearchResult *search,
item.setContainingFunctionName(result.containingFunction);
item.setStyle(colorStyleForUsageType(result.tags));
item.setUseTextEditorFont(true);
if (search->supportsReplace())
item.setSelectForReplacement(ProjectManager::projectForFile(result.path));
if (search->supportsReplace()) {
item.setSelectForReplacement(!ProjectManager::hasProjects()
|| ProjectManager::projectForFile(result.path));
}
search->addResult(item);
if (parameters.prettySymbolName.isEmpty())

View File

@@ -1,6 +1,8 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "cppquickfix.h"
#include "cpptoolstestcase.h"

View File

@@ -0,0 +1,146 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cpprenaming_test.h"
#include "cppeditorwidget.h"
#include "cppmodelmanager.h"
#include "cppquickfix_test.h"
#include <texteditor/texteditor.h>
#include <QEventLoop>
#include <QTimer>
#include <QtTest>
namespace CppEditor::Internal::Tests {
class RenamingTestRunner : public BaseQuickFixTestCase
{
public:
RenamingTestRunner(const QList<TestDocumentPtr> &testDocuments, const QString &replacement)
: BaseQuickFixTestCase(testDocuments, {})
{
QVERIFY(succeededSoFar());
const TestDocumentPtr &doc = m_documentWithMarker;
const CursorInEditor cursorInEditor(doc->m_editor->textCursor(), doc->filePath(),
doc->m_editorWidget, doc->m_editor->textDocument());
QEventLoop loop;
CppModelManager::globalRename(cursorInEditor, replacement, [&loop]{ loop.quit(); });
QTimer::singleShot(10000, &loop, [&loop] { loop.exit(1); });
QVERIFY(loop.exec() == 0);
// Compare all files
for (const TestDocumentPtr &testDocument : std::as_const(m_testDocuments)) {
QString result = testDocument->m_editorWidget->document()->toPlainText();
if (result != testDocument->m_expectedSource) {
qDebug() << "---" << testDocument->m_expectedSource;
qDebug() << "+++" << result;
}
QCOMPARE(result, testDocument->m_expectedSource);
// Undo the change
for (int i = 0; i < 100; ++i)
testDocument->m_editorWidget->undo();
result = testDocument->m_editorWidget->document()->toPlainText();
QCOMPARE(result, testDocument->m_source);
}
}
};
void GlobalRenamingTest::test_data()
{
QTest::addColumn<QByteArrayList>("headers");
QTest::addColumn<QByteArrayList>("sources");
QTest::addColumn<QString>("replacement");
const char testClassHeader[] = R"cpp(
/**
* \brief MyClass
*/
class MyClass {
/** \brief MyClass::MyClass */
MyClass() {}
~MyClass();
/** \brief MyClass::run */
void run();
};
)cpp";
const char testClassSource[] = R"cpp(
#include "file.h"
/** \brief MyClass::~MyClass */
MyClass::~MyClass() {}
void MyClass::run() {}
)cpp";
QByteArray origHeaderClassName(testClassHeader);
const int classOffset = origHeaderClassName.indexOf("class MyClass");
QVERIFY(classOffset != -1);
origHeaderClassName.insert(classOffset + 6, '@');
const QByteArray newHeaderClassName = R"cpp(
/**
* \brief MyClass
*/
class MyNewClass {
/** \brief MyClass::MyClass */
MyNewClass() {}
~MyNewClass();
/** \brief MyClass::run */
void run();
};
)cpp";
const QByteArray newSourceClassName = R"cpp(
#include "file.h"
/** \brief MyClass::~MyClass */
MyNewClass::~MyNewClass() {}
void MyNewClass::run() {}
)cpp";
QTest::newRow("class name") << QByteArrayList{origHeaderClassName, newHeaderClassName}
<< QByteArrayList{testClassSource, newSourceClassName}
<< QString("MyNewClass");
QByteArray origSourceMethodName(testClassSource);
const int methodOffset = origSourceMethodName.indexOf("::run()");
QVERIFY(methodOffset != -1);
origSourceMethodName.insert(methodOffset + 2, '@');
const QByteArray newHeaderMethodName = R"cpp(
/**
* \brief MyClass
*/
class MyClass {
/** \brief MyClass::MyClass */
MyClass() {}
~MyClass();
/** \brief MyClass::run */
void runAgain();
};
)cpp";
const QByteArray newSourceMethodName = R"cpp(
#include "file.h"
/** \brief MyClass::~MyClass */
MyClass::~MyClass() {}
void MyClass::runAgain() {}
)cpp";
QTest::newRow("method name") << QByteArrayList{testClassHeader, newHeaderMethodName}
<< QByteArrayList{origSourceMethodName, newSourceMethodName}
<< QString("runAgain");
}
void GlobalRenamingTest::test()
{
QFETCH(QByteArrayList, headers);
QFETCH(QByteArrayList, sources);
QFETCH(QString, replacement);
QList<TestDocumentPtr> testDocuments(
{CppTestDocument::create("file.h", headers.at(0), headers.at(1)),
CppTestDocument::create("file.cpp", sources.at(0), sources.at(1))});
RenamingTestRunner testRunner(testDocuments, replacement);
}
} // namespace CppEditor::Internal::Tests

View File

@@ -0,0 +1,19 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <QObject>
namespace CppEditor::Internal::Tests {
class GlobalRenamingTest : public QObject
{
Q_OBJECT
private slots:
void test_data();
void test();
};
} // namespace CppEditor::Internal::Tests