diff options
Diffstat (limited to 'src/QtUtils.cpp')
-rw-r--r-- | src/QtUtils.cpp | 109 |
1 files changed, 64 insertions, 45 deletions
diff --git a/src/QtUtils.cpp b/src/QtUtils.cpp index 8a72392b..05f463d2 100644 --- a/src/QtUtils.cpp +++ b/src/QtUtils.cpp @@ -34,7 +34,7 @@ using namespace std; using namespace clang; -bool QtUtils::isQtIterableClass(clang::CXXRecordDecl *record) +bool clazy::isQtIterableClass(clang::CXXRecordDecl *record) { if (!record) return false; @@ -42,30 +42,41 @@ bool QtUtils::isQtIterableClass(clang::CXXRecordDecl *record) return isQtIterableClass(record->getQualifiedNameAsString()); } -const vector<string> & QtUtils::qtContainers() +const vector<StringRef> & clazy::qtContainers() { - static const vector<string> classes = { "QListSpecialMethods", "QList", "QVector", "QVarLengthArray", "QMap", - "QHash", "QMultiMap", "QMultiHash", "QSet", "QStack", "QQueue", "QString", "QStringRef", - "QByteArray", "QSequentialIterable", "QAssociativeIterable", "QJsonArray", "QLinkedList" }; + static const vector<StringRef> classes = { "QListSpecialMethods", "QList", "QVector", "QVarLengthArray", "QMap", + "QHash", "QMultiMap", "QMultiHash", "QSet", "QStack", "QQueue", "QString", "QStringRef", + "QByteArray", "QSequentialIterable", "QAssociativeIterable", "QJsonArray", "QLinkedList" }; return classes; } -const vector<string> & QtUtils::qtCOWContainers() +const vector<StringRef> & clazy::qtCOWContainers() { - static const vector<string> classes = { "QListSpecialMethods", "QList", "QVector", "QMap", "QHash", - "QMultiMap", "QMultiHash", "QSet", "QStack", "QQueue", "QString", "QStringRef", - "QByteArray", "QJsonArray", "QLinkedList" }; + static const vector<StringRef> classes = { "QListSpecialMethods", "QList", "QVector", "QMap", "QHash", + "QMultiMap", "QMultiHash", "QSet", "QStack", "QQueue", "QString", "QStringRef", + "QByteArray", "QJsonArray", "QLinkedList" }; return classes; } -std::unordered_map<string, std::vector<string> > QtUtils::detachingMethods() +std::unordered_map<string, std::vector<StringRef> > clazy::detachingMethods() { - static std::unordered_map<string, std::vector<string> > map; + static std::unordered_map<string, std::vector<StringRef> > map; + if (map.empty()) { + map = detachingMethodsWithConstCounterParts(); + map["QVector"].push_back("fill"); + } + + return map; +} + +std::unordered_map<string, std::vector<StringRef> > clazy::detachingMethodsWithConstCounterParts() +{ + static std::unordered_map<string, std::vector<StringRef> > map; if (map.empty()) { map["QList"] = {"first", "last", "begin", "end", "front", "back", "operator[]"}; - map["QVector"] = {"first", "last", "begin", "end", "front", "back", "data", "operator[]", "fill" }; - map["QMap"] = {"begin", "end", "first", "find", "last", "lowerBound", "upperBound", "operator[]" }; + map["QVector"] = {"first", "last", "begin", "end", "front", "back", "data", "operator[]" }; + map["QMap"] = {"begin", "end", "first", "find", "last", "operator[]", "lowerBound", "upperBound" }; map["QHash"] = {"begin", "end", "find", "operator[]" }; map["QLinkedList"] = {"first", "last", "begin", "end", "front", "back", "operator[]" }; map["QSet"] = {"begin", "end", "find", "operator[]" }; @@ -83,8 +94,7 @@ std::unordered_map<string, std::vector<string> > QtUtils::detachingMethods() return map; } - -bool QtUtils::isQtCOWIterableClass(clang::CXXRecordDecl *record) +bool clazy::isQtCOWIterableClass(clang::CXXRecordDecl *record) { if (!record) return false; @@ -92,19 +102,19 @@ bool QtUtils::isQtCOWIterableClass(clang::CXXRecordDecl *record) return isQtCOWIterableClass(record->getQualifiedNameAsString()); } -bool QtUtils::isQtCOWIterableClass(const string &className) +bool clazy::isQtCOWIterableClass(const string &className) { const auto &classes = qtCOWContainers(); - return clazy_std::contains(classes, className); + return clazy::contains(classes, className); } -bool QtUtils::isQtIterableClass(const string &className) +bool clazy::isQtIterableClass(StringRef className) { const auto &classes = qtContainers(); - return clazy_std::contains(classes, className); + return clazy::contains(classes, className); } -bool QtUtils::isQtAssociativeContainer(clang::CXXRecordDecl *record) +bool clazy::isQtAssociativeContainer(clang::CXXRecordDecl *record) { if (!record) return false; @@ -112,25 +122,25 @@ bool QtUtils::isQtAssociativeContainer(clang::CXXRecordDecl *record) return isQtAssociativeContainer(record->getNameAsString()); } -bool QtUtils::isQtAssociativeContainer(const string &className) +bool clazy::isQtAssociativeContainer(StringRef className) { - static const vector<string> classes = { "QSet", "QMap", "QHash" }; - return clazy_std::contains(classes, className); + static const vector<StringRef> classes = { "QSet", "QMap", "QHash" }; + return clazy::contains(classes, className); } -bool QtUtils::isQObject(CXXRecordDecl *decl) +bool clazy::isQObject(const CXXRecordDecl *decl) { return TypeUtils::derivesFrom(decl, "QObject"); } -bool QtUtils::isQObject(clang::QualType qt) +bool clazy::isQObject(clang::QualType qt) { qt = TypeUtils::pointeeQualType(qt); const auto t = qt.getTypePtrOrNull(); return t ? isQObject(t->getAsCXXRecordDecl()) : false; } -bool QtUtils::isConvertibleTo(const Type *source, const Type *target) +bool clazy::isConvertibleTo(const Type *source, const Type *target) { if (!source || !target) return false; @@ -159,18 +169,18 @@ bool QtUtils::isConvertibleTo(const Type *source, const Type *target) return false; } -bool QtUtils::isJavaIterator(CXXRecordDecl *record) +bool clazy::isJavaIterator(CXXRecordDecl *record) { if (!record) return false; - static const vector<string> names = { "QHashIterator", "QMapIterator", "QSetIterator", "QListIterator", - "QVectorIterator", "QLinkedListIterator", "QStringListIterator" }; + static const vector<StringRef> names = { "QHashIterator", "QMapIterator", "QSetIterator", "QListIterator", + "QVectorIterator", "QLinkedListIterator", "QStringListIterator" }; - return clazy_std::contains(names, record->getNameAsString()); + return clazy::contains(names, clazy::name(record)); } -bool QtUtils::isJavaIterator(CXXMemberCallExpr *call) +bool clazy::isJavaIterator(CXXMemberCallExpr *call) { if (!call) return false; @@ -178,19 +188,24 @@ bool QtUtils::isJavaIterator(CXXMemberCallExpr *call) return isJavaIterator(call->getRecordDecl()); } -bool QtUtils::isQtContainer(QualType t) +bool clazy::isQtContainer(QualType t) { CXXRecordDecl *record = TypeUtils::typeAsRecord(t); if (!record) return false; - const string typeName = record->getNameAsString(); - return clazy_std::any_of(QtUtils::qtContainers(), [typeName] (const string &container) { + return isQtContainer(record); +} + +bool clazy::isQtContainer(const CXXRecordDecl *record) +{ + const StringRef typeName = clazy::name(record); + return clazy::any_of(clazy::qtContainers(), [typeName] (StringRef container) { return container == typeName; }); } -bool QtUtils::containerNeverDetaches(const clang::VarDecl *valDecl, StmtBodyRange bodyRange) // clazy:exclude=function-args-by-value +bool clazy::containerNeverDetaches(const clang::VarDecl *valDecl, StmtBodyRange bodyRange) // clazy:exclude=function-args-by-value { if (!valDecl) return false; @@ -210,19 +225,19 @@ bool QtUtils::containerNeverDetaches(const clang::VarDecl *valDecl, StmtBodyRang return true; } -bool QtUtils::isAReserveClass(CXXRecordDecl *recordDecl) +bool clazy::isAReserveClass(CXXRecordDecl *recordDecl) { if (!recordDecl) return false; static const std::vector<std::string> classes = {"QVector", "std::vector", "QList", "QSet"}; - return clazy_std::any_of(classes, [recordDecl](const string &className) { + return clazy::any_of(classes, [recordDecl](const string &className) { return TypeUtils::derivesFrom(recordDecl, className); }); } -clang::CXXRecordDecl *QtUtils::getQObjectBaseClass(clang::CXXRecordDecl *recordDecl) +clang::CXXRecordDecl *clazy::getQObjectBaseClass(clang::CXXRecordDecl *recordDecl) { if (!recordDecl) return nullptr; @@ -237,12 +252,12 @@ clang::CXXRecordDecl *QtUtils::getQObjectBaseClass(clang::CXXRecordDecl *recordD } -bool QtUtils::isConnect(FunctionDecl *func) +bool clazy::isConnect(FunctionDecl *func) { return func && func->getQualifiedNameAsString() == "QObject::connect"; } -bool QtUtils::connectHasPMFStyle(FunctionDecl *func) +bool clazy::connectHasPMFStyle(FunctionDecl *func) { // Look for char* arguments for (auto parm : Utils::functionParameters(func)) { @@ -259,7 +274,7 @@ bool QtUtils::connectHasPMFStyle(FunctionDecl *func) return true; } -CXXMethodDecl *QtUtils::pmfFromConnect(CallExpr *funcCall, int argIndex) +CXXMethodDecl *clazy::pmfFromConnect(CallExpr *funcCall, int argIndex) { if (!funcCall) return nullptr; @@ -278,7 +293,7 @@ CXXMethodDecl *QtUtils::pmfFromConnect(CallExpr *funcCall, int argIndex) } -CXXMethodDecl *QtUtils::pmfFromUnary(Expr *expr) +CXXMethodDecl *clazy::pmfFromUnary(Expr *expr) { if (auto uo = dyn_cast<UnaryOperator>(expr)) { return pmfFromUnary(uo); @@ -295,7 +310,7 @@ CXXMethodDecl *QtUtils::pmfFromUnary(Expr *expr) if (!context) return nullptr; - CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(context); + auto record = dyn_cast<CXXRecordDecl>(context); if (!record) return nullptr; @@ -306,12 +321,16 @@ CXXMethodDecl *QtUtils::pmfFromUnary(Expr *expr) return pmfFromUnary(dyn_cast<UnaryOperator>(call->getArg(1))); } else if (auto staticCast = dyn_cast<CXXStaticCastExpr>(expr)) { return pmfFromUnary(staticCast->getSubExpr()); + } else if (auto callexpr = dyn_cast<CallExpr>(expr)) { + // QOverload case, go deeper one level to get to the UnaryOperator + if (callexpr->getNumArgs() == 1) + return pmfFromUnary(callexpr->getArg(0)); } return nullptr; } -CXXMethodDecl *QtUtils::pmfFromUnary(UnaryOperator *uo) +CXXMethodDecl *clazy::pmfFromUnary(UnaryOperator *uo) { if (!uo) return nullptr; @@ -328,7 +347,7 @@ CXXMethodDecl *QtUtils::pmfFromUnary(UnaryOperator *uo) return nullptr; } -bool QtUtils::recordHasCtorWithParam(clang::CXXRecordDecl *record, const std::string ¶mType, bool &ok, int &numCtors) +bool clazy::recordHasCtorWithParam(clang::CXXRecordDecl *record, const std::string ¶mType, bool &ok, int &numCtors) { ok = true; numCtors = 0; |