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
qqmljscontextproperties.cpp
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
6
7#include <private/qtqmlglobal_p.h>
8
9#include <QtCore/qtconfigmacros.h>
10#include <QtCore/qregularexpression.h>
11#include <QtCore/qdirlisting.h>
12#include <QtCore/qfile.h>
13
14#if QT_CONFIG(qmlcontextpropertydump)
15# include <QtCore/qsettings.h>
16#endif
17
18#if QT_CONFIG(process)
19# include <QtCore/qprocess.h>
20#endif
21
23
24namespace QQmlJS {
25
26using namespace Qt::StringLiterals;
27
28// There are many ways to set context properties without triggering the regexp in s_pattern,
29// but its supposed to catch most context properties set via "setContextProperty".
30static constexpr QLatin1StringView s_pattern =
31 R"x((\.|->)setContextProperty\s*\‍(\s*(QStringLiteral\s*\‍(|QString\s*\‍(|QLatin1String(View)?\s*\‍(|u)?\s*"([^"]*)")x"_L1;
32static constexpr int s_contextPropertyNameIdxInPattern = 4;
33
34// TODO: use a central list of file extensions that can also be used by qmetatypesjsonprocessor.cpp
35// (that needs header file extensions) and Qt6QmlMacros.cmake.
36static constexpr std::array s_fileFilters = {
37 "*.cpp"_L1, "*.cxx"_L1, "*.cc"_L1, "*.c"_L1, "*.c++"_L1,
38 "*.hpp"_L1, "*.hxx"_L1, "*.hh"_L1, "*.h"_L1, "*.h++"_L1,
39};
40
43
46{
47 const auto it = m_properties.find(name);
48 if (it != m_properties.end())
49 return it.value();
50 return {};
51}
52
54{
55 if (const auto it = m_properties.find(name); it != m_properties.end()) {
57 return;
58 }
60}
61
63{
66 return;
67
74
77 }
78}
79
81{
83
84 for (const QString &url : rootUrls) {
85 for (const auto &dirEntry : QDirListing{ url, fileFilters,
88
91 }
92 }
93}
94
95#if QT_CONFIG(process) && !defined(Q_OS_WINDOWS)
97{
98 for (const auto line : QStringTokenizer{ output, "\n"_L1, Qt::SkipEmptyParts })
100}
101#endif
102
110
111/*!
112 \internal
113 Uses grep to find files that have setContextProperty()-calls, and then search matching files
114 with QRegularExpression to extract the location and name of the found context properties.
115*/
117{
118 if (dirs.isEmpty())
119 return;
120
121#if QT_CONFIG(process) && !defined(Q_OS_WINDOWS)
122 if (qEnvironmentVariableIsSet("QT_QML_NO_GREP")) {
124 return;
125 }
126
128 QStringList arguments{ "--recursive"_L1,
129 "--null-data"_L1, // match multiline patterns
130 "--files-with-matches"_L1,
131 "--extended-regexp"_L1, // the pattern is "extended"
132 "-e"_L1,
133 s_pattern };
134
135 // don't search non-cpp files
136 for (const auto fileFilter : s_fileFilters)
137 arguments << "--include"_L1 << fileFilter;
138
140 grep.start("grep"_L1, arguments);
143 switch (grep.exitCode()) {
144 case 0: { // success
147 return;
148 }
149 case 1: // success but no context properties found
150 return;
151 default: // grep error
152 break;
153 }
154 }
155#endif
157}
158
159#if QT_CONFIG(qmlcontextpropertydump)
161{
162 constexpr int size = 4;
164 if (bits.length() != size)
165 return SourceLocation{};
166
170
171 bool everythingOk = true;
172 for (int i = 0; i < size; ++i) {
173 bool ok = false;
174 *destination[i] = bits[i].toInt(&ok);
175 everythingOk &= ok;
176 }
177
178 if (everythingOk)
179 return result;
180 return SourceLocation{};
181}
182
184{
190 return result;
191}
192#endif
193
194static constexpr auto cachedHeuristicListKey = "cachedHeuristicList"_L1;
195
197{
198#if QT_CONFIG(qmlcontextpropertydump)
201
203 for (int i = 0; i < size; ++i) {
206 }
208
209 for (const auto &name : names) {
210 const int size = settings->beginReadArray(u"property_"_s.append(name));
211 for (int i = 0; i < size; ++i) {
213 result.add(
214 name,
216 settings->value("fileName").toString(),
217 deserializeSourceLocation(settings->value("sourceLocation").toString()),
218 });
219 }
221 }
222 return result;
223#else
226#endif
227}
228
230{
231#if QT_CONFIG(qmlcontextpropertydump)
232 QSettings settings(folder + "/.qt/contextPropertyDump.ini"_L1, QSettings::IniFormat);
234 int index = 0;
235 for (const auto &[name, _] : m_properties) {
237 settings.setValue("name", name);
238 }
240
241 for (const auto &[name, definitions] : m_properties) {
242 settings.beginWriteArray(u"property_"_s.append(name));
243 for (int i = 0; i < definitions.size(); ++i) {
245 settings.setValue("fileName", definitions[i].filename);
247 }
249 }
250#else
252#endif
253}
254} // namespace QQmlJS
255
256QT_END_NAMESPACE
static const QRegularExpression s_matchSetContextProperty
static constexpr auto cachedHeuristicListKey
static constexpr QLatin1StringView s_pattern
static constexpr int s_contextPropertyNameIdxInPattern
static constexpr std::array s_fileFilters