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