From 273192759b08eb356db5492a686b8da6a0d8e3ab Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 10 Dec 2013 11:38:16 +0100 Subject: [PATCH] CppEditor/CppTools: Move FunctionHelper to CppTools ...and rename it to FunctionUtils. Change-Id: If076ec01fd82e8ba728764bdeab7e87e8bc1ff3b Reviewed-by: Erik Verbruggen --- src/plugins/cppeditor/cppeditorplugin.h | 3 - .../cppeditor/cppfollowsymbolundercursor.cpp | 5 +- .../cppvirtualfunctionassistprovider.cpp | 284 +--------------- .../cppvirtualfunctionassistprovider.h | 17 - src/plugins/cpptools/cpptools.pro | 6 +- src/plugins/cpptools/cpptools.qbs | 2 + src/plugins/cpptools/cpptoolsplugin.h | 3 + src/plugins/cpptools/functionutils.cpp | 321 ++++++++++++++++++ src/plugins/cpptools/functionutils.h | 68 ++++ 9 files changed, 404 insertions(+), 305 deletions(-) create mode 100644 src/plugins/cpptools/functionutils.cpp create mode 100644 src/plugins/cpptools/functionutils.h diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index e06355949b1..6ef87cf793e 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -206,9 +206,6 @@ private slots: void test_quickfix_InsertVirtualMethods_implementationFile(); void test_quickfix_InsertVirtualMethods_BaseClassInNamespace(); - void test_functionhelper_virtualFunctions(); - void test_functionhelper_virtualFunctions_data(); - // tests for "Include Hiererchy" void test_includeHierarchyModel_simpleIncludes(); void test_includeHierarchyModel_simpleIncludedBy(); diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 6b566f9f418..1b678ba33ca 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -128,12 +129,12 @@ bool VirtualFunctionHelper::canLookupVirtualFunctionOverrides(Function *function if (IdExpressionAST *idExpressionAST = m_baseExpressionAST->asIdExpression()) { NameAST *name = idExpressionAST->name; const bool nameIsQualified = name && name->asQualifiedName(); - result = !nameIsQualified && FunctionHelper::isVirtualFunction( + result = !nameIsQualified && FunctionUtils::isVirtualFunction( function, LookupContext(m_document, m_snapshot)); } else if (MemberAccessAST *memberAccessAST = m_baseExpressionAST->asMemberAccess()) { NameAST *name = memberAccessAST->member_name; const bool nameIsQualified = name && name->asQualifiedName(); - if (!nameIsQualified && FunctionHelper::isVirtualFunction( + if (!nameIsQualified && FunctionUtils::isVirtualFunction( function, LookupContext(m_document, m_snapshot))) { TranslationUnit *unit = m_expressionDocument->translationUnit(); QTC_ASSERT(unit, return false); diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index aff4973e05b..a3f70489092 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -55,6 +56,7 @@ using namespace CPlusPlus; using namespace CppEditor::Internal; +using namespace CppTools; using namespace TextEditor; /// Activate current item with the same shortcut that is configured for Follow Symbol Under Cursor. @@ -143,7 +145,7 @@ public: if (!functionsClass) return 0; - const QList overrides = FunctionHelper::overrides( + const QList overrides = FunctionUtils::overrides( m_params.function, functionsClass, m_params.staticClass, m_params.snapshot); if (overrides.isEmpty()) return 0; @@ -208,283 +210,3 @@ IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const { return new VirtualFunctionsAssistProcessor(m_params); } - -enum VirtualType { Virtual, PureVirtual }; - -static bool isVirtualFunction_helper(const Function *function, - const LookupContext &context, - VirtualType virtualType, - const Function **firstVirtual) -{ - enum { Unknown, False, True } res = Unknown; - - if (firstVirtual) - *firstVirtual = 0; - - if (!function) - return false; - - if (virtualType == PureVirtual) - res = function->isPureVirtual() ? True : False; - - if (function->isVirtual()) { - if (firstVirtual) - *firstVirtual = function; - if (res == Unknown) - res = True; - } - - if (!firstVirtual && res != Unknown) - return res == True; - - QList results = context.lookup(function->name(), function->enclosingScope()); - if (!results.isEmpty()) { - const bool isDestructor = function->name()->isDestructorNameId(); - foreach (const LookupItem &item, results) { - if (Symbol *symbol = item.declaration()) { - if (Function *functionType = symbol->type()->asFunctionType()) { - if (functionType->name()->isDestructorNameId() != isDestructor) - continue; - if (functionType == function) // already tested - continue; - if (functionType->isFinal()) - return res == True; - if (functionType->isVirtual()) { - if (!firstVirtual) - return true; - if (res == Unknown) - res = True; - *firstVirtual = functionType; - } - } - } - } - } - - return res == True; -} - -bool FunctionHelper::isVirtualFunction(const Function *function, - const LookupContext &context, - const Function **firstVirtual) -{ - return isVirtualFunction_helper(function, context, Virtual, firstVirtual); -} - -bool FunctionHelper::isPureVirtualFunction(const Function *function, - const LookupContext &context, - const Function **firstVirtual) -{ - return isVirtualFunction_helper(function, context, PureVirtual, firstVirtual); -} - -QList FunctionHelper::overrides(Function *function, Class *functionsClass, - Class *staticClass, const Snapshot &snapshot) -{ - QList result; - QTC_ASSERT(function && functionsClass && staticClass, return result); - - FullySpecifiedType referenceType = function->type(); - const Name *referenceName = function->name(); - QTC_ASSERT(referenceName && referenceType.isValid(), return result); - - // Find overrides - CppTools::TypeHierarchyBuilder builder(staticClass, snapshot); - const CppTools::TypeHierarchy &staticClassHierarchy = builder.buildDerivedTypeHierarchy(); - - QList l; - l.append(CppTools::TypeHierarchy(functionsClass)); - l.append(staticClassHierarchy); - - while (!l.isEmpty()) { - // Add derived - const CppTools::TypeHierarchy hierarchy = l.takeFirst(); - QTC_ASSERT(hierarchy.symbol(), continue); - Class *c = hierarchy.symbol()->asClass(); - QTC_ASSERT(c, continue); - - foreach (const CppTools::TypeHierarchy &t, hierarchy.hierarchy()) { - if (!l.contains(t)) - l << t; - } - - // Check member functions - for (int i = 0, total = c->memberCount(); i < total; ++i) { - Symbol *candidate = c->memberAt(i); - const Name *candidateName = candidate->name(); - const FullySpecifiedType candidateType = candidate->type(); - if (!candidateName || !candidateType.isValid()) - continue; - if (candidateName->isEqualTo(referenceName) && candidateType.isEqualTo(referenceType)) - result << candidate; - } - } - - return result; -} - -#ifdef WITH_TESTS -#include "cppeditorplugin.h" - -#include -#include - -namespace CppEditor { -namespace Internal { - -enum Virtuality -{ - NotVirtual, - Virtual, - PureVirtual -}; -typedef QList VirtualityList; -} // Internal namespace -} // CppEditor namespace - -Q_DECLARE_METATYPE(CppEditor::Internal::Virtuality) -Q_DECLARE_METATYPE(CppEditor::Internal::VirtualityList) -Q_DECLARE_METATYPE(QList) - -namespace CppEditor { -namespace Internal { - -void CppEditorPlugin::test_functionhelper_virtualFunctions() -{ - // Create and parse document - QFETCH(QByteArray, source); - QFETCH(VirtualityList, virtualityList); - QFETCH(QList, firstVirtualList); - Document::Ptr document = Document::create(QLatin1String("virtuals")); - document->setUtf8Source(source); - document->check(); // calls parse(); - QCOMPARE(document->diagnosticMessages().size(), 0); - QVERIFY(document->translationUnit()->ast()); - QList allFunctions; - const Function *firstVirtual = 0; - - // Iterate through Function symbols - Snapshot snapshot; - snapshot.insert(document); - const LookupContext context(document, snapshot); - Control *control = document->translationUnit()->control(); - Symbol **end = control->lastSymbol(); - for (Symbol **it = control->firstSymbol(); it != end; ++it) { - if (const Function *function = (*it)->asFunction()) { - allFunctions.append(function); - QTC_ASSERT(!virtualityList.isEmpty(), return); - Virtuality virtuality = virtualityList.takeFirst(); - QTC_ASSERT(!firstVirtualList.isEmpty(), return); - int firstVirtualIndex = firstVirtualList.takeFirst(); - bool isVirtual = FunctionHelper::isVirtualFunction(function, context, &firstVirtual); - bool isPureVirtual = FunctionHelper::isPureVirtualFunction(function, context, - &firstVirtual); - - // Test for regressions introduced by firstVirtual - QCOMPARE(FunctionHelper::isVirtualFunction(function, context), isVirtual); - QCOMPARE(FunctionHelper::isPureVirtualFunction(function, context), isPureVirtual); - if (isVirtual) { - if (isPureVirtual) - QCOMPARE(virtuality, PureVirtual); - else - QCOMPARE(virtuality, Virtual); - } else { - QEXPECT_FAIL("virtual-dtor-dtor", "Not implemented", Abort); - if (allFunctions.size() == 3) - QEXPECT_FAIL("dtor-virtual-dtor-dtor", "Not implemented", Abort); - QCOMPARE(virtuality, NotVirtual); - } - if (firstVirtualIndex == -1) - QVERIFY(!firstVirtual); - else - QCOMPARE(firstVirtual, allFunctions.at(firstVirtualIndex)); - } - } - QVERIFY(virtualityList.isEmpty()); - QVERIFY(firstVirtualList.isEmpty()); -} - -void CppEditorPlugin::test_functionhelper_virtualFunctions_data() -{ - typedef QByteArray _; - QTest::addColumn("source"); - QTest::addColumn("virtualityList"); - QTest::addColumn >("firstVirtualList"); - - QTest::newRow("none") - << _("struct None { void foo() {} };\n") - << (VirtualityList() << NotVirtual) - << (QList() << -1); - - QTest::newRow("single-virtual") - << _("struct V { virtual void foo() {} };\n") - << (VirtualityList() << Virtual) - << (QList() << 0); - - QTest::newRow("single-pure-virtual") - << _("struct PV { virtual void foo() = 0; };\n") - << (VirtualityList() << PureVirtual) - << (QList() << 0); - - QTest::newRow("virtual-derived-with-specifier") - << _("struct Base { virtual void foo() {} };\n" - "struct Derived : Base { virtual void foo() {} };\n") - << (VirtualityList() << Virtual << Virtual) - << (QList() << 0 << 0); - - QTest::newRow("virtual-derived-implicit") - << _("struct Base { virtual void foo() {} };\n" - "struct Derived : Base { void foo() {} };\n") - << (VirtualityList() << Virtual << Virtual) - << (QList() << 0 << 0); - - QTest::newRow("not-virtual-then-virtual") - << _("struct Base { void foo() {} };\n" - "struct Derived : Base { virtual void foo() {} };\n") - << (VirtualityList() << NotVirtual << Virtual) - << (QList() << -1 << 1); - - QTest::newRow("virtual-final-not-virtual") - << _("struct Base { virtual void foo() {} };\n" - "struct Derived : Base { void foo() final {} };\n" - "struct Derived2 : Derived { void foo() {} };") - << (VirtualityList() << Virtual << Virtual << NotVirtual) - << (QList() << 0 << 0 << -1); - - QTest::newRow("virtual-then-pure") - << _("struct Base { virtual void foo() {} };\n" - "struct Derived : Base { virtual void foo() = 0; };\n" - "struct Derived2 : Derived { void foo() {} };") - << (VirtualityList() << Virtual << PureVirtual << Virtual) - << (QList() << 0 << 0 << 0); - - QTest::newRow("virtual-virtual-final-not-virtual") - << _("struct Base { virtual void foo() {} };\n" - "struct Derived : Base { virtual void foo() final {} };\n" - "struct Derived2 : Derived { void foo() {} };") - << (VirtualityList() << Virtual << Virtual << NotVirtual) - << (QList() << 0 << 0 << -1); - - QTest::newRow("ctor-virtual-dtor") - << _("struct Base { Base() {} virtual ~Base() {} };\n") - << (VirtualityList() << NotVirtual << Virtual) - << (QList() << -1 << 1); - - QTest::newRow("virtual-dtor-dtor") - << _("struct Base { virtual ~Base() {} };\n" - "struct Derived : Base { ~Derived() {} };\n") - << (VirtualityList() << Virtual << Virtual) - << (QList() << 0 << 0); - - QTest::newRow("dtor-virtual-dtor-dtor") - << _("struct Base { ~Base() {} };\n" - "struct Derived : Base { virtual ~Derived() {} };\n" - "struct Derived2 : Derived { ~Derived2() {} };\n") - << (VirtualityList() << NotVirtual << Virtual << Virtual) - << (QList() << -1 << 1 << 1); -} - -} // namespace Internal -} // namespace CppEditor - -#endif diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h index 933fa3be4eb..731f1efc5ab 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h @@ -70,23 +70,6 @@ private: Parameters m_params; }; -class FunctionHelper -{ -public: - static bool isVirtualFunction(const CPlusPlus::Function *function, - const CPlusPlus::LookupContext &context, - const CPlusPlus::Function **firstVirtual = 0); - - static bool isPureVirtualFunction(const CPlusPlus::Function *function, - const CPlusPlus::LookupContext &context, - const CPlusPlus::Function **firstVirtual = 0); - - static QList overrides(CPlusPlus::Function *function, - CPlusPlus::Class *functionsClass, - CPlusPlus::Class *staticClass, - const CPlusPlus::Snapshot &snapshot); -}; - } // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 9700ea853a0..c75af62eb93 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -51,7 +51,8 @@ HEADERS += completionsettingspage.h \ cpplocatordata.h \ cppmodelmanagersupportinternal.h \ cppcodemodelsettings.h \ - cppcodemodelsettingspage.h + cppcodemodelsettingspage.h \ + functionutils.h SOURCES += completionsettingspage.cpp \ cppclassesfilter.cpp \ @@ -100,7 +101,8 @@ SOURCES += completionsettingspage.cpp \ cpplocatordata.cpp \ cppmodelmanagersupportinternal.cpp \ cppcodemodelsettings.cpp \ - cppcodemodelsettingspage.cpp + cppcodemodelsettingspage.cpp \ + functionutils.cpp FORMS += completionsettingspage.ui \ cppfilesettingspage.ui \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index e955c80e3ad..14dc119d61b 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -101,6 +101,8 @@ QtcPlugin { "cpptoolssettings.h", "doxygengenerator.cpp", "doxygengenerator.h", + "functionutils.cpp", + "functionutils.h", "insertionpointlocator.cpp", "insertionpointlocator.h", "searchsymbols.cpp", diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 94b30bf9e56..bb5cd9b3c66 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -204,6 +204,9 @@ private slots: void test_cpppreprocessor_includes(); + void test_functionutils_virtualFunctions(); + void test_functionutils_virtualFunctions_data(); + void test_modelmanager_paths_are_clean(); void test_modelmanager_framework_headers(); void test_modelmanager_refresh_also_includes_of_project_files(); diff --git a/src/plugins/cpptools/functionutils.cpp b/src/plugins/cpptools/functionutils.cpp new file mode 100644 index 00000000000..fd7ae1d89c8 --- /dev/null +++ b/src/plugins/cpptools/functionutils.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "functionutils.h" + +#include "typehierarchybuilder.h" + +#include +#include +#include +#include + +#include + +using namespace CPlusPlus; +using namespace CppTools; + +enum VirtualType { Virtual, PureVirtual }; + +static bool isVirtualFunction_helper(const Function *function, + const LookupContext &context, + VirtualType virtualType, + const Function **firstVirtual) +{ + enum { Unknown, False, True } res = Unknown; + + if (firstVirtual) + *firstVirtual = 0; + + if (!function) + return false; + + if (virtualType == PureVirtual) + res = function->isPureVirtual() ? True : False; + + if (function->isVirtual()) { + if (firstVirtual) + *firstVirtual = function; + if (res == Unknown) + res = True; + } + + if (!firstVirtual && res != Unknown) + return res == True; + + QList results = context.lookup(function->name(), function->enclosingScope()); + if (!results.isEmpty()) { + const bool isDestructor = function->name()->isDestructorNameId(); + foreach (const LookupItem &item, results) { + if (Symbol *symbol = item.declaration()) { + if (Function *functionType = symbol->type()->asFunctionType()) { + if (functionType->name()->isDestructorNameId() != isDestructor) + continue; + if (functionType == function) // already tested + continue; + if (functionType->isFinal()) + return res == True; + if (functionType->isVirtual()) { + if (!firstVirtual) + return true; + if (res == Unknown) + res = True; + *firstVirtual = functionType; + } + } + } + } + } + + return res == True; +} + +bool FunctionUtils::isVirtualFunction(const Function *function, + const LookupContext &context, + const Function **firstVirtual) +{ + return isVirtualFunction_helper(function, context, Virtual, firstVirtual); +} + +bool FunctionUtils::isPureVirtualFunction(const Function *function, + const LookupContext &context, + const Function **firstVirtual) +{ + return isVirtualFunction_helper(function, context, PureVirtual, firstVirtual); +} + +QList FunctionUtils::overrides(Function *function, Class *functionsClass, + Class *staticClass, const Snapshot &snapshot) +{ + QList result; + QTC_ASSERT(function && functionsClass && staticClass, return result); + + FullySpecifiedType referenceType = function->type(); + const Name *referenceName = function->name(); + QTC_ASSERT(referenceName && referenceType.isValid(), return result); + + // Find overrides + TypeHierarchyBuilder builder(staticClass, snapshot); + const TypeHierarchy &staticClassHierarchy = builder.buildDerivedTypeHierarchy(); + + QList l; + l.append(TypeHierarchy(functionsClass)); + l.append(staticClassHierarchy); + + while (!l.isEmpty()) { + // Add derived + const TypeHierarchy hierarchy = l.takeFirst(); + QTC_ASSERT(hierarchy.symbol(), continue); + Class *c = hierarchy.symbol()->asClass(); + QTC_ASSERT(c, continue); + + foreach (const TypeHierarchy &t, hierarchy.hierarchy()) { + if (!l.contains(t)) + l << t; + } + + // Check member functions + for (int i = 0, total = c->memberCount(); i < total; ++i) { + Symbol *candidate = c->memberAt(i); + const Name *candidateName = candidate->name(); + const FullySpecifiedType candidateType = candidate->type(); + if (!candidateName || !candidateType.isValid()) + continue; + if (candidateName->isEqualTo(referenceName) && candidateType.isEqualTo(referenceType)) + result << candidate; + } + } + + return result; +} + +#ifdef WITH_TESTS +#include "cpptoolsplugin.h" + +#include + +namespace CppTools { +namespace Internal { + +enum Virtuality +{ + NotVirtual, + Virtual, + PureVirtual +}; +typedef QList VirtualityList; +} // Internal namespace +} // CppTools namespace + +Q_DECLARE_METATYPE(CppTools::Internal::Virtuality) +Q_DECLARE_METATYPE(CppTools::Internal::VirtualityList) +Q_DECLARE_METATYPE(QList) + +namespace CppTools { +namespace Internal { + +void CppToolsPlugin::test_functionutils_virtualFunctions() +{ + // Create and parse document + QFETCH(QByteArray, source); + QFETCH(VirtualityList, virtualityList); + QFETCH(QList, firstVirtualList); + Document::Ptr document = Document::create(QLatin1String("virtuals")); + document->setUtf8Source(source); + document->check(); // calls parse(); + QCOMPARE(document->diagnosticMessages().size(), 0); + QVERIFY(document->translationUnit()->ast()); + QList allFunctions; + const Function *firstVirtual = 0; + + // Iterate through Function symbols + Snapshot snapshot; + snapshot.insert(document); + const LookupContext context(document, snapshot); + Control *control = document->translationUnit()->control(); + Symbol **end = control->lastSymbol(); + for (Symbol **it = control->firstSymbol(); it != end; ++it) { + if (const Function *function = (*it)->asFunction()) { + allFunctions.append(function); + QTC_ASSERT(!virtualityList.isEmpty(), return); + Virtuality virtuality = virtualityList.takeFirst(); + QTC_ASSERT(!firstVirtualList.isEmpty(), return); + int firstVirtualIndex = firstVirtualList.takeFirst(); + bool isVirtual = FunctionUtils::isVirtualFunction(function, context, &firstVirtual); + bool isPureVirtual = FunctionUtils::isPureVirtualFunction(function, context, + &firstVirtual); + + // Test for regressions introduced by firstVirtual + QCOMPARE(FunctionUtils::isVirtualFunction(function, context), isVirtual); + QCOMPARE(FunctionUtils::isPureVirtualFunction(function, context), isPureVirtual); + if (isVirtual) { + if (isPureVirtual) + QCOMPARE(virtuality, PureVirtual); + else + QCOMPARE(virtuality, Virtual); + } else { + QEXPECT_FAIL("virtual-dtor-dtor", "Not implemented", Abort); + if (allFunctions.size() == 3) + QEXPECT_FAIL("dtor-virtual-dtor-dtor", "Not implemented", Abort); + QCOMPARE(virtuality, NotVirtual); + } + if (firstVirtualIndex == -1) + QVERIFY(!firstVirtual); + else + QCOMPARE(firstVirtual, allFunctions.at(firstVirtualIndex)); + } + } + QVERIFY(virtualityList.isEmpty()); + QVERIFY(firstVirtualList.isEmpty()); +} + +void CppToolsPlugin::test_functionutils_virtualFunctions_data() +{ + typedef QByteArray _; + QTest::addColumn("source"); + QTest::addColumn("virtualityList"); + QTest::addColumn >("firstVirtualList"); + + QTest::newRow("none") + << _("struct None { void foo() {} };\n") + << (VirtualityList() << NotVirtual) + << (QList() << -1); + + QTest::newRow("single-virtual") + << _("struct V { virtual void foo() {} };\n") + << (VirtualityList() << Virtual) + << (QList() << 0); + + QTest::newRow("single-pure-virtual") + << _("struct PV { virtual void foo() = 0; };\n") + << (VirtualityList() << PureVirtual) + << (QList() << 0); + + QTest::newRow("virtual-derived-with-specifier") + << _("struct Base { virtual void foo() {} };\n" + "struct Derived : Base { virtual void foo() {} };\n") + << (VirtualityList() << Virtual << Virtual) + << (QList() << 0 << 0); + + QTest::newRow("virtual-derived-implicit") + << _("struct Base { virtual void foo() {} };\n" + "struct Derived : Base { void foo() {} };\n") + << (VirtualityList() << Virtual << Virtual) + << (QList() << 0 << 0); + + QTest::newRow("not-virtual-then-virtual") + << _("struct Base { void foo() {} };\n" + "struct Derived : Base { virtual void foo() {} };\n") + << (VirtualityList() << NotVirtual << Virtual) + << (QList() << -1 << 1); + + QTest::newRow("virtual-final-not-virtual") + << _("struct Base { virtual void foo() {} };\n" + "struct Derived : Base { void foo() final {} };\n" + "struct Derived2 : Derived { void foo() {} };") + << (VirtualityList() << Virtual << Virtual << NotVirtual) + << (QList() << 0 << 0 << -1); + + QTest::newRow("virtual-then-pure") + << _("struct Base { virtual void foo() {} };\n" + "struct Derived : Base { virtual void foo() = 0; };\n" + "struct Derived2 : Derived { void foo() {} };") + << (VirtualityList() << Virtual << PureVirtual << Virtual) + << (QList() << 0 << 0 << 0); + + QTest::newRow("virtual-virtual-final-not-virtual") + << _("struct Base { virtual void foo() {} };\n" + "struct Derived : Base { virtual void foo() final {} };\n" + "struct Derived2 : Derived { void foo() {} };") + << (VirtualityList() << Virtual << Virtual << NotVirtual) + << (QList() << 0 << 0 << -1); + + QTest::newRow("ctor-virtual-dtor") + << _("struct Base { Base() {} virtual ~Base() {} };\n") + << (VirtualityList() << NotVirtual << Virtual) + << (QList() << -1 << 1); + + QTest::newRow("virtual-dtor-dtor") + << _("struct Base { virtual ~Base() {} };\n" + "struct Derived : Base { ~Derived() {} };\n") + << (VirtualityList() << Virtual << Virtual) + << (QList() << 0 << 0); + + QTest::newRow("dtor-virtual-dtor-dtor") + << _("struct Base { ~Base() {} };\n" + "struct Derived : Base { virtual ~Derived() {} };\n" + "struct Derived2 : Derived { ~Derived2() {} };\n") + << (VirtualityList() << NotVirtual << Virtual << Virtual) + << (QList() << -1 << 1 << 1); +} + +} // namespace Internal +} // namespace CppTools + +#endif diff --git a/src/plugins/cpptools/functionutils.h b/src/plugins/cpptools/functionutils.h new file mode 100644 index 00000000000..d44231cc19a --- /dev/null +++ b/src/plugins/cpptools/functionutils.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef FUNCTIONUTILS_H +#define FUNCTIONUTILS_H + +#include "cpptools_global.h" + +QT_BEGIN_NAMESPACE +template class QList; +QT_END_NAMESPACE + +namespace CPlusPlus { +class Class; +class Function; +class LookupContext; +class Snapshot; +class Symbol; +} // namespace CPlusPlus + +namespace CppTools { + +class CPPTOOLS_EXPORT FunctionUtils +{ +public: + static bool isVirtualFunction(const CPlusPlus::Function *function, + const CPlusPlus::LookupContext &context, + const CPlusPlus::Function **firstVirtual = 0); + + static bool isPureVirtualFunction(const CPlusPlus::Function *function, + const CPlusPlus::LookupContext &context, + const CPlusPlus::Function **firstVirtual = 0); + + static QList overrides(CPlusPlus::Function *function, + CPlusPlus::Class *functionsClass, + CPlusPlus::Class *staticClass, + const CPlusPlus::Snapshot &snapshot); +}; + +} // namespace CppTools + +#endif // FUNCTIONUTILS_H