summaryrefslogtreecommitdiff
path: root/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2013-07-04 20:11:10 +0200
committerNikolai Kosjar <nikolai.kosjar@digia.com>2013-10-01 14:23:00 +0200
commit11aeaea86f99bb00ef328c6f439d5549131cfc28 (patch)
treecc15cb55e6b7e6ad0d65065b49506c7f979e8d51 /src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
parent3a64f8a344b1c702f66331a4fa21807f0a017762 (diff)
downloadqt-creator-11aeaea86f99bb00ef328c6f439d5549131cfc28.tar.gz
CppEditor: "Follow Symbol Under Cursor" for virtual functions
F2 on a virtual function call presents a list of overrides in derived classes. The function declaration of the static type is shown immediately at the top. Task-number: QTCREATORBUG-9611 Change-Id: I80ce906fa06272dc9fbd1662cd17500b8c77067f Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp')
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp346
1 files changed, 306 insertions, 40 deletions
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 46ff3e159b..f922b20de3 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -29,8 +29,13 @@
#include "cppeditor.h"
#include "cppeditorplugin.h"
+#include "cppelementevaluator.h"
+#include "cppvirtualfunctionassistprovider.h"
#include <coreplugin/plugintestutils.h>
+#include <texteditor/codeassist/iassistproposal.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/codeassist/basicproposalitemlistmodel.h>
#include <utils/fileutils.h>
#include <QDebug>
@@ -57,6 +62,60 @@ using namespace Core;
namespace {
+/// A fake virtual functions assist provider that runs processor->perform() already in configure()
+class VirtualFunctionTestAssistProvider : public VirtualFunctionAssistProvider
+{
+public:
+ VirtualFunctionTestAssistProvider(CPPEditorWidget *editorWidget)
+ : m_editorWidget(editorWidget)
+ {}
+
+ // Invoke the processor already here to calculate the proposals. Return false in order to
+ // indicate that configure failed, so the actual code assist invocation leading to a pop-up
+ // will not happen.
+ bool configure(CPlusPlus::Class *startClass, CPlusPlus::Function *function,
+ const CPlusPlus::Snapshot &snapshot, bool openInNextSplit)
+ {
+ VirtualFunctionAssistProvider::configure(startClass, function, snapshot, openInNextSplit);
+
+ IAssistProcessor *processor = createProcessor();
+ IAssistInterface *interface = m_editorWidget->createAssistInterface(FollowSymbol,
+ ExplicitlyInvoked);
+ IAssistProposal *immediateProposal = processor->immediateProposal(interface);
+ IAssistProposal *finalProposal = processor->perform(interface);
+
+ m_immediateItems = itemList(immediateProposal->model());
+ m_finalItems = itemList(finalProposal->model());
+
+ return false;
+ }
+
+ static QStringList itemList(IAssistProposalModel *imodel)
+ {
+ QStringList immediateItems;
+ BasicProposalItemListModel *model = dynamic_cast<BasicProposalItemListModel *>(imodel);
+ if (!model)
+ return immediateItems;
+ if (model->isSortable(QString()))
+ model->sort(QString());
+ model->removeDuplicates();
+
+ for (int i = 0, size = model->size(); i < size; ++i) {
+ const QString text = model->text(i);
+ immediateItems.append(text);
+ }
+
+ return immediateItems;
+ }
+
+public:
+ QStringList m_immediateItems;
+ QStringList m_finalItems;
+
+private:
+ CPPEditorWidget *m_editorWidget;
+};
+
class TestDocument;
typedef QSharedPointer<TestDocument> TestDocumentPtr;
@@ -136,12 +195,16 @@ class TestCase
{
public:
enum CppEditorAction {
- FollowSymbolUnderCursor,
- SwitchBetweenMethodDeclarationDefinition
+ FollowSymbolUnderCursorAction,
+ SwitchBetweenMethodDeclarationDefinitionAction
};
- TestCase(CppEditorAction action, const QByteArray &source);
- TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles);
+ TestCase(CppEditorAction action, const QByteArray &source,
+ const QStringList &expectedVirtualFunctionImmediateProposal = QStringList(),
+ const QStringList &expectedVirtualFunctionFinalProposal = QStringList());
+ TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles,
+ const QStringList &expectedVirtualSymbolsImmediateProposal = QStringList(),
+ const QStringList &expectedVirtualSymbolsFinalProposal = QStringList());
~TestCase();
void run(bool expectedFail = false);
@@ -158,12 +221,18 @@ private:
private:
CppEditorAction m_action;
QList<TestDocumentPtr> m_testFiles;
+ QStringList m_expectedVirtualSymbolsImmediateProposal; // for virtual functions
+ QStringList m_expectedVirtualSymbolsFinalProposals; // for virtual functions
};
/// Convenience function for creating a TestDocument.
/// See TestDocument.
-TestCase::TestCase(CppEditorAction action, const QByteArray &source)
+TestCase::TestCase(CppEditorAction action, const QByteArray &source,
+ const QStringList &expectedVirtualFunctionImmediateProposal,
+ const QStringList &expectedVirtualFunctionFinalProposal)
: m_action(action)
+ , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualFunctionImmediateProposal)
+ , m_expectedVirtualSymbolsFinalProposals(expectedVirtualFunctionFinalProposal)
{
m_testFiles << TestDocument::create(source, QLatin1String("file.cpp"));
init();
@@ -173,9 +242,13 @@ TestCase::TestCase(CppEditorAction action, const QByteArray &source)
/// Exactly one test document must be provided that contains '@', the initial position marker.
/// Exactly one test document must be provided that contains '$', the target position marker.
/// It can be the same document.
-TestCase::TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles)
+TestCase::TestCase(CppEditorAction action, const QList<TestDocumentPtr> theTestFiles,
+ const QStringList &expectedVirtualSymbolsImmediateProposal,
+ const QStringList &expectedVirtualSymbolsFinalProposal)
: m_action(action)
, m_testFiles(theTestFiles)
+ , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualSymbolsImmediateProposal)
+ , m_expectedVirtualSymbolsFinalProposals(expectedVirtualSymbolsFinalProposal)
{
init();
}
@@ -292,12 +365,29 @@ void TestCase::run(bool expectedFail)
// qDebug() << "Initial line:" << initialTestFile->editor->currentLine();
// qDebug() << "Initial column:" << initialTestFile->editor->currentColumn() - 1;
+ QStringList immediateVirtualSymbolResults;
+ QStringList finalVirtualSymbolResults;
+
// Trigger the action
switch (m_action) {
- case FollowSymbolUnderCursor:
+ case FollowSymbolUnderCursorAction: {
+ CPPEditorWidget *widget = initialTestFile->editorWidget;
+ FollowSymbolUnderCursor *delegate = widget->followSymbolUnderCursorDelegate();
+ VirtualFunctionAssistProvider *original = delegate->virtualFunctionAssistProvider();
+
+ // Set test provider, run and get results
+ QScopedPointer<VirtualFunctionTestAssistProvider> testProvider(
+ new VirtualFunctionTestAssistProvider(widget));
+ delegate->setVirtualFunctionAssistProvider(testProvider.data());
initialTestFile->editorWidget->openLinkUnderCursor();
+ immediateVirtualSymbolResults = testProvider->m_immediateItems;
+ finalVirtualSymbolResults = testProvider->m_finalItems;
+
+ // Restore original test provider
+ delegate->setVirtualFunctionAssistProvider(original);
break;
- case SwitchBetweenMethodDeclarationDefinition:
+ }
+ case SwitchBetweenMethodDeclarationDefinitionAction:
CppEditorPlugin::instance()->switchDeclarationDefinition();
break;
default:
@@ -318,10 +408,16 @@ void TestCase::run(bool expectedFail)
&expectedLine, &expectedColumn);
// qDebug() << "Expected line:" << expectedLine;
// qDebug() << "Expected column:" << expectedColumn;
+
if (expectedFail)
QEXPECT_FAIL("", "Contributor works on a fix.", Abort);
QCOMPARE(currentTextEditor->currentLine(), expectedLine);
QCOMPARE(currentTextEditor->currentColumn() - 1, expectedColumn);
+
+// qDebug() << immediateVirtualSymbolResults;
+// qDebug() << finalVirtualSymbolResults;
+ QCOMPARE(immediateVirtualSymbolResults, m_expectedVirtualSymbolsImmediateProposal);
+ QCOMPARE(finalVirtualSymbolResults, m_expectedVirtualSymbolsFinalProposals);
}
} // anonymous namespace
@@ -354,7 +450,7 @@ void CppEditorPlugin::test_SwitchMethodDeclarationDefinition_fromFunctionDeclara
;
testFiles << TestDocument::create(sourceContents, QLatin1String("file.cpp"));
- TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinition, testFiles);
+ TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinitionAction, testFiles);
test.run();
}
@@ -386,7 +482,7 @@ void CppEditorPlugin::test_SwitchMethodDeclarationDefinition_fromFunctionDefinit
;
testFiles << TestDocument::create(sourceContents, QLatin1String("file.cpp"));
- TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinition, testFiles);
+ TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinitionAction, testFiles);
test.run();
}
@@ -418,7 +514,7 @@ void CppEditorPlugin::test_SwitchMethodDeclarationDefinition_fromFunctionBody()
;
testFiles << TestDocument::create(sourceContents, QLatin1String("file.cpp"));
- TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinition, testFiles);
+ TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinitionAction, testFiles);
test.run();
}
@@ -450,7 +546,7 @@ void CppEditorPlugin::test_SwitchMethodDeclarationDefinition_fromReturnType()
;
testFiles << TestDocument::create(sourceContents, QLatin1String("file.cpp"));
- TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinition, testFiles);
+ TestCase test(TestCase::SwitchBetweenMethodDeclarationDefinitionAction, testFiles);
test.run();
}
@@ -465,7 +561,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_globalVarFromFunction()
"}\n" // Line 5
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -483,7 +579,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesClassMember()
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -503,7 +599,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesNamespaceMemb
"}\n" // Line 10
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -521,7 +617,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVa
"}\n";
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -539,7 +635,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVa
"}\n";
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -553,7 +649,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_subsequentDefinedClassMember(
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -569,7 +665,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_classMemberHidesOuterTypeDef(
"};\n" // Line 5
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -584,7 +680,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_globalVarFromEnum()
"}\n" // Line 5
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run(/*expectedFail =*/ true);
}
@@ -599,7 +695,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_selfInitialization()
"}\n" // Line 5
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -612,7 +708,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_pointerToClassInClassDefiniti
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -626,7 +722,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_previouslyDefinedMemberFromAr
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -648,7 +744,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_outerStaticMemberVariableFrom
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -668,7 +764,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_memberVariableFollowingDotOpe
"}\n" // Line 10
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -688,7 +784,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_memberVariableFollowingArrowO
"}\n" // Line 10
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -707,7 +803,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowing
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -727,7 +823,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowing
"}\n" // Line 10
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -748,7 +844,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowing
"}\n" // Line 10
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -762,7 +858,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_previouslyDefinedEnumValueFro
"};\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -785,7 +881,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_nsMemberHidesNsMemberIntroduc
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -812,7 +908,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_baseClassFunctionIntroducedBy
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -839,7 +935,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_funWithSameNameAsBaseClassFun
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -858,7 +954,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass()
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -876,7 +972,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_classConstructor()
"{\n"
"}\n";
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -894,7 +990,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_classDestructor()
"{\n"
"}\n";
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -988,7 +1084,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_QObject_connect()
return;
}
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -1005,7 +1101,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_global
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -1024,7 +1120,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_namesp
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}
@@ -1041,7 +1137,177 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_using_QTCREATORBUG7903_inside
"}\n"
;
- TestCase test(TestCase::FollowSymbolUnderCursor, source);
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
+ test.run();
+}
+
+/// Check: Static type is base class pointer, all overrides are presented.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_allOverrides()
+{
+ const QByteArray source =
+ "struct A { virtual void virt() = 0; };\n"
+ "void A::virt() {}\n"
+ "\n"
+ "struct B : A { void virt(); };\n"
+ "void B::virt() {}\n"
+ "\n"
+ "struct C : B { void virt(); };\n"
+ "void C::virt() {}\n"
+ "\n"
+ "struct CD1 : C { void virt(); };\n"
+ "void CD1::virt() {}\n"
+ "\n"
+ "struct CD2 : C { void virt(); };\n"
+ "void CD2::virt() {}\n"
+ "\n"
+ "int f(A *o)\n"
+ "{\n"
+ " o->$@virt();\n"
+ "}\n"
+ ;
+
+ const QStringList immediateResults = QStringList()
+ << QLatin1String("A::virt")
+ << QLatin1String("...searching overrides");
+ const QStringList finalResults = QStringList()
+ << QLatin1String("A::virt")
+ << QLatin1String("A::virt") // TODO: Double entry
+ << QLatin1String("B::virt")
+ << QLatin1String("C::virt")
+ << QLatin1String("CD1::virt")
+ << QLatin1String("CD2::virt");
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: Static type is derived class pointer, only overrides of sub classes are presented.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides1()
+{
+ const QByteArray source =
+ "struct A { virtual void virt() = 0; };\n"
+ "void A::virt() {}\n"
+ "\n"
+ "struct B : A { void virt(); };\n"
+ "void B::virt() {}\n"
+ "\n"
+ "struct C : B { void virt(); };\n"
+ "void C::virt() {}\n"
+ "\n"
+ "struct CD1 : C { void virt(); };\n"
+ "void CD1::virt() {}\n"
+ "\n"
+ "struct CD2 : C { void virt(); };\n"
+ "void CD2::virt() {}\n"
+ "\n"
+ "int f(B *o)\n"
+ "{\n"
+ " o->$@virt();\n"
+ "}\n"
+ ;
+
+ const QStringList immediateResults = QStringList()
+ << QLatin1String("B::virt")
+ << QLatin1String("...searching overrides");
+ const QStringList finalResults = QStringList()
+ << QLatin1String("B::virt")
+ << QLatin1String("B::virt") // Double entry
+ << QLatin1String("C::virt")
+ << QLatin1String("CD1::virt")
+ << QLatin1String("CD2::virt");
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: Virtual function call in member of class hierarchy, only possible overrides are presented.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2()
+{
+ const QByteArray source =
+ "struct A { virtual void f(); };\n"
+ "void A::f() {}\n"
+ "\n"
+ "struct B : public A { void f(); };\n"
+ "void B::f() {}\n"
+ "\n"
+ "struct C : public B { void g() { f$@(); } }; \n"
+ "\n"
+ "struct D : public C { void f(); };\n"
+ "void D::f() {}\n"
+ ;
+
+ const QStringList immediateResults = QStringList()
+ << QLatin1String("B::f")
+ << QLatin1String("...searching overrides");
+ const QStringList finalResults = QStringList()
+ << QLatin1String("B::f")
+ << QLatin1String("B::f")
+ << QLatin1String("D::f");
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults);
+ test.run();
+}
+
+/// Check: Do not trigger on qualified function calls.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified()
+{
+ const QByteArray source =
+ "struct A { virtual void f(); };\n"
+ "void A::$f() {}\n"
+ "\n"
+ "struct B : public A {\n"
+ " void f();\n"
+ " void g() { A::@f(); }\n"
+ "};\n"
+ ;
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
+ test.run();
+}
+
+/// Check: Do not trigger on member function declaration.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDeclaration()
+{
+ const QByteArray source =
+ "struct A { virtual void f(); };\n"
+ "void A::f() {}\n"
+ "\n"
+ "struct B : public A { void f@(); };\n"
+ "void B::$f() {}\n"
+ ;
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
+ test.run();
+}
+
+/// Check: Do not trigger on function definition.
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefinition()
+{
+ const QByteArray source =
+ "struct A { virtual void f(); };\n"
+ "void A::f() {}\n"
+ "\n"
+ "struct B : public A { void $f(); };\n"
+ "void B::@f() {}\n"
+ ;
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
+ test.run();
+}
+
+void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnNonPointerNonReference()
+{
+ const QByteArray source =
+ "struct A { virtual void f(); };\n"
+ "void A::f() {}\n"
+ "\n"
+ "struct B : public A { void f(); };\n"
+ "void B::$f() {}\n"
+ "\n"
+ "void client(B b) { b.@f(); }\n"
+ ;
+
+ TestCase test(TestCase::FollowSymbolUnderCursorAction, source);
test.run();
}