Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmljslintervisitor_p.h
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
5#ifndef QQMLJSLINTERVISITOR_P_H
6#define QQMLJSLINTERVISITOR_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17
18#include <private/qqmljsimportvisitor_p.h>
19#include <private/qqmljslinterrenamedcomponents_p.h>
20
21#include <private/qqmljsengine_p.h>
22
23#include <QtCore/qtyperevision.h>
24
25QT_BEGIN_NAMESPACE
26
27namespace QQmlJS {
28
29/*!
30 \internal
31 Extends QQmlJSImportVisitor with extra warnings that are required for linting but unrelated to
32 QQmlJSImportVisitor actual task that is constructing QQmlJSScopes. One example of such warnings
33 are purely syntactic checks, or warnings that don't affect compilation.
34 */
35class LinterVisitor final : public QQmlJSImportVisitor
36{
37public:
38 LinterVisitor(QQmlJSImporter *importer, QQmlJSLogger *logger,
39 const QString &implicitImportDirectory,
40 const QStringList &qmldirFiles = QStringList(), QQmlJS::Engine *engine = nullptr);
41
42 const LinterRenamedComponents &renamedComponents() const { return m_renamedComponents; }
43
44protected:
45 using QQmlJSImportVisitor::endVisit;
46 using QQmlJSImportVisitor::visit;
47
48 bool preVisit(QQmlJS::AST::Node *) override;
49 void postVisit(QQmlJS::AST::Node *) override;
51
53
54 bool visit(QQmlJS::AST::StringLiteral *) override;
55 bool visit(AST::CommaExpression *) override;
56 bool visit(QQmlJS::AST::NewMemberExpression *) override;
57 bool visit(QQmlJS::AST::VoidExpression *ast) override;
58 bool visit(QQmlJS::AST::BinaryExpression *) override;
59 bool visit(QQmlJS::AST::UiImport *import) override;
60 bool visit(QQmlJS::AST::UiEnumDeclaration *uied) override;
61 bool visit(QQmlJS::AST::CaseBlock *) override;
62 bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
63 bool visit(QQmlJS::AST::FunctionDeclaration *fdecl) override;
64 bool visit(QQmlJS::AST::FunctionExpression *fexpr) override;
65 bool visit(QQmlJS::AST::UiPublicMember *publicMember) override;
66 bool visit(QQmlJS::AST::UiObjectDefinition *objectDefinition) override;
67 bool visit(QQmlJS::AST::Type *typeAnnotation) override;
68 bool visit(QQmlJS::AST::UiPragma *pragma) override;
69
70 bool visit(QQmlJS::AST::UiProgram *ast) override;
71 void endVisit(QQmlJS::AST::UiProgram *ast) override;
72
73 bool safeInsertJSIdentifier(QQmlJSScope::Ptr &scope, const QString &name,
74 const QQmlJSScope::JavaScriptIdentifier &identifier) override;
75
76private:
77 struct SeenImport
78 {
79 QStringView filename;
80 QString uri;
81 QTypeRevision version;
82 QStringView id;
83 QQmlJS::AST::UiImport *uiImport;
84
85 SeenImport(QQmlJS::AST::UiImport *i) : filename(i->fileName), id(i->importId), uiImport(i)
86 {
87 if (i->importUri)
88 uri = i->importUri->toString();
89 if (i->version)
90 version = i->version->version;
91 }
92 friend bool comparesEqual(const SeenImport &lhs, const SeenImport &rhs) noexcept
93 {
94 return lhs.filename == rhs.filename && lhs.uri == rhs.uri
95 && lhs.version == rhs.version && lhs.id == rhs.id;
96 }
97 Q_DECLARE_EQUALITY_COMPARABLE(SeenImport)
98
99 friend size_t qHash(const SeenImport &i, size_t seed = 0)
100 {
101 return qHashMulti(seed, i.filename, i.uri, i.version, i.id);
102 }
103 };
104 QQmlJS::Engine *m_engine = nullptr;
105 QSet<SeenImport> m_seenImports;
106 QSet<std::pair<const QQmlJSScope *, QString>> misplacedJSIdentifiers;
107 std::vector<QQmlJS::AST::Node *> m_ancestryIncludingCurrentNode;
108 QQmlJS::LinterRenamedComponents m_renamedComponents;
109
110 void handleDuplicateEnums(QQmlJS::AST::UiEnumMemberList *members, QStringView key,
111 const QQmlJS::SourceLocation &location);
112 void warnCaseNoFlowControl(QQmlJS::SourceLocation caseToken) const;
113 void checkCaseFallthrough(QQmlJS::AST::StatementList *statements, SourceLocation errorLoc,
114 SourceLocation nextLoc);
116 const QString &name, const QQmlJS::AST::Statement *statement,
117 const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition = nullptr) override;
118 void handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding,
119 const AST::UiPublicMember *associatedPropertyDefinition) override;
120 void handleUselessExpressionStatement(const AST::ExpressionStatement *ast);
121 void handleRecursivelyInstantiatedType(AST::UiQualifiedId *qualifiedId);
122 void handleRenamedType(QQmlJS::AST::UiQualifiedId *id);
123 void checkSingletonRoot();
124 void checkFileSelections();
125
126 bool m_rootIsSingleton = false;
127};
128
129} // namespace QQmlJS
130
131QT_END_NAMESPACE
132
133#endif // QQMLJSLINTERVISITOR_P_H
void postVisit(QQmlJS::AST::Node *) override
void handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding, const AST::UiPublicMember *associatedPropertyDefinition) override
LinterVisitor(QQmlJSImporter *importer, QQmlJSLogger *logger, const QString &implicitImportDirectory, const QStringList &qmldirFiles=QStringList(), QQmlJS::Engine *engine=nullptr)
BindingExpressionParseResult parseBindingExpression(const QString &name, const QQmlJS::AST::Statement *statement, const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition=nullptr) override
bool safeInsertJSIdentifier(QQmlJSScope::Ptr &scope, const QString &name, const QQmlJSScope::JavaScriptIdentifier &identifier) override
const LinterRenamedComponents & renamedComponents() const
void endVisit(QQmlJS::AST::UiProgram *ast) override
bool visit(QQmlJS::AST::StringLiteral *) override
QQmlJS::AST::Node * astParentOfVisitedNode() const
bool preVisit(QQmlJS::AST::Node *) override
static void warnForMethodShadowingInBase(const QQmlJSScope::ConstPtr &base, const QString &name, const QQmlJS::SourceLocation &location, QQmlJSLogger *logger)
static bool isUselessExpressionStatement_impl(const ExpressionNode *ast)
static void warnForDuplicates(const QQmlJSScope::ConstPtr &scope, const QString &name, QLatin1String type, const QQmlJS::SourceLocation &location, OverrideInformations overrideFlags, QQmlJSLogger *logger)
static constexpr QLatin1String s_method
static void warnAboutLiteralConstructors(NewMemberExpression *expression, QQmlJSLogger *logger)
static SourceLocation confusingPluses(BinaryExpression *exp)
static bool isUselessExpressionStatement(const ExpressionStatement *ast)
static bool allCodePathsReturnInsideCase(Node *statement)
Q_DECLARE_FLAGS(OverrideInformations, OverrideInformation)
static bool compatibilityHeuristicForFileSelector(const QQmlJSScope::ConstPtr &scope1, const QQmlJSScope::ConstPtr &scope2)
static SourceLocation confusingMinuses(BinaryExpression *exp)
static QList< const Statement * > possibleLastStatements(const StatementList *ast)
static constexpr QLatin1String s_property
static constexpr QLatin1String s_signal
static void warnForPropertyShadowingInBase(const QQmlJSScope::ConstPtr &base, const QString &name, const QQmlJS::SourceLocation &location, OverrideInformations overrideFlags, QQmlJSLogger *logger)
Combined button and popup list for selecting options.