diff options
author | Sergio Martins <smartins@kde.org> | 2019-09-29 23:12:17 +0100 |
---|---|---|
committer | Sergio Martins <smartins@kde.org> | 2019-09-29 23:12:17 +0100 |
commit | 788c7e1722eea9ca39032271bcc638115f76bcf9 (patch) | |
tree | 993dafbc5cb4a6f3f973d2678c0b8bc8beb3dce2 /src | |
parent | 5e3eb5554cd31f0c0a9e205e7ec47139900a6b0e (diff) |
qproperty-type-mismatch: refactor
Type comparison is made in several places, so add it to a function
Diffstat (limited to 'src')
-rw-r--r-- | src/checks/manuallevel/qproperty-type-mismatch.cpp | 56 | ||||
-rw-r--r-- | src/checks/manuallevel/qproperty-type-mismatch.h | 7 |
2 files changed, 41 insertions, 22 deletions
diff --git a/src/checks/manuallevel/qproperty-type-mismatch.cpp b/src/checks/manuallevel/qproperty-type-mismatch.cpp index c0c1c342..06fd2099 100644 --- a/src/checks/manuallevel/qproperty-type-mismatch.cpp +++ b/src/checks/manuallevel/qproperty-type-mismatch.cpp @@ -64,6 +64,8 @@ void QPropertyTypeMismatch::VisitDecl(clang::Decl *decl) VisitMethod(*method); else if (auto field = dyn_cast<FieldDecl>(decl)) VisitField(*field); + else if (auto typedefdecl = dyn_cast<TypedefDecl>(decl)) + VisitTypedef(*typedefdecl); } void QPropertyTypeMismatch::VisitMethod(const clang::CXXMethodDecl & method) @@ -99,7 +101,15 @@ void QPropertyTypeMismatch::VisitField(const FieldDecl & field) } } -std::string QPropertyTypeMismatch::cleanupType(QualType type, bool unscoped) +void QPropertyTypeMismatch::VisitTypedef(const TypedefDecl &td) +{ + // Since when processing Q_PROPERTY we're at the pre-processor stage we don't have access + // to the Qualtypes, so catch any typedefs here + QualType underlyingType = td.getUnderlyingType(); + m_typedefMap[td.getNameAsString()] = underlyingType; +} + +std::string QPropertyTypeMismatch::cleanupType(QualType type, bool unscoped) const { type = type.getNonReferenceType().getCanonicalType().getUnqualifiedType(); @@ -117,12 +127,9 @@ void QPropertyTypeMismatch::checkMethodAgainstProperty (const Property& prop, co auto error_begin = [&] { return "Q_PROPERTY '" + prop.name + "' of type '" + prop.type + "' is mismatched with "; }; if (prop.read == methodName) { - auto retTypeStr = cleanupType(method.getReturnType()); - if (prop.type != retTypeStr) { - // Maybe the difference is just the scope, if yes then don't warn. We already have a check for complaining about lack of scope - auto retTypeStrUnscopped = cleanupType(method.getReturnType(), /*unscopped=*/ true); - if (prop.type != retTypeStrUnscopped) - emitWarning(&method, error_begin() + "method '" + methodName + "' of return type '"+ retTypeStr +"'"); + std::string retTypeStr; + if (!typesMatch(prop.type, method.getReturnType(), retTypeStr)) { + emitWarning(&method, error_begin() + "method '" + methodName + "' of return type '"+ retTypeStr +"'"); } } else if(prop.write == methodName) @@ -134,11 +141,9 @@ void QPropertyTypeMismatch::checkMethodAgainstProperty (const Property& prop, co break; case 1: { - auto parmTypeStr = cleanupType(method.getParamDecl(0)->getType()); - if(prop.type != parmTypeStr) - { + std::string parmTypeStr; + if (!typesMatch(prop.type, method.getParamDecl(0)->getType(), parmTypeStr)) emitWarning(&method, error_begin() + "method '" + methodName + "' with parameter of type '"+ parmTypeStr +"'"); - } break; } default: @@ -166,11 +171,9 @@ void QPropertyTypeMismatch::checkMethodAgainstProperty (const Property& prop, co } case 1: { - auto param0TypeStr = cleanupType(method.getParamDecl(0)->getType()); - if(prop.type != param0TypeStr) - { + std::string param0TypeStr; + if (!typesMatch(prop.type, method.getParamDecl(0)->getType(), param0TypeStr)) emitWarning(&method, error_begin() + "signal '" + methodName + "' with parameter of type '"+ param0TypeStr +"'"); - } break; } default: @@ -184,16 +187,27 @@ void QPropertyTypeMismatch::checkMethodAgainstProperty (const Property& prop, co void QPropertyTypeMismatch::checkFieldAgainstProperty (const Property& prop, const FieldDecl& field, const std::string& fieldName) { - if(prop.member && prop.name == fieldName) - { - auto typeStr = cleanupType(field.getType()); - if(prop.type != typeStr) - { + if (prop.member && prop.name == fieldName) { + std::string typeStr; + if (!typesMatch(prop.type, field.getType(), typeStr)) emitWarning(&field, "Q_PROPERTY '" + prop.name + "' of type '" + prop.type + "' is mismatched with member '" + fieldName + "' of type '"+ typeStr +"'"); - } } } +bool QPropertyTypeMismatch::typesMatch(const string &type1, QualType type2Qt, std::string &cleaned) const +{ + cleaned = cleanupType(type2Qt); + if (type1 == cleaned) + return true; + + // Maybe the difference is just the scope, if yes then don't warn. We already have a check for complaining about lack of scope + cleaned = cleanupType(type2Qt, /*unscopped=*/ true); + if (type1 == cleaned) + return true; + + return false; +} + void QPropertyTypeMismatch::VisitMacroExpands(const clang::Token &MacroNameTok, const clang::SourceRange &range, const MacroInfo *) { IdentifierInfo *ii = MacroNameTok.getIdentifierInfo(); diff --git a/src/checks/manuallevel/qproperty-type-mismatch.h b/src/checks/manuallevel/qproperty-type-mismatch.h index ce80900c..078376d9 100644 --- a/src/checks/manuallevel/qproperty-type-mismatch.h +++ b/src/checks/manuallevel/qproperty-type-mismatch.h @@ -28,6 +28,7 @@ #include <vector> #include <string> +#include <unordered_map> class ClazyContext; namespace clang { @@ -50,6 +51,7 @@ public: private: void VisitMethod(const clang::CXXMethodDecl &); void VisitField(const clang::FieldDecl &); + void VisitTypedef(const clang::TypedefDecl &); void VisitMacroExpands(const clang::Token &MacroNameTok, const clang::SourceRange &range, const clang::MacroInfo *minfo = nullptr) override; @@ -65,9 +67,12 @@ private: }; std::vector<Property> m_qproperties; - std::string cleanupType(clang::QualType type, bool unscoped = false); + std::string cleanupType(clang::QualType type, bool unscoped = false) const; void checkMethodAgainstProperty(const Property &prop, const clang::CXXMethodDecl &method, const std::string &methodName); void checkFieldAgainstProperty(const Property &prop, const clang::FieldDecl &method, const std::string &methodName); + + bool typesMatch(const std::string &type1, clang::QualType type2Qt, std::string &cleaned) const; + std::unordered_map<std::string, clang::QualType> m_typedefMap; }; #endif |