Commit 6a94f7e3 authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppEditor: Add basic test for ExtractFunction

Change-Id: I44f2edb2905e202669630ab5da85066011491fae
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@theqtcompany.com>
parent 251b444c
......@@ -192,6 +192,9 @@ private slots:
void test_quickfix_AssignToLocalVariable_templates();
void test_quickfix_ExtractFunction_data();
void test_quickfix_ExtractFunction();
void test_quickfix_ExtractLiteralAsParameter_typeDeduction_data();
void test_quickfix_ExtractLiteralAsParameter_typeDeduction();
void test_quickfix_ExtractLiteralAsParameter_freeFunction_separateFiles();
......
......@@ -40,6 +40,8 @@
#include <QDir>
#include <utils/qtcassert.h>
using namespace CppEditor::Internal;
namespace CppEditor {
......@@ -48,14 +50,34 @@ namespace Tests {
TestDocument::TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker)
: CppTools::Tests::TestDocument(fileName, source, cursorMarker)
, m_cursorPosition(m_source.indexOf(QLatin1Char(m_cursorMarker)))
, m_cursorPosition(-1)
, m_anchorPosition(-1)
, m_selectionStartMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{start}"))
, m_selectionEndMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{end}"))
, m_editor(0)
, m_editorWidget(0)
{
// Try to find selection markers
const int selectionStartIndex = m_source.indexOf(m_selectionStartMarker);
const int selectionEndIndex = m_source.indexOf(m_selectionEndMarker);
const bool bothSelectionMarkersFound = selectionStartIndex != -1 && selectionEndIndex != -1;
const bool noneSelectionMarkersFounds = selectionStartIndex == -1 && selectionEndIndex == -1;
QTC_ASSERT(bothSelectionMarkersFound || noneSelectionMarkersFounds, return);
if (selectionStartIndex != -1) {
m_cursorPosition = selectionEndIndex;
m_anchorPosition = selectionStartIndex;
// No selection markers found, so check for simple cursorMarker
} else {
m_cursorPosition = m_source.indexOf(QLatin1Char(cursorMarker));
}
}
bool TestDocument::hasCursorMarker() const { return m_cursorPosition != -1; }
bool TestDocument::hasAnchorMarker() const { return m_anchorPosition != -1; }
TestCase::TestCase(bool runGarbageCollector)
: CppTools::Tests::TestCase(runGarbageCollector)
{
......
......@@ -50,9 +50,13 @@ public:
TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker = '@');
bool hasCursorMarker() const;
bool hasAnchorMarker() const;
public:
int m_cursorPosition;
int m_anchorPosition;
QString m_selectionStartMarker;
QString m_selectionEndMarker;
CppEditor *m_editor;
CppEditorWidget *m_editorWidget;
};
......
......@@ -73,8 +73,27 @@ QuickFixTestDocument::QuickFixTestDocument(const QByteArray &fileName,
: TestDocument(fileName, source)
, m_expectedSource(QString::fromUtf8(expectedSource))
{
if (m_cursorPosition > -1)
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));
......@@ -135,9 +154,16 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<QuickFixTestDocument::Ptr
closeEditorAtEndOfTestCase(document->m_editor);
// Set cursor position
const int cursorPosition = document->hasCursorMarker()
? document->m_cursorPosition : 0;
document->m_editor->setCursorPosition(cursorPosition);
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);
......@@ -4349,6 +4375,39 @@ void CppEditorPlugin::test_quickfix_AssignToLocalVariable_templates()
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");
}
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");
......
......@@ -50,8 +50,9 @@ namespace Tests {
/// Represents a test document before and after applying the quick fix.
///
/// A TestDocument's source may contain an '@' character to denote
/// the cursor position. This marker is removed before the Editor reads
/// the document.
/// the cursor position. For selections the markers "@{start}" and
/// "@{end}" can be used. The markers are removed before the editor
/// reads the document.
///
class QuickFixTestDocument : public TestDocument
......@@ -65,6 +66,9 @@ public:
static Ptr create(const QByteArray &fileName, const QByteArray &source,
const QByteArray &expectedSource);
private:
void removeMarkers();
public:
QString m_expectedSource;
};
......@@ -74,7 +78,8 @@ typedef QList<QuickFixTestDocument::Ptr> QuickFixTestDocuments;
class BaseQuickFixTestCase : public TestCase
{
public:
/// Exactly one QuickFixTestDocument must contain the cursor position marker '@'.
/// Exactly one QuickFixTestDocument must contain the cursor position marker '@'
/// or "@{start}" and "@{end}"
BaseQuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &testDocuments,
const CppTools::ProjectPart::HeaderPaths &headerPaths
= CppTools::ProjectPart::HeaderPaths());
......
......@@ -3118,13 +3118,16 @@ public:
int extractionEnd,
FunctionDefinitionAST *refFuncDef,
Symbol *funcReturn,
QList<QPair<QString, QString> > relevantDecls)
QList<QPair<QString, QString> > relevantDecls,
ExtractFunction::FunctionNameGetter functionNameGetter
= ExtractFunction::FunctionNameGetter())
: CppQuickFixOperation(interface)
, m_extractionStart(extractionStart)
, m_extractionEnd(extractionEnd)
, m_refFuncDef(refFuncDef)
, m_funcReturn(funcReturn)
, m_relevantDecls(relevantDecls)
, m_functionNameGetter(functionNameGetter)
{
setDescription(QCoreApplication::translate("QuickFix::ExtractFunction", "Extract Function"));
}
......@@ -3135,7 +3138,7 @@ public:
CppRefactoringChanges refactoring(snapshot());
CppRefactoringFilePtr currentFile = refactoring.file(fileName());
const QString &funcName = getFunctionName();
const QString &funcName = m_functionNameGetter ? m_functionNameGetter() : getFunctionName();
if (funcName.isEmpty())
return;
......@@ -3302,6 +3305,7 @@ public:
FunctionDefinitionAST *m_refFuncDef;
Symbol *m_funcReturn;
QList<QPair<QString, QString> > m_relevantDecls;
ExtractFunction::FunctionNameGetter m_functionNameGetter;
};
QPair<QString, QString> assembleDeclarationData(const QString &specifiers, DeclaratorAST *decltr,
......@@ -3505,6 +3509,11 @@ public:
} // anonymous namespace
ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter)
: m_functionNameGetter(functionNameGetter)
{
}
void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
CppRefactoringFilePtr file = interface.currentFile();
......@@ -3632,7 +3641,8 @@ void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOpera
analyser.m_extractionEnd,
refFuncDef,
funcReturn,
relevantDecls));
relevantDecls,
m_functionNameGetter));
}
namespace {
......
......@@ -34,11 +34,12 @@
#include "cppquickfix.h"
#include <cpptools/cpprefactoringchanges.h>
#include <extensionsystem/iplugin.h>
#include <QDialog>
#include <functional>
QT_BEGIN_NAMESPACE
class QByteArray;
template <class> class QList;
......@@ -435,7 +436,13 @@ public:
class ExtractFunction : public CppQuickFixFactory
{
public:
typedef std::function<QString ()> FunctionNameGetter;
ExtractFunction(FunctionNameGetter functionNameGetter = FunctionNameGetter());
void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result);
private:
FunctionNameGetter m_functionNameGetter; // For tests to avoid GUI pop-up.
};
/*!
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment