diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index e6cc0068250c76d32cc0332e808a9c4b08096e16..f15950bc71c8f520b99af7cf8c0aebcacb7c4339 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -162,6 +162,16 @@ private: IEditor *m_editor; }; +bool isProbablyGlobalCompletion(const QStringList &list) +{ + const int numberOfPrimitivesAndBasicKeywords = (T_LAST_PRIMITIVE - T_FIRST_PRIMITIVE) + + (T_FIRST_OBJC_AT_KEYWORD - T_FIRST_KEYWORD); + + return list.size() >= numberOfPrimitivesAndBasicKeywords + && list.contains(QLatin1String("if")) + && list.contains(QLatin1String("bool")); +} + } // anonymous namespace void CppToolsPlugin::test_completion_basic_1() @@ -327,6 +337,31 @@ void CppToolsPlugin::test_completion() QCOMPARE(actualCompletions, expectedCompletions); } +void CppToolsPlugin::test_global_completion_data() +{ + QTest::addColumn<QByteArray>("code"); + QTest::addColumn<QByteArray>("prefix"); + + // Check that special completion after '&' for Qt5 signal/slots does not + // interfere global completion after '&' + QTest::newRow("global completion after & in return expression") + << _("void f() { foo(myObject, @); }\n") + << _("&"); + QTest::newRow("global completion after & in function argument") + << _("int f() { return @; }\n") + << _("&"); +} + +void CppToolsPlugin::test_global_completion() +{ + QFETCH(QByteArray, code); + QFETCH(QByteArray, prefix); + + CompletionTestCase test(code, prefix); + QVERIFY(test.succeededSoFar()); + QVERIFY(isProbablyGlobalCompletion(test.getCompletions())); +} + static void enumTestCase(const QByteArray &tag, const QByteArray &source, const QByteArray &prefix = QByteArray()) { @@ -2337,14 +2372,6 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("hiddenFunction") << QLatin1String("hiddenSignal")); - QTest::newRow("Qt5 signals: no class name completion if not after 'connect(' 1") - << commonSignalSlotCompletionTestCode - << _("foo(myObject, &") << (QStringList()); - - QTest::newRow("Qt5 signals/slots: no class name completion if not after 'connect(' 2") - << commonSignalSlotCompletionTestCode - << _("&") << (QStringList()); - QTest::newRow("Qt5 signals: fallback to scope completion") << commonSignalSlotCompletionTestCode << _("connect(myObject, &N::") << (QStringList() diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index bb482038ec4de822a850fcf1c1633b39071c64bd..8811ae5132c120a294cae8037f5c9ff2114ddda3 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -1128,8 +1128,14 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper() // "connect(sender, &" or // "connect(otherSender, &Foo::signal1, receiver, &" const int beforeExpression = startOfExpression - 1; - if (canCompleteClassNameAt2ndOr4thConnectArgument(m_interface.data(), beforeExpression)) + if (canCompleteClassNameAt2ndOr4thConnectArgument(m_interface.data(), + beforeExpression)) { m_model->m_completionOperator = CompleteQt5SignalOrSlotClassNameTrigger; + } else { // Ensure global completion + startOfExpression = endOfExpression = m_startPosition; + expression.clear(); + m_model->m_completionOperator = T_EOF_SYMBOL; + } } else if (m_model->m_completionOperator == T_COLON_COLON) { // We expect 'expression' to be "Foo" in // "connect(sender, &Foo::" or diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 128d922085081c373a78c7814a93bd1cc69bf732..ea9cc91ed746894f0dc09795340b11021fa2518a 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -112,6 +112,9 @@ private slots: void test_completion_data(); void test_completion(); + void test_global_completion_data(); + void test_global_completion(); + void test_completion_member_access_operator_data(); void test_completion_member_access_operator();