diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 0ed9233d0ef..10ddd4d4937 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -55,22 +55,60 @@ typedef BaseTextEditorWidget::Link Link; namespace { -bool lookupVirtualFunctionOverrides(TypeOfExpression &typeOfExpression, - const Document::Ptr &document, - const Function *function, - Scope *scope, - const Snapshot &snapshot) -{ - if (!document || !function || !scope || scope->isClass() || snapshot.isEmpty()) - return false; +class VirtualFunctionHelper { +public: + VirtualFunctionHelper(const TypeOfExpression &typeOfExpression, + Scope *scope, + const Document::Ptr &document, + const Snapshot &snapshot); - ExpressionAST *expressionAST = typeOfExpression.expressionAST(); - if (!expressionAST) + bool canLookupVirtualFunctionOverrides(const Function *function) const; + +private: + VirtualFunctionHelper(); + Q_DISABLE_COPY(VirtualFunctionHelper) + + ExpressionAST *getBaseExpressionAST() const + { + if (!m_expressionAST) + return 0; + CallAST *callAST = m_expressionAST->asCall(); + if (!callAST) + return 0; + if (ExpressionAST *baseExpressionAST = callAST->base_expression) + return baseExpressionAST; + return 0; + } + +private: + const QSharedPointer m_typeOfExpression; + ExpressionAST *m_expressionAST; + const Document::Ptr m_expressionDocument; + Scope *m_scope; + const Document::Ptr &m_document; + const Snapshot &m_snapshot; +}; + +VirtualFunctionHelper::VirtualFunctionHelper(const TypeOfExpression &typeOfExpression, + Scope *scope, + const Document::Ptr &document, + const Snapshot &snapshot) + : m_expressionAST(typeOfExpression.expressionAST()) + , m_expressionDocument(typeOfExpression.context().expressionDocument()) + , m_scope(scope) + , m_document(document) + , m_snapshot(snapshot) +{ +} + +bool VirtualFunctionHelper::canLookupVirtualFunctionOverrides(const Function *function) const +{ + if (!m_expressionDocument || !m_document || !function || !m_scope || m_scope->isClass() + || m_snapshot.isEmpty()) { return false; - CallAST *callAST = expressionAST->asCall(); - if (!callAST) - return false; - ExpressionAST *baseExpressionAST = callAST->base_expression; + } + + ExpressionAST *baseExpressionAST = getBaseExpressionAST(); if (!baseExpressionAST) return false; @@ -79,23 +117,23 @@ bool lookupVirtualFunctionOverrides(TypeOfExpression &typeOfExpression, if (IdExpressionAST *idExpressionAST = baseExpressionAST->asIdExpression()) { NameAST *name = idExpressionAST->name; const bool nameIsQualified = name && name->asQualifiedName(); - result = !nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot); + result = !nameIsQualified && FunctionHelper::isVirtualFunction(function, m_snapshot); } else if (MemberAccessAST *memberAccessAST = baseExpressionAST->asMemberAccess()) { NameAST *name = memberAccessAST->member_name; const bool nameIsQualified = name && name->asQualifiedName(); - if (!nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot)) { - const Document::Ptr expressionDocument - = typeOfExpression.context().expressionDocument(); - QTC_ASSERT(expressionDocument, return false); - TranslationUnit *unit = expressionDocument->translationUnit(); + if (!nameIsQualified && FunctionHelper::isVirtualFunction(function, m_snapshot)) { + TranslationUnit *unit = m_expressionDocument->translationUnit(); QTC_ASSERT(unit, return false); const int accessTokenKind = unit->tokenKind(memberAccessAST->access_token); if (accessTokenKind == T_ARROW) { result = true; } else if (accessTokenKind == T_DOT) { + TypeOfExpression typeOfExpression; + typeOfExpression.init(m_document, m_snapshot); + typeOfExpression.setExpandTemplates(true); const QList items = typeOfExpression.reference( - memberAccessAST->base_expression, document, scope); + memberAccessAST->base_expression, m_document, m_scope); if (!items.isEmpty()) { const LookupItem item = items.first(); if (Symbol *declaration = item.declaration()) @@ -552,13 +590,10 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor & // Consider to show a pop-up displaying overrides for the function Function *function = symbol->type()->asFunctionType(); + VirtualFunctionHelper helper(*typeOfExpression, scope, doc, snapshot); - if (lookupVirtualFunctionOverrides(*typeOfExpression, doc, function, scope, snapshot)) { - Class *klass = symbolFinder->findMatchingClassDeclaration(function, snapshot); - QTC_CHECK(klass); - + if (helper.canLookupVirtualFunctionOverrides(function)) { VirtualFunctionAssistProvider::Parameters params; - params.startClass = klass; params.function = function; params.typeOfExpression = typeOfExpression; params.snapshot = snapshot; diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 76d6cc0d172..dcf2718bc05 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -132,12 +132,16 @@ public: IAssistProposal *perform(const IAssistInterface *) { - QTC_ASSERT(m_params.startClass, return 0); QTC_ASSERT(m_params.function, return 0); QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0); + Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function, + m_params.snapshot); + if (!functionsClass) + return 0; + const QList overrides - = FunctionHelper::overrides(m_params.startClass, m_params.function, m_params.snapshot); + = FunctionHelper::overrides(m_params.function, functionsClass, m_params.snapshot); if (overrides.isEmpty()) return 0; @@ -250,19 +254,19 @@ bool FunctionHelper::isPureVirtualFunction(const Function *function, const Snaps return isVirtualFunction_helper(function, snapshot, PureVirtual); } -QList FunctionHelper::overrides(Class *startClass, Function *function, +QList FunctionHelper::overrides(Function *function, Class *functionsClass, const Snapshot &snapshot) { QList result; - QTC_ASSERT(startClass && function, return result); + QTC_ASSERT(function && functionsClass, return result); FullySpecifiedType referenceType = function->type(); const Name *referenceName = function->name(); QTC_ASSERT(referenceName && referenceType.isValid(), return result); // Find overrides - CppEditor::Internal::CppClass cppClass = CppClass(startClass); - cppClass.lookupDerived(startClass, snapshot); + CppEditor::Internal::CppClass cppClass = CppClass(functionsClass); + cppClass.lookupDerived(functionsClass, snapshot); QList l; l << cppClass; diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h index a8f5927a02a..3aa0dfb68fa 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h @@ -48,9 +48,8 @@ public: VirtualFunctionAssistProvider(); struct Parameters { - Parameters() : startClass(0), function(0), cursorPosition(-1), openInNextSplit(false) {} + Parameters() : function(0), cursorPosition(-1), openInNextSplit(false) {} - CPlusPlus::Class *startClass; CPlusPlus::Function *function; QSharedPointer typeOfExpression; // Keeps instantiated symbols. CPlusPlus::Snapshot snapshot; @@ -79,8 +78,8 @@ public: static bool isPureVirtualFunction(const CPlusPlus::Function *function, const CPlusPlus::Snapshot &snapshot); - static QList overrides(CPlusPlus::Class *startClass, - CPlusPlus::Function *function, + static QList overrides(CPlusPlus::Function *function, + CPlusPlus::Class *functionsClass, const CPlusPlus::Snapshot &snapshot); };