forked from qt-creator/qt-creator
CppEditor: Let users check for unused functions in (sub-)projects
Note that especially in C++, there can be a lot of false positives,
especially in template-heavy code bases. We filter out the most notorious
offenders, namely:
- templates themselves
- constructors and destructors
- *begin() and *end()
- qHash()
- main()
Since the code model does not know about symbol visibility, the
functionality is quite useless for libraries, unless you want to check
your test coverage.
The procedure is rather slow, but that shouldn't matter so much, as it's
something you'll only run "once in a while".
Fixes: QTCREATORBUG-6772
Change-Id: If00a537b760a9b0babdda6c848133715c3240155
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -118,14 +118,18 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &cand
|
||||
lineText = matchingLine(tk);
|
||||
const int len = tk.utf16chars();
|
||||
|
||||
const Usage u(_doc->filePath(), lineText,
|
||||
getContainingFunction(line, col), getTags(line, col, tokenIndex),
|
||||
line, col - 1, len);
|
||||
QString callerName;
|
||||
const Function * const caller = getContainingFunction(line, col);
|
||||
if (caller)
|
||||
callerName = Overview().prettyName(caller->name());
|
||||
Usage u(_doc->filePath(), lineText, callerName, getTags(line, col, tokenIndex),
|
||||
line, col - 1, len);
|
||||
u.containingFunctionSymbol = caller;
|
||||
_usages.append(u);
|
||||
_references.append(tokenIndex);
|
||||
}
|
||||
|
||||
QString FindUsages::getContainingFunction(int line, int column)
|
||||
Function *FindUsages::getContainingFunction(int line, int column)
|
||||
{
|
||||
const QList<AST *> astPath = ASTPath(_doc)(line, column);
|
||||
bool hasBlock = false;
|
||||
@@ -135,9 +139,7 @@ QString FindUsages::getContainingFunction(int line, int column)
|
||||
if (const auto func = (*it)->asFunctionDefinition()) {
|
||||
if (!hasBlock)
|
||||
return {};
|
||||
if (!func->symbol)
|
||||
return {};
|
||||
return Overview().prettyName(func->symbol->name());
|
||||
return func->symbol;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
@@ -222,7 +224,7 @@ public:
|
||||
// We don't want to classify constructors and destructors as declarations
|
||||
// when listing class usages.
|
||||
if (m_findUsages->_declSymbol->asClass())
|
||||
return {};
|
||||
return Usage::Tag::ConstructorDestructor;
|
||||
continue;
|
||||
}
|
||||
if (const auto declarator = (*it)->asDeclarator()) {
|
||||
@@ -257,6 +259,10 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const auto declId = declarator->core_declarator->asDeclaratorId()) {
|
||||
if (declId->name && declId->name->asOperatorFunctionId())
|
||||
tags |= Usage::Tag::Operator;
|
||||
}
|
||||
}
|
||||
if (const auto decl = (*(it + 1))->asSimpleDeclaration()) {
|
||||
if (tags.toInt() && decl->qt_invokable_token)
|
||||
@@ -268,6 +274,11 @@ public:
|
||||
declarator->initializer, it + 1),
|
||||
it + 1);
|
||||
}
|
||||
Class *clazz = decl->symbols->value->enclosingClass();
|
||||
if (clazz && clazz->name()
|
||||
&& decl->symbols->value->name()->match(clazz->name())) {
|
||||
return tags |= Usage::Tag::ConstructorDestructor;
|
||||
}
|
||||
if (const auto func = decl->symbols->value->type()->asFunctionType()) {
|
||||
if (func->isSignal() || func->isSlot() || func->isInvokable())
|
||||
return tags |= Usage::Tag::MocInvokable;
|
||||
|
||||
@@ -25,6 +25,9 @@ public:
|
||||
Override = 1 << 4,
|
||||
MocInvokable = 1 << 5,
|
||||
Template = 1 << 6,
|
||||
ConstructorDestructor = 1 << 7,
|
||||
Operator = 1 << 8,
|
||||
Used = 1 << 9,
|
||||
};
|
||||
using Tags = QFlags<Tag>;
|
||||
|
||||
@@ -37,6 +40,7 @@ public:
|
||||
Utils::FilePath path;
|
||||
QString lineText;
|
||||
QString containingFunction;
|
||||
const Function *containingFunctionSymbol = nullptr;
|
||||
Tags tags;
|
||||
int line = 0;
|
||||
int col = 0;
|
||||
@@ -65,7 +69,7 @@ protected:
|
||||
void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr);
|
||||
void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
|
||||
Usage::Tags getTags(int line, int column, int tokenIndex);
|
||||
QString getContainingFunction(int line, int column);
|
||||
Function *getContainingFunction(int line, int column);
|
||||
|
||||
bool checkCandidates(const QList<LookupItem> &candidates) const;
|
||||
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user