diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 17fa3497d42..920e2a73088 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -124,6 +124,7 @@ private slots: void test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespaceToCpp(); void test_quickfix_ConvertQt4Connect_connectOutOfClass(); + void test_quickfix_ConvertQt4Connect_connectWithinClass_data(); void test_quickfix_ConvertQt4Connect_connectWithinClass(); void test_quickfix_InsertDefFromDecl_afterClass(); diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 244e922d5b6..5f13f8dfeda 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -3860,8 +3860,25 @@ void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectOutOfClass() QuickFixTestCase(testFiles, &factory); } +void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectWithinClass_data() +{ + QTest::addColumn("original"); + QTest::addColumn("expected"); + + QTest::newRow("case1") + << QByteArray("conne@ct(this, SIGNAL(sigFoo(int)), this, SLOT(setProp(int)));") + << QByteArray("connect(this, &TestClass::sigFoo, this, &TestClass::setProp);"); + + QTest::newRow("case2") + << QByteArray("conne@ct(this, SIGNAL(sigFoo(int)), SLOT(setProp(int)));") + << QByteArray("connect(this, &TestClass::sigFoo, this, &TestClass::setProp);"); +} + void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectWithinClass() { + QFETCH(QByteArray, original); + QFETCH(QByteArray, expected); + QByteArray prefix = "class QObject {};\n" "class TestClass : public QObject\n" @@ -3877,16 +3894,10 @@ void CppEditorPlugin::test_quickfix_ConvertQt4Connect_connectWithinClass() QByteArray suffix = "\n}\n"; - QByteArray original = prefix - + " conne@ct(this, SIGNAL(sigFoo(int)), this, SLOT(setProp(int)));" - + suffix; - - QByteArray expected = prefix - + " connect(this, &TestClass::sigFoo, this, &TestClass::setProp);" - + suffix; - QList testFiles; - testFiles << QuickFixTestDocument::create("file.cpp", original, expected); + testFiles << QuickFixTestDocument::create("file.cpp", + prefix + original + suffix, + prefix + expected + suffix); ConvertQt4Connect factory; QuickFixTestCase(testFiles, &factory); diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 36d274b6e35..429925e9126 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -5323,15 +5323,21 @@ Symbol *skipForwardDeclarations(const QList &symbols) Class *senderOrReceiverClass(const CppQuickFixInterface &interface, const CppRefactoringFilePtr &file, - const ExpressionAST *objectPointerAST) + const ExpressionAST *objectPointerAST, + Scope *objectPointerScope) { const LookupContext &context = interface.context(); - Scope *scope = file->scopeAt(objectPointerAST->firstToken()); + + QByteArray objectPointerExpression; + if (objectPointerAST) + objectPointerExpression = file->textOf(objectPointerAST).toUtf8(); + else + objectPointerExpression = "this"; TypeOfExpression toe; toe.init(interface.semanticInfo().doc, interface.snapshot(), context.bindings()); - const QList objectPointerExpressions = toe(file->textOf(objectPointerAST).toUtf8(), - scope, TypeOfExpression::Preprocess); + const QList objectPointerExpressions = toe(objectPointerExpression, + objectPointerScope, TypeOfExpression::Preprocess); QTC_ASSERT(objectPointerExpressions.size() == 1, return 0); Type *objectPointerTypeBase = objectPointerExpressions.first().type().type(); @@ -5346,7 +5352,7 @@ Class *senderOrReceiverClass(const CppQuickFixInterface &interface, NamedType *objectType = objectTypeBase->asNamedType(); QTC_ASSERT(objectType, return 0); - ClassOrNamespace *objectClassCON = context.lookupType(objectType->name(), scope); + ClassOrNamespace *objectClassCON = context.lookupType(objectType->name(), objectPointerScope); QTC_ASSERT(objectClassCON, return 0); QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0); @@ -5375,7 +5381,8 @@ bool findConnectReplacement(const CppQuickFixInterface &interface, return false; // Lookup object pointer type - Class *objectClass = senderOrReceiverClass(interface, file, objectPointerAST); + Scope *scope = file->scopeAt(methodAST->firstToken()); + Class *objectClass = senderOrReceiverClass(interface, file, objectPointerAST, scope); QTC_ASSERT(objectClass, return false); // Look up member function in call, including base class members. @@ -5394,7 +5401,6 @@ bool findConnectReplacement(const CppQuickFixInterface &interface, QTC_ASSERT(method, return false); // Minimize qualification - Scope *scope = file->scopeAt(objectPointerAST->firstToken()); Control *control = context.bindings()->control().data(); ClassOrNamespace *functionCON = context.lookupParent(scope); const Name *shortName = LookupContext::minimalName(method, functionCON, control); @@ -5458,8 +5464,18 @@ bool collectConnectArguments(const ExpressionListAST *arguments, return false; *arg3 = arguments->value; + if (!*arg3) + return false; + + // Take care of three-arg version, with 'this' receiver. + if (QtMethodAST *receiverMethod = arguments->value->asQtMethod()) { + *arg3 = 0; // Means 'this' + *arg4 = receiverMethod; + return true; + } + arguments = arguments->next; - if (!*arg3 || !arguments) + if (!arguments) return false; *arg4 = arguments->value->asQtMethod(); @@ -5497,6 +5513,8 @@ void ConvertQt4Connect::match(const CppQuickFixInterface &interface, QuickFixOpe ChangeSet changes; changes.replace(file->startOf(arg2), file->endOf(arg2), newSignal); + if (!arg3) + newMethod.prepend(QLatin1String("this, ")); changes.replace(file->startOf(arg4), file->endOf(arg4), newMethod); result.append(new ConvertQt4ConnectOperation(interface, changes));