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#include <private/qqmljslintercontext_p.h>
21
22#include <private/qqmljsengine_p.h>
23
24#include <QtCore/qtyperevision.h>
25
26QT_BEGIN_NAMESPACE
27
28namespace QQmlJS {
29
30/*!
31 \internal
32 Extends QQmlJSImportVisitor with extra warnings that are required for linting but unrelated to
33 QQmlJSImportVisitor actual task that is constructing QQmlJSScopes. One example of such warnings
34 are purely syntactic checks, or warnings that don't affect compilation.
35 */
36class LinterVisitor final : public QQmlJSImportVisitor
37{
38public:
39 LinterVisitor(QQmlJSImporter *importer, QQmlJSLogger *logger,
40 const QString &implicitImportDirectory,
41 const QStringList &qmldirFiles = QStringList(), QQmlJS::Engine *engine = nullptr);
42
43 const QQmlJS::LinterRenamedComponents &renamedComponents() const { return m_renamedComponents; }
44
45protected:
46 using QQmlJSImportVisitor::endVisit;
47 using QQmlJSImportVisitor::visit;
48
49 bool preVisit(QQmlJS::AST::Node *) override;
50 void postVisit(QQmlJS::AST::Node *) override;
52
54
55 bool visit(QQmlJS::AST::StringLiteral *) override;
56 bool visit(AST::CommaExpression *) override;
57 bool visit(QQmlJS::AST::NewMemberExpression *) override;
58 bool visit(QQmlJS::AST::VoidExpression *ast) override;
59 bool visit(QQmlJS::AST::BinaryExpression *) override;
60 bool visit(QQmlJS::AST::UiImport *import) override;
61 bool visit(QQmlJS::AST::UiEnumDeclaration *uied) override;
62 bool visit(QQmlJS::AST::CaseBlock *) override;
63 bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
64 bool visit(QQmlJS::AST::FunctionDeclaration *fdecl) override;
65 bool visit(QQmlJS::AST::FunctionExpression *fexpr) override;
66 bool visit(QQmlJS::AST::UiPublicMember *publicMember) override;
67 bool visit(QQmlJS::AST::UiObjectDefinition *objectDefinition) override;
68 bool visit(QQmlJS::AST::Type *typeAnnotation) override;
69 bool visit(QQmlJS::AST::UiPragma *pragma) override;
70
71 bool visit(QQmlJS::AST::IdentifierExpression *idexp) override;
72 void endVisit(QQmlJS::AST::FieldMemberExpression *fieldMember) override;
73
74 bool visit(QQmlJS::AST::UiProgram *ast) override;
75 void endVisit(QQmlJS::AST::UiProgram *ast) override;
76
77 bool safeInsertJSIdentifier(QQmlJSScope::Ptr &scope, const QString &name,
78 const QQmlJSScope::JavaScriptIdentifier &identifier) override;
79
80 void addImportWithLocation(const QString &name, const QQmlJS::SourceLocation &loc,
81 bool hadWarnings) override;
82 void addStaticImportWithLocation(const QString &name, const QQmlJS::SourceLocation &loc,
83 bool isDependency) override;
84
85 QSet<QString> *usedTypes() override { return &m_usedTypes; }
86
87private:
88 struct SeenImport
89 {
90 QStringView filename;
91 QString uri;
92 QTypeRevision version;
93 QStringView id;
94 QQmlJS::AST::UiImport *uiImport;
95
96 SeenImport(QQmlJS::AST::UiImport *i) : filename(i->fileName), id(i->importId), uiImport(i)
97 {
98 if (i->importUri)
99 uri = i->importUri->toString();
100 if (i->version)
101 version = i->version->version;
102 }
103 friend bool comparesEqual(const SeenImport &lhs, const SeenImport &rhs) noexcept
104 {
105 return lhs.filename == rhs.filename && lhs.uri == rhs.uri
106 && lhs.version == rhs.version && lhs.id == rhs.id;
107 }
108 Q_DECLARE_EQUALITY_COMPARABLE(SeenImport)
109
110 friend size_t qHash(const SeenImport &i, size_t seed = 0)
111 {
112 return qHashMulti(seed, i.filename, i.uri, i.version, i.id);
113 }
114 };
115 QQmlJS::Engine *m_engine = nullptr;
116 QSet<SeenImport> m_seenImports;
117 QSet<std::pair<const QQmlJSScope *, QString>> misplacedJSIdentifiers;
118 std::vector<QQmlJS::AST::Node *> m_ancestryIncludingCurrentNode;
119 QQmlJS::LinterRenamedComponents m_renamedComponents;
120
121 // Maps all qmlNames to the source location of their import
122 QMultiHash<QString, QQmlJS::SourceLocation> m_importTypeLocationMap;
123 // Maps all static modules to the source location of their import
124 QMultiHash<QString, QQmlJS::SourceLocation> m_importStaticModuleLocationMap;
125 // Contains all import source locations (could be extracted from above but that is expensive)
126 QSet<QQmlJS::SourceLocation> m_importLocations;
127 // A set of all types that have been used during type resolution
128 QSet<QString> m_usedTypes;
129
130 void handleDuplicateEnums(QQmlJS::AST::UiEnumMemberList *members, QStringView key,
131 const QQmlJS::SourceLocation &location);
132 void warnCaseNoFlowControl(QQmlJS::SourceLocation caseToken) const;
133 void checkCaseFallthrough(QQmlJS::AST::StatementList *statements, SourceLocation errorLoc,
134 SourceLocation nextLoc);
136 const QString &name, const QQmlJS::AST::Statement *statement,
137 const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition = nullptr) override;
138 void handleLiteralBinding(const QQmlJSMetaPropertyBinding &binding,
139 const AST::UiPublicMember *associatedPropertyDefinition) override;
140 void handleUselessExpressionStatement(const AST::ExpressionStatement *ast);
141 void handleRecursivelyInstantiatedType(AST::UiQualifiedId *qualifiedId);
142 void handleRenamedType(QQmlJS::AST::UiQualifiedId *id);
143 void checkSingletonRoot();
144 void checkFileSelections();
145 void checkUnusedImports();
146
147 bool m_rootIsSingleton = false;
148};
149
150} // namespace QQmlJS
151
152QT_END_NAMESPACE
153
154#endif // QQMLJSLINTERVISITOR_P_H
void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName, QQmlJS::SourceLocation declarationLocation, QQmlJS::SourceLocation accessLocation) override
void reportFunctionUsedBeforeDeclaration(const QString &name, const QString &fileName, QQmlJS::SourceLocation declarationLocation, QQmlJS::SourceLocation accessLocation) override
UnreachableVisitor * unreachableVisitor() override
CodegenWarningInterface(QQmlJSLogger *logger)
bool visit(QQmlJS::AST::FunctionDeclaration *functionDeclaration) override
void throwRecursionDepthError() override
void setPassManager(QQmlSA::PassManager *passManager)
const QList< QQmlJS::LoggerCategory > categories() const
bool isInternal() const
Plugin(Plugin &&plugin) noexcept
Plugin(const QStaticPlugin &plugin)
const QString & name() const
const QString & version() const
const QString & author() const
void setEnabled(bool isEnabled)
const QString & description() const
Result lintModule(const QString &uri, LintOptions options, const QStringList &qmlImportPaths, const QStringList &resourceFiles)
void setPluginsEnabled(bool enablePlugins)
bool useAbsolutePath() const
Result lintFileInBatch(const QString &filename)
static std::vector< Plugin > loadPlugins(QStringList paths)
QQmlJSLinter(const QStringList &importPaths, const QStringList &extraPluginPaths={}, bool useAbsolutePath=false)
std::vector< Plugin > & plugins()
void setPlugins(std::vector< Plugin > plugins)
bool prepareFileForBatchLinting(const QString &filename, const QString *fileContents, LintOptions options, const QStringList &qmlImportPaths, const QStringList &qmldirFiles, const QStringList &resourceFiles, const QList< QQmlJS::LoggerCategory > &categories)
QQmlJSImporter m_importer
Q_DECLARE_FLAGS(LintOptions, LintOption)
static FixResult applyFixes(const QQmlJSLogger *logger, QString *fixedCode, bool silent)
bool pluginsEnabled() const
void postVisit(QQmlJS::AST::Node *) override
QSet< QString > * usedTypes() override
void addStaticImportWithLocation(const QString &name, const QQmlJS::SourceLocation &loc, bool isDependency) 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)
const QQmlJS::LinterRenamedComponents & renamedComponents() const
BindingExpressionParseResult parseBindingExpression(const QString &name, const QQmlJS::AST::Statement *statement, const QQmlJS::AST::UiPublicMember *associatedPropertyDefinition=nullptr) override
void addImportWithLocation(const QString &name, const QQmlJS::SourceLocation &loc, bool hadWarnings) override
bool safeInsertJSIdentifier(QQmlJSScope::Ptr &scope, const QString &name, const QQmlJSScope::JavaScriptIdentifier &identifier) override
bool visit(QQmlJS::AST::StringLiteral *) override
QQmlJS::AST::Node * astParentOfVisitedNode() const
void endVisit(QQmlJS::AST::FieldMemberExpression *fieldMember) override
bool preVisit(QQmlJS::AST::Node *) override
UnreachableVisitor(QQmlJSLogger *logger)
void throwRecursionDepthError() override
bool containsFunctionDeclaration(QQmlJS::AST::Node *node)
bool visit(QQmlJS::AST::StatementList *unreachable) override
\inmodule QtQmlCompiler
Combined button and popup list for selecting options.
static void addJsonWarning(QJsonArray &warnings, const QQmlJS::DiagnosticMessage &message, QAnyStringView id, const std::optional< QQmlJSFixSuggestion > &suggestion={})
static void processMessages(const QQmlJSLogger &logger, QJsonArray &warnings)
std::unique_ptr< QQmlJSLogger > logger