1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QQMLJSLINTERVISITOR_P_H
#define QQMLJSLINTERVISITOR_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include <private/qqmljsimportvisitor_p.h>
#include <private/qqmljsengine_p.h>
QT_BEGIN_NAMESPACE
namespace QQmlJS {
/*!
\internal
Extends QQmlJSImportVisitor with extra warnings that are required for linting but unrelated to
QQmlJSImportVisitor actual task that is constructing QQmlJSScopes. One example of such warnings
are purely syntactic checks, or warnings that don't affect compilation.
*/
class LinterVisitor final : public QQmlJSImportVisitor
{
public:
LinterVisitor(QQmlJSImporter *importer, QQmlJSLogger *logger,
const QString &implicitImportDirectory,
const QStringList &qmldirFiles = QStringList(), QQmlJS::Engine *engine = nullptr);
protected:
using QQmlJSImportVisitor::endVisit;
using QQmlJSImportVisitor::visit;
bool preVisit(QQmlJS::AST::Node *) override;
void postVisit(QQmlJS::AST::Node *) override;
QQmlJS::AST::Node *astParentOfVisitedNode() const;
void leaveEnvironment() override;
bool visit(QQmlJS::AST::StringLiteral *) override;
bool visit(AST::CommaExpression *) override;
bool visit(QQmlJS::AST::NewMemberExpression *) override;
bool visit(QQmlJS::AST::VoidExpression *ast) override;
bool visit(QQmlJS::AST::BinaryExpression *) override;
bool visit(QQmlJS::AST::UiImport *import) override;
bool visit(QQmlJS::AST::UiEnumDeclaration *uied) override;
bool visit(QQmlJS::AST::CaseBlock *) override;
bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
private:
struct SeenImport
{
QStringView filename;
QString uri;
QTypeRevision version;
QStringView id;
QQmlJS::AST::UiImport *uiImport;
SeenImport(QQmlJS::AST::UiImport *i) : filename(i->fileName), id(i->importId), uiImport(i)
{
if (i->importUri)
uri = i->importUri->toString();
if (i->version)
version = i->version->version;
}
friend bool comparesEqual(const SeenImport &lhs, const SeenImport &rhs) noexcept
{
return lhs.filename == rhs.filename && lhs.uri == rhs.uri
&& lhs.version == rhs.version && lhs.id == rhs.id;
}
Q_DECLARE_EQUALITY_COMPARABLE(SeenImport)
friend size_t qHash(const SeenImport &i, size_t seed = 0)
{
return qHashMulti(seed, i.filename, i.uri, i.version, i.id);
}
};
QQmlJS::Engine *m_engine = nullptr;
QSet<SeenImport> m_seenImports;
std::vector<QQmlJS::AST::Node *> m_ancestryIncludingCurrentNode;
void handleDuplicateEnums(QQmlJS::AST::UiEnumMemberList *members, QStringView key,
const QQmlJS::SourceLocation &location);
void warnCaseNoFlowControl(QQmlJS::SourceLocation caseToken) const;
void checkCaseFallthrough(QQmlJS::AST::StatementList *statements, SourceLocation errorLoc,
SourceLocation nextLoc);
BindingExpressionParseResult parseBindingExpression(
const QString &name, const QQmlJS::AST::Statement *statement,
const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition = nullptr) override;
void handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding,
const AST::UiPublicMember *associatedPropertyDefinition) override;
};
} // namespace QQmlJS
QT_END_NAMESPACE
#endif // QQMLJSLINTERVISITOR_P_H
|