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