forked from qt-creator/qt-creator
CppEditor: Same insert position for quick fixes
Now definitions are inserted at the same position inside the implementation file for MoveFuncDefOutside and InsertDefFromDecl. Task-number: QTCREATORBUG-9389 Change-Id: If823ffd15ec39a7bc2edb53519380cb9cabb4c55 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
8f4c4b41f6
commit
c95b324b79
@@ -186,7 +186,8 @@ private slots:
|
||||
void test_quickfix_AddIncludeForUndefinedIdentifier_veryFirstIncludeCStyleCommentOnTop();
|
||||
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncToCpp();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncOutside();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncOutside1();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncOutside2();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing();
|
||||
void test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs();
|
||||
|
||||
@@ -760,15 +760,14 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_basic()
|
||||
"struct Foo\n"
|
||||
"{\n"
|
||||
" Foo();@\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
;
|
||||
"};\n";
|
||||
const QByteArray expected = original +
|
||||
"\n"
|
||||
"\n"
|
||||
"Foo::Foo()\n"
|
||||
"{\n\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
;
|
||||
"\n";
|
||||
|
||||
InsertDefFromDecl factory;
|
||||
TestCase data(original, expected);
|
||||
@@ -826,6 +825,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic2()
|
||||
" Foo()@;\n"
|
||||
"};\n";
|
||||
expected = original +
|
||||
"\n"
|
||||
"\n"
|
||||
"Foo::Foo()\n"
|
||||
"{\n\n"
|
||||
@@ -1768,8 +1768,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCpp()
|
||||
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"\n";
|
||||
"#include \"file.h\"\n";
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
@@ -1787,7 +1786,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCpp()
|
||||
}
|
||||
|
||||
/// Check: Move definition outside class
|
||||
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside()
|
||||
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside1()
|
||||
{
|
||||
QByteArray original =
|
||||
"class Foo {\n"
|
||||
@@ -1814,7 +1813,6 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside()
|
||||
" return 1;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void Foo::f4() {}\n\n";
|
||||
|
||||
MoveFuncDefOutside factory;
|
||||
@@ -1822,6 +1820,50 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside()
|
||||
data.run(&factory);
|
||||
}
|
||||
|
||||
/// Check: Move definition outside class
|
||||
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside2()
|
||||
{
|
||||
QList<TestDocumentPtr> testFiles;
|
||||
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"
|
||||
"\n"
|
||||
"int Foo::f2()\n"
|
||||
"{\n"
|
||||
" return 1;\n"
|
||||
"}\n\n";
|
||||
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
|
||||
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"void Foo::f1() {}\n"
|
||||
"void Foo::f3() {}\n";
|
||||
expected = original + "\n";
|
||||
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
|
||||
|
||||
MoveFuncDefOutside factory;
|
||||
TestCase data(testFiles);
|
||||
data.run(&factory, 1);
|
||||
}
|
||||
|
||||
/// Check: Move definition from header to cpp (with namespace).
|
||||
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS()
|
||||
{
|
||||
@@ -1849,8 +1891,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNS()
|
||||
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"\n";
|
||||
"#include \"file.h\"\n";
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
@@ -1895,8 +1936,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncToCppNSUsing()
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"using namespace MyNs;\n"
|
||||
"\n";
|
||||
"using namespace MyNs;\n";
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"using namespace MyNs;\n"
|
||||
@@ -1934,7 +1974,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutsideWithNs()
|
||||
"int Foo::number() const\n"
|
||||
"{\n"
|
||||
" return 5;\n"
|
||||
"}"
|
||||
"}\n"
|
||||
"\n}\n";
|
||||
|
||||
MoveFuncDefOutside factory;
|
||||
@@ -1962,8 +2002,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCpp()
|
||||
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"\n";
|
||||
"#include \"file.h\"\n";
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
@@ -2004,8 +2043,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_FreeFuncToCppNS()
|
||||
|
||||
// Source File
|
||||
original =
|
||||
"#include \"file.h\"\n"
|
||||
"\n";
|
||||
"#include \"file.h\"\n";
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
@@ -2053,6 +2091,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization1()
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Foo::Foo() : a(42), b(3.141) {}\n"
|
||||
"\n";
|
||||
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
|
||||
@@ -2096,6 +2135,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_CtorWithInitialization2()
|
||||
expected =
|
||||
"#include \"file.h\"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Foo::Foo() : member(2)\n"
|
||||
"{\n"
|
||||
"}\n"
|
||||
|
||||
@@ -143,6 +143,37 @@ enum DefPos {
|
||||
DefPosImplementationFile
|
||||
};
|
||||
|
||||
InsertionLocation insertLocationForMethodDefinition(Symbol *symbol,
|
||||
CppRefactoringChanges& refactoring,
|
||||
const QString& fileName)
|
||||
{
|
||||
QTC_ASSERT(symbol, return InsertionLocation());
|
||||
|
||||
// Try to find optimal location
|
||||
const InsertionPointLocator locator(refactoring);
|
||||
const QList<InsertionLocation> list = locator.methodDefinition(symbol, symbol->asDeclaration(),
|
||||
fileName);
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
InsertionLocation location = list.at(i);
|
||||
if (location.isValid() && location.fileName() == fileName) {
|
||||
return location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ...failed, so return location at end of file
|
||||
CppRefactoringFilePtr file = refactoring.file(fileName);
|
||||
const QTextDocument *doc = file->document();
|
||||
int pos = qMax(0, doc->characterCount() - 1);
|
||||
|
||||
//TODO watch for matching namespace
|
||||
//TODO watch for moc-includes
|
||||
|
||||
unsigned line, column;
|
||||
file->lineAndColumn(pos, &line, &column);
|
||||
return InsertionLocation(fileName, QLatin1String("\n\n"), QLatin1String("\n"), line, column);
|
||||
}
|
||||
|
||||
inline bool isQtStringLiteral(const QByteArray &id)
|
||||
{
|
||||
return id == "QLatin1String" || id == "QLatin1Literal" || id == "QStringLiteral";
|
||||
@@ -2549,11 +2580,6 @@ void InsertDefFromDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|
||||
if (func->isSignal())
|
||||
return;
|
||||
|
||||
InsertDefOperation *op = 0;
|
||||
bool isHeaderFile = false;
|
||||
const QString cppFileName = correspondingHeaderOrSource(
|
||||
interface->fileName(), &isHeaderFile);
|
||||
|
||||
// Check if there is already a definition
|
||||
CppTools::SymbolFinder symbolFinder;
|
||||
if (symbolFinder.findMatchingDefinition(decl, interface->snapshot(),
|
||||
@@ -2561,18 +2587,21 @@ void InsertDefFromDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|
||||
return;
|
||||
}
|
||||
|
||||
InsertDefOperation *op = 0;
|
||||
bool isHeaderFile = false;
|
||||
const QString cppFileName = correspondingHeaderOrSource(
|
||||
interface->fileName(), &isHeaderFile);
|
||||
InsertionLocation loc;
|
||||
|
||||
// Insert Position: Implementation File
|
||||
if (isHeaderFile && !cppFileName.isEmpty()) {
|
||||
CppRefactoringChanges refactoring(interface->snapshot());
|
||||
InsertionPointLocator locator(refactoring);
|
||||
foreach (const InsertionLocation &loc,
|
||||
locator.methodDefinition(decl)) {
|
||||
if (loc.isValid()) {
|
||||
op = new InsertDefOperation(interface, decl, loc,
|
||||
DefPosImplementationFile);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
break;
|
||||
}
|
||||
loc = insertLocationForMethodDefinition(decl, refactoring,
|
||||
cppFileName);
|
||||
if (loc.isValid()) {
|
||||
op = new InsertDefOperation(interface, decl, loc,
|
||||
DefPosImplementationFile);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2581,8 +2610,8 @@ void InsertDefFromDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|
||||
unsigned line, column;
|
||||
if (func->enclosingClass() == 0) {
|
||||
file->lineAndColumn(file->endOf(simpleDecl), &line, &column);
|
||||
InsertionLocation loc(interface->fileName(), QLatin1String(""),
|
||||
QLatin1String(""), line, column);
|
||||
loc = InsertionLocation(interface->fileName(), QLatin1String(""),
|
||||
QLatin1String(""), line, column);
|
||||
op = new InsertDefOperation(interface, decl, loc,
|
||||
DefPosInsideClass, true);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
@@ -2590,25 +2619,19 @@ void InsertDefFromDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|
||||
}
|
||||
|
||||
// Insert Position: Outside Class
|
||||
--idx;
|
||||
for (; idx >= 0; --idx) {
|
||||
AST *node = path.at(idx);
|
||||
if (ClassSpecifierAST *ast = node->asClassSpecifier()) {
|
||||
file->lineAndColumn(file->endOf(ast), &line, &column);
|
||||
InsertionLocation loc(interface->fileName(),
|
||||
QLatin1String("\n\n"), QLatin1String(""),
|
||||
line, column + 1); // include ';'
|
||||
op = new InsertDefOperation(interface, decl, loc,
|
||||
DefPosOutsideClass);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
break;
|
||||
}
|
||||
CppRefactoringChanges refactoring(interface->snapshot());
|
||||
loc = insertLocationForMethodDefinition(decl, refactoring,
|
||||
interface->fileName());
|
||||
if (loc.isValid()) {
|
||||
op = new InsertDefOperation(interface, decl, loc,
|
||||
DefPosOutsideClass);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
}
|
||||
|
||||
// Insert Position: Inside Class
|
||||
file->lineAndColumn(file->endOf(simpleDecl), &line, &column);
|
||||
InsertionLocation loc(interface->fileName(), QLatin1String(""),
|
||||
QLatin1String(""), line, column);
|
||||
loc = InsertionLocation(interface->fileName(), QLatin1String(""),
|
||||
QLatin1String(""), line, column);
|
||||
op = new InsertDefOperation(interface, decl, loc, DefPosInsideClass);
|
||||
result.append(CppQuickFixOperation::Ptr(op));
|
||||
return;
|
||||
@@ -3726,32 +3749,25 @@ public:
|
||||
{
|
||||
CppRefactoringChanges refactoring(snapshot());
|
||||
CppRefactoringFilePtr fromFile = refactoring.file(m_headerFileName);
|
||||
CppRefactoringFilePtr toFile;
|
||||
int insertPos = 0;
|
||||
Scope *scopeAtInsertPos = 0;
|
||||
CppRefactoringFilePtr toFile = (m_type == MoveOutside) ? fromFile
|
||||
: refactoring.file(m_cppFileName);
|
||||
|
||||
// Determine file, insert position and scope
|
||||
if (m_type == MoveOutside) {
|
||||
toFile = fromFile;
|
||||
insertPos = toFile->endOf(m_classAST);
|
||||
scopeAtInsertPos = m_func->enclosingScope()->enclosingScope();
|
||||
} else {
|
||||
toFile = refactoring.file(m_cppFileName);
|
||||
const QTextDocument *doc = toFile->document();
|
||||
insertPos = qMax(0, doc->characterCount() - 1);
|
||||
scopeAtInsertPos = toFile->cppDocument()->scopeAt(doc->lineCount(),
|
||||
doc->lastBlock().length());
|
||||
}
|
||||
InsertionLocation l = insertLocationForMethodDefinition(m_func, refactoring,
|
||||
toFile->fileName());
|
||||
const QString prefix = l.prefix();
|
||||
const QString suffix = l.suffix();
|
||||
const int insertPos = toFile->position(l.line(), l.column());
|
||||
Scope *scopeAtInsertPos = toFile->cppDocument()->scopeAt(l.line(), l.column());
|
||||
|
||||
// construct definition
|
||||
const QString funcDec = getDefinitionSignature(assistInterface(), m_func, toFile,
|
||||
scopeAtInsertPos);
|
||||
QString funcDef = QLatin1String("\n") + funcDec;
|
||||
QString funcDef = prefix + funcDec;
|
||||
const int startPosition = fromFile->endOf(m_funcDef->declarator);
|
||||
const int endPosition = fromFile->endOf(m_funcDef->function_body);
|
||||
funcDef += fromFile->textOf(startPosition, endPosition) + QLatin1String("\n");
|
||||
if (m_cppFileName.isEmpty() || !m_insideHeader)
|
||||
funcDef = QLatin1String("\n") + funcDef;
|
||||
funcDef += fromFile->textOf(startPosition, endPosition);
|
||||
funcDef += suffix;
|
||||
|
||||
// insert definition at new position
|
||||
ChangeSet cppChanges;
|
||||
|
||||
Reference in New Issue
Block a user