aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-11-15 16:59:46 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-01-13 16:54:22 +0100
commit01b865411d945960cb00b51a0078549eb3dd38e8 (patch)
tree85695e53c11322ac34d50111c1a9b89fc311acad /tools
parent2677de3c79de984e88e4a950c915b4f3f54786dd (diff)
qmllint: parse simple type assertions
Change-Id: Ic24018137d8f989686d4a8f927efb824453d114b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmllint/findunqualified.cpp28
-rw-r--r--tools/qmllint/findunqualified.h3
-rw-r--r--tools/qmllint/scopetree.cpp20
-rw-r--r--tools/qmllint/scopetree.h4
4 files changed, 46 insertions, 9 deletions
diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp
index d0dc3a3711..dc1bb29567 100644
--- a/tools/qmllint/findunqualified.cpp
+++ b/tools/qmllint/findunqualified.cpp
@@ -900,11 +900,37 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::FieldMemberExpression *)
void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::FieldMemberExpression *fieldMember)
{
- if (m_fieldMemberBase == fieldMember->base) {
+ using namespace QQmlJS::AST;
+ ExpressionNode *base = fieldMember->base;
+ while (auto *nested = cast<NestedExpression *>(base))
+ base = nested->expression;
+
+ if (m_fieldMemberBase == base) {
+ QString type;
+ if (auto *binary = cast<BinaryExpression *>(base)) {
+ if (binary->op == QSOperator::As) {
+ if (auto *right = cast<IdentifierExpression *>(binary->right))
+ type = right->name.toString();
+ }
+ }
m_currentScope->accessMember(fieldMember->name.toString(),
+ type,
fieldMember->identifierToken);
m_fieldMemberBase = fieldMember;
} else {
m_fieldMemberBase = nullptr;
}
}
+
+bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::BinaryExpression *)
+{
+ return true;
+}
+
+void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::BinaryExpression *binExp)
+{
+ if (binExp->op == QSOperator::As && m_fieldMemberBase == binExp->left)
+ m_fieldMemberBase = binExp;
+ else
+ m_fieldMemberBase = nullptr;
+}
diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h
index f5955a3a74..6668b53b08 100644
--- a/tools/qmllint/findunqualified.h
+++ b/tools/qmllint/findunqualified.h
@@ -161,6 +161,9 @@ private:
bool visit(QQmlJS::AST::PatternElement *) override;
bool visit(QQmlJS::AST::FieldMemberExpression *idprop) override;
void endVisit(QQmlJS::AST::FieldMemberExpression *) override;
+
+ bool visit(QQmlJS::AST::BinaryExpression *) override;
+ void endVisit(QQmlJS::AST::BinaryExpression *) override;
};
#endif // FINDUNQUALIFIED_H
diff --git a/tools/qmllint/scopetree.cpp b/tools/qmllint/scopetree.cpp
index e5b0eecc5f..6c122f0368 100644
--- a/tools/qmllint/scopetree.cpp
+++ b/tools/qmllint/scopetree.cpp
@@ -88,14 +88,15 @@ bool ScopeTree::isIdInCurrentScope(const QString &id) const
}
void ScopeTree::addIdToAccessed(const QString &id, const QQmlJS::AST::SourceLocation &location) {
- m_currentFieldMember = new FieldMemberList {id, location, {}};
+ m_currentFieldMember = new FieldMemberList {id, QString(), location, {}};
m_accessedIdentifiers.push_back(std::unique_ptr<FieldMemberList>(m_currentFieldMember));
}
-void ScopeTree::accessMember(const QString &name, const QQmlJS::AST::SourceLocation &location)
+void ScopeTree::accessMember(const QString &name, const QString &parentType,
+ const QQmlJS::AST::SourceLocation &location)
{
Q_ASSERT(m_currentFieldMember);
- auto *fieldMember = new FieldMemberList {name, location, {}};
+ auto *fieldMember = new FieldMemberList {name, parentType, location, {}};
m_currentFieldMember->m_child.reset(fieldMember);
m_currentFieldMember = fieldMember;
}
@@ -150,7 +151,9 @@ bool ScopeTree::checkMemberAccess(
const auto scopeIt = scope->m_properties.find(access->m_name);
if (scopeIt != scope->m_properties.end()) {
- if (scopeIt->isList() || scopeIt->typeName() == QLatin1String("string")) {
+ const QString typeName = access->m_parentType.isEmpty() ? scopeIt->typeName()
+ : access->m_parentType;
+ if (scopeIt->isList() || typeName == QLatin1String("string")) {
if (access->m_child && access->m_child->m_name != QLatin1String("length")) {
colorOut.write("Warning: ", Warning);
colorOut.write(
@@ -166,8 +169,9 @@ bool ScopeTree::checkMemberAccess(
}
return true;
}
- const ScopeTree *type = scopeIt->type() ? scopeIt->type()
- : types.value(scopeIt->typeName()).get();
+ const ScopeTree *type = (scopeIt->type() && access->m_parentType.isEmpty())
+ ? scopeIt->type()
+ : types.value(typeName).get();
return checkMemberAccess(code, access.get(), type, types, colorOut);
}
@@ -199,7 +203,9 @@ bool ScopeTree::checkMemberAccess(
while (type) {
const auto typeIt = type->m_properties.find(access->m_name);
if (typeIt != type->m_properties.end()) {
- const auto propType = typeIt->type();
+ const ScopeTree *propType = access->m_parentType.isEmpty()
+ ? typeIt->type()
+ : types.value(access->m_parentType).get();
return checkMemberAccess(code, access.get(),
propType ? propType : types.value(typeIt->typeName()).get(),
types, colorOut);
diff --git a/tools/qmllint/scopetree.h b/tools/qmllint/scopetree.h
index eb5f384477..f5d1155a49 100644
--- a/tools/qmllint/scopetree.h
+++ b/tools/qmllint/scopetree.h
@@ -120,7 +120,8 @@ public:
bool isIdInCurrentScope(const QString &id) const;
void addIdToAccessed(const QString &id, const QQmlJS::AST::SourceLocation &location);
- void accessMember(const QString &name, const QQmlJS::AST::SourceLocation &location);
+ void accessMember(const QString &name, const QString &parentType,
+ const QQmlJS::AST::SourceLocation &location);
void resetMemberScope();
bool isVisualRootScope() const;
@@ -172,6 +173,7 @@ private:
struct FieldMemberList
{
QString m_name;
+ QString m_parentType;
QQmlJS::AST::SourceLocation m_location;
std::unique_ptr<FieldMemberList> m_child;
};