aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSergio Martins <smartins@kde.org>2019-09-29 23:12:17 +0100
committerSergio Martins <smartins@kde.org>2019-09-29 23:12:17 +0100
commit788c7e1722eea9ca39032271bcc638115f76bcf9 (patch)
tree993dafbc5cb4a6f3f973d2678c0b8bc8beb3dce2 /src
parent5e3eb5554cd31f0c0a9e205e7ec47139900a6b0e (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.cpp56
-rw-r--r--src/checks/manuallevel/qproperty-type-mismatch.h7
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