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
qqmljslintercodegen.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
7
8#include <private/qqmljsbasicblocks_p.h>
9#include <private/qqmljsfunctioninitializer_p.h>
10#include <private/qqmljsimportvisitor_p.h>
11#include <private/qqmljsshadowcheck_p.h>
12#include <private/qqmljsstoragegeneralizer_p.h>
13#include <private/qqmljsstorageinitializer_p.h>
14
15#include <QFileInfo>
16
18
19using namespace Qt::StringLiterals;
20
21bool operator==(const IdMemberShadow &lhs, const IdMemberShadow &rhs)
22{
23 return lhs.name == rhs.name && lhs.idScope == rhs.idScope
24 && lhs.memberOwnerScope == rhs.memberOwnerScope;
25}
26bool operator!=(const IdMemberShadow &lhs, const IdMemberShadow &rhs)
27{
28 return !(lhs == rhs);
29}
30size_t qHash(const IdMemberShadow &idShadowsMember, size_t seed)
31{
32 return qHashMulti(seed, idShadowsMember.name, idShadowsMember.idScope,
33 idShadowsMember.memberOwnerScope);
34}
35
36QQmlJSLinterCodegen::QQmlJSLinterCodegen(QQmlJSImporter *importer, const QString &fileName,
37 const QStringList &qmldirFiles, QQmlJSLogger *logger,
38 const ContextPropertyInfo &contextPropertyInfo)
39 : QQmlJSAotCompiler(importer, fileName, qmldirFiles, logger),
40 m_contextPropertyInfo(contextPropertyInfo)
41{
42 m_flags |= QQmlJSAotCompiler::IsLintCompiler;
43}
44
45void QQmlJSLinterCodegen::setDocument(const QmlIR::JSCodeGen *codegen,
46 const QmlIR::Document *document)
47{
48 Q_UNUSED(codegen);
49 m_document = document;
50 m_unitGenerator = &document->jsGenerator;
51}
52
53std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
54QQmlJSLinterCodegen::compileBinding(const QV4::Compiler::Context *context,
55 const QmlIR::Binding &irBinding, QQmlJS::AST::Node *astNode)
56{
57 const QString name = m_document->stringAt(irBinding.propertyNameIndex);
58 m_logger->setCompileErrorPrefix(
59 u"Could not determine signature of binding for %1: "_s.arg(name));
60
61 QQmlJSFunctionInitializer initializer(
62 &m_typeResolver, m_currentObject->location, m_currentScope->location, m_logger);
63 QQmlJSCompilePass::Function function = initializer.run(context, name, astNode, irBinding);
64
65 m_logger->iterateCurrentFunctionMessages([this](const Message &error) {
66 diagnose(error.message, error.type, error.loc);
67 });
68
69 m_logger->setCompileErrorPrefix(u"Could not compile binding for %1: "_s.arg(name));
70 m_logger->setCompileSkipPrefix(u"Compilation of binding for %1 was skipped: "_s.arg(name));
71
72 analyzeFunction(context, &function);
73 if (const auto errors = finalizeBindingOrFunction())
74 return *errors;
75
76 return QQmlJSAotFunction {};
77}
78
79std::variant<QQmlJSAotFunction, QList<QQmlJS::DiagnosticMessage>>
80QQmlJSLinterCodegen::compileFunction(const QV4::Compiler::Context *context,
81 const QString &name, QQmlJS::AST::Node *astNode)
82{
83 m_logger->setCompileErrorPrefix(u"Could not determine signature of function %1: "_s.arg(name));
84
85 QQmlJSFunctionInitializer initializer(
86 &m_typeResolver, m_currentObject->location, m_currentScope->location, m_logger);
87 QQmlJSCompilePass::Function function = initializer.run(context, name, astNode);
88
89 m_logger->iterateCurrentFunctionMessages([this](const Message &error) {
90 diagnose(error.message, error.type, error.loc);
91 });
92
93 m_logger->setCompileErrorPrefix(u"Could not compile function %1: "_s.arg(name));
94 m_logger->setCompileSkipPrefix(u"Compilation of function %1 was skipped: "_s.arg(name));
95 analyzeFunction(context, &function);
96
97 if (const auto errors = finalizeBindingOrFunction())
98 return *errors;
99
100 return QQmlJSAotFunction {};
101}
102
103void QQmlJSLinterCodegen::setPassManager(QQmlSA::PassManager *passManager)
104{
105 m_passManager = passManager;
106 auto managerPriv = QQmlSA::PassManagerPrivate::get(passManager);
107 managerPriv->m_typeResolver = typeResolver();
108}
109
110void QQmlJSLinterCodegen::analyzeFunction(const QV4::Compiler::Context *context,
111 QQmlJSCompilePass::Function *function)
112{
113 bool dummy = false;
114 QQmlJSCompilePass::BlocksAndAnnotations blocksAndAnnotations =
115 QQmlJSBasicBlocks(context, m_unitGenerator, &m_typeResolver, m_logger)
116 .run(function, ValidateBasicBlocks, dummy);
117
118 QQmlJSLinterTypePropagator lintTypePropgator(
119 m_unitGenerator, &m_typeResolver, m_logger, blocksAndAnnotations.basicBlocks,
120 blocksAndAnnotations.annotations, m_passManager, m_contextPropertyInfo);
121 lintTypePropgator.setScopesById(m_scopesById);
122 lintTypePropgator.setIdMemberShadows(&m_idMemberShadows);
123 blocksAndAnnotations = lintTypePropgator.run(function);
124
125 if (m_logger->categorySeverity(qmlCompiler) == QQmlJS::WarningSeverity::Disable)
126 return;
127
128 if (!m_logger->currentFunctionHasCompileError()) {
129 blocksAndAnnotations = QQmlJSShadowCheck(m_unitGenerator, &m_typeResolver, m_logger,
130 blocksAndAnnotations.basicBlocks,
131 blocksAndAnnotations.annotations)
132 .run(function);
133 }
134
135 if (!m_logger->currentFunctionHasCompileError()) {
136 blocksAndAnnotations = QQmlJSStorageInitializer(m_unitGenerator, &m_typeResolver, m_logger,
137 blocksAndAnnotations.basicBlocks,
138 blocksAndAnnotations.annotations)
139 .run(function);
140 }
141
142 if (!m_logger->currentFunctionHasCompileError()) {
143 blocksAndAnnotations = QQmlJSStorageGeneralizer(m_unitGenerator, &m_typeResolver, m_logger,
144 blocksAndAnnotations.basicBlocks,
145 blocksAndAnnotations.annotations)
146 .run(function);
147 }
148}
149
150QT_END_NAMESPACE
void setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document) override
void setPassManager(QQmlSA::PassManager *passManager)
\inmodule QtQmlCompiler
Combined button and popup list for selecting options.
bool operator==(const IdMemberShadow &lhs, const IdMemberShadow &rhs)
bool operator!=(const IdMemberShadow &lhs, const IdMemberShadow &rhs)
size_t qHash(const IdMemberShadow &idShadowsMember, size_t seed)