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