C++: Synchronize function decl/def refactoring.

When editing a function declaration or definition the code model
may realize the same changes have to be applied somewhere else. A
refactoring marker will pop up that can be clicked to perform the
changes. Alternatively, press enter to apply.

Change-Id: I2299a2ecfb6a8f87d4853fc7cfa99486f890a1d3
Reviewed-on: http://codereview.qt.nokia.com/2909
Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
This commit is contained in:
Christian Kamm
2011-08-10 09:50:04 +02:00
parent 13c8f9eaaa
commit 8f14bc0ea2
14 changed files with 973 additions and 92 deletions

View File

@@ -50,6 +50,7 @@
#include <NameVisitor.h>
#include <TypeVisitor.h>
#include <CoreTypes.h>
#include <LookupContext.h>
#include <QtCore/QByteArray>
#include <QtCore/QBitArray>
@@ -583,6 +584,8 @@ void Document::check(CheckMode mode)
semantic(ast, _globalNamespace);
} else if (ExpressionAST *ast = _translationUnit->ast()->asExpression()) {
semantic(ast, _globalNamespace);
} else if (DeclarationAST *ast = translationUnit()->ast()->asDeclaration()) {
semantic(ast, _globalNamespace);
}
}
@@ -972,7 +975,9 @@ public:
};
} // end of anonymous namespace
Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
// strict means the returned symbol has to match exactly,
// including argument count and argument types
Symbol *Snapshot::findMatchingDefinition(Symbol *declaration, bool strict) const
{
if (!declaration)
return 0;
@@ -1030,7 +1035,7 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
if (viableFunctions.isEmpty())
continue;
else if (viableFunctions.length() == 1)
else if (! strict && viableFunctions.length() == 1)
return viableFunctions.first();
Function *best = 0;
@@ -1039,7 +1044,7 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
continue;
else if (fun->argumentCount() == declarationTy->argumentCount()) {
if (! best)
if (! strict && ! best)
best = fun;
unsigned argc = 0;
@@ -1055,7 +1060,7 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
}
}
if (! best)
if (!strict && ! best)
best = viableFunctions.first();
return best;
@@ -1089,3 +1094,74 @@ Class *Snapshot::findMatchingClassDeclaration(Symbol *declaration) const
return 0;
}
void CPlusPlus::findMatchingDeclaration(const LookupContext &context,
Function *functionType,
QList<Declaration *> *typeMatch,
QList<Declaration *> *argumentCountMatch,
QList<Declaration *> *nameMatch)
{
Scope *enclosingScope = functionType->enclosingScope();
while (! (enclosingScope->isNamespace() || enclosingScope->isClass()))
enclosingScope = enclosingScope->enclosingScope();
Q_ASSERT(enclosingScope != 0);
const Name *functionName = functionType->name();
if (! functionName)
return; // anonymous function names are not valid c++
ClassOrNamespace *binding = 0;
const QualifiedNameId *qName = functionName->asQualifiedNameId();
if (qName) {
if (qName->base())
binding = context.lookupType(qName->base(), enclosingScope);
functionName = qName->name();
}
if (!binding) { // declaration for a global function
binding = context.lookupType(enclosingScope);
if (!binding)
return;
}
const Identifier *funcId = functionName->identifier();
if (!funcId) // E.g. operator, which we might be able to handle in the future...
return;
foreach (Symbol *s, binding->symbols()) {
Class *matchingClass = s->asClass();
if (!matchingClass)
continue;
for (Symbol *s = matchingClass->find(funcId); s; s = s->next()) {
if (! s->name())
continue;
else if (! funcId->isEqualTo(s->identifier()))
continue;
else if (! s->type()->isFunctionType())
continue;
else if (Declaration *decl = s->asDeclaration()) {
if (Function *declFunTy = decl->type()->asFunctionType()) {
if (functionType->isEqualTo(declFunTy))
typeMatch->prepend(decl);
else if (functionType->argumentCount() == declFunTy->argumentCount())
argumentCountMatch->prepend(decl);
else
nameMatch->append(decl);
}
}
}
}
}
QList<Declaration *> CPlusPlus::findMatchingDeclaration(const LookupContext &context, Function *functionType)
{
QList<Declaration *> result;
QList<Declaration *> nameMatch, argumentCountMatch, typeMatch;
findMatchingDeclaration(context, functionType, &typeMatch, &argumentCountMatch, &nameMatch);
result.append(typeMatch);
result.append(argumentCountMatch);
result.append(nameMatch);
return result;
}

View File

@@ -45,6 +45,7 @@ namespace CPlusPlus {
class Macro;
class MacroArgumentReference;
class LookupContext;
class CPLUSPLUS_EXPORT Document
{
@@ -386,7 +387,7 @@ public:
Document::Ptr documentFromSource(const QByteArray &preprocessedCode,
const QString &fileName) const;
Symbol *findMatchingDefinition(Symbol *symbol) const;
Symbol *findMatchingDefinition(Symbol *symbol, bool strict = false) const;
Class *findMatchingClassDeclaration(Symbol *symbol) const;
private:
@@ -396,6 +397,15 @@ private:
_Base _documents;
};
void CPLUSPLUS_EXPORT findMatchingDeclaration(
const LookupContext &context,
Function *functionType,
QList<Declaration *> *typeMatch,
QList<Declaration *> *argumentCountMatch,
QList<Declaration *> *nameMatch);
QList<Declaration *> CPLUSPLUS_EXPORT findMatchingDeclaration(
const LookupContext &context, Function *functionType);
} // namespace CPlusPlus
#endif // CPLUSPLUS_CPPDOCUMENT_H