CppEditor: Handle classes that do not override

...when searching the overrides for virtual functions.

In case there is no override for the static type of a function call
expression, make sure to:

1) include the last provided override (look up bases)
2) and all overrides whose classes are derived from that static type

Task-number: QTCREATORBUG-10470

Change-Id: I2c01bfdc6cb35c5a01a000ebd81a2b322ce2b795
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
Nikolai Kosjar
2013-10-28 15:12:18 +01:00
parent 0c16757085
commit 4a06dab30a
5 changed files with 276 additions and 39 deletions

View File

@@ -133,6 +133,7 @@ public:
IAssistProposal *perform(const IAssistInterface *)
{
QTC_ASSERT(m_params.function, return 0);
QTC_ASSERT(m_params.staticClass, return 0);
QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0);
Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function,
@@ -140,8 +141,8 @@ public:
if (!functionsClass)
return 0;
const QList<Symbol *> overrides
= FunctionHelper::overrides(m_params.function, functionsClass, m_params.snapshot);
const QList<Symbol *> overrides = FunctionHelper::overrides(
m_params.function, functionsClass, m_params.staticClass, m_params.snapshot);
if (overrides.isEmpty())
return 0;
@@ -254,11 +255,40 @@ bool FunctionHelper::isPureVirtualFunction(const Function *function, const Snaps
return isVirtualFunction_helper(function, snapshot, PureVirtual);
}
static bool isDerivedOf(Class *derivedClassCandidate, Class *baseClass,
const Snapshot &snapshot)
{
QTC_ASSERT(derivedClassCandidate && baseClass, return false);
QList<CppClass> l = QList<CppClass>() << CppClass(derivedClassCandidate);
while (!l.isEmpty()) {
CppClass clazz = l.takeFirst();
QTC_ASSERT(clazz.declaration, continue);
const QString fileName = QString::fromUtf8(clazz.declaration->fileName());
const Document::Ptr document = snapshot.document(fileName);
if (!document)
continue;
const LookupContext context(document, snapshot);
clazz.lookupBases(clazz.declaration, context);
foreach (const CppClass &base, clazz.bases) {
if (base.declaration == baseClass)
return true;
if (!l.contains(base))
l << base;
}
}
return false;
}
QList<Symbol *> FunctionHelper::overrides(Function *function, Class *functionsClass,
const Snapshot &snapshot)
Class *staticClass, const Snapshot &snapshot)
{
QList<Symbol *> result;
QTC_ASSERT(function && functionsClass, return result);
QTC_ASSERT(function && functionsClass && staticClass, return result);
FullySpecifiedType referenceType = function->type();
const Name *referenceName = function->name();
@@ -274,15 +304,22 @@ QList<Symbol *> FunctionHelper::overrides(Function *function, Class *functionsCl
while (!l.isEmpty()) {
// Add derived
CppClass clazz = l.takeFirst();
QTC_ASSERT(clazz.declaration, continue);
Class *c = clazz.declaration->asClass();
QTC_ASSERT(c, continue);
if (c != functionsClass && c != staticClass) {
if (!isDerivedOf(c, staticClass, snapshot))
continue;
}
foreach (const CppClass &d, clazz.derived) {
if (!l.contains(d))
l << d;
}
// Check member functions
QTC_ASSERT(clazz.declaration, continue);
Class *c = clazz.declaration->asClass();
QTC_ASSERT(c, continue);
for (int i = 0, total = c->memberCount(); i < total; ++i) {
Symbol *candidate = c->memberAt(i);
const Name *candidateName = candidate->name();