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
utilities.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
4#include "utilities.h"
5
6#include "inode.h"
7#include "location.h"
8#include "textutils.h"
9
10#include <QtCore/qfileinfo.h>
11#include <QtCore/qprocess.h>
12
14
15/*!
16 \namespace Utilities
17 \internal
18 \brief This namespace holds QDoc-internal utility methods.
19 */
20namespace Utilities {
21static inline void setDebugEnabled(bool value)
22{
23 const_cast<QLoggingCategory &>(lcQdoc()).setEnabled(QtDebugMsg, value);
24 const_cast<QLoggingCategory &>(lcQdocClang()).setEnabled(QtDebugMsg, value);
25}
26
27void startDebugging(const QString &message)
28{
30 qCDebug(lcQdoc, "START DEBUGGING: %ls", qUtf16Printable(message));
31}
32
33void stopDebugging(const QString &message)
34{
35 qCDebug(lcQdoc, "STOP DEBUGGING: %ls", qUtf16Printable(message));
37}
38
40{
41 return lcQdoc().isEnabled(QtDebugMsg);
42}
43
44/*!
45 \brief Converts a string representation of a pointer address to an INode pointer.
46
47 This function takes a \a string, assumed to contain the numerical
48 representation of an INode pointer's address (as generated by
49 stringForNode()), and casts it back to an \c INode pointer.
50
51 \sa stringForNode()
52 */
53const INode *nodeForString(const QString &string)
54{
55 return reinterpret_cast<const INode *>(string.toULongLong());
56}
57/*!
58 \brief Converts an INode pointer address to its string representation.
59
60 This function takes a \a node pointer and returns a string that contains the
61 numerical value of its memory address. This is used for serialization or
62 passing node references where a direct pointer cannot be used.
63
64 \note The returned string is only valid within the same process. It does
65 \e {not} persist across runs.
66 */
68{
69 return QString::number(reinterpret_cast<quintptr>(node));
70}
71
72/*!
73 Returns a unique identifier based on location \a loc, with a
74 given \a prefix.
75*/
76QString uniqueIdentifier(const Location &loc, const QString &prefix)
77{
78 Q_ASSERT(!loc.filePath().isEmpty());
79 QFileInfo fi{loc.filePath()};
80 const auto id = QLatin1String("%1_%2_%3").arg(prefix, fi.fileName(), QString::number(loc.lineNo()));
81 return TextUtils::asAsciiPrintable(id);
82}
83
84/*!
85 \internal
86*/
87static bool runProcess(const QString &program, const QStringList &arguments,
88 QByteArray *stdOutIn, QByteArray *stdErrIn)
89{
90 QProcess process;
91 process.start(program, arguments, QProcess::ReadWrite);
92 if (!process.waitForStarted()) {
93 qCDebug(lcQdoc).nospace() << "Unable to start " << process.program()
94 << ": " << process.errorString();
95 return false;
96 }
97 process.closeWriteChannel();
98 const bool finished = process.waitForFinished();
99 const QByteArray stdErr = process.readAllStandardError();
100 if (stdErrIn)
101 *stdErrIn = stdErr;
102 if (stdOutIn)
103 *stdOutIn = process.readAllStandardOutput();
104
105 if (!finished) {
106 qCDebug(lcQdoc).nospace() << process.program() << " timed out: " << stdErr;
107 process.kill();
108 return false;
109 }
110
111 if (process.exitStatus() != QProcess::NormalExit) {
112 qCDebug(lcQdoc).nospace() << process.program() << " crashed: " << stdErr;
113 return false;
114 }
115
116 if (process.exitCode() != 0) {
117 qCDebug(lcQdoc).nospace() << process.program() << " exited with "
118 << process.exitCode() << ": " << stdErr;
119 return false;
120 }
121
122 return true;
123}
124
125/*!
126 \internal
127*/
129 return QByteArrayLiteral(" (framework directory)");
130}
131
132/*!
133 \internal
134 Determine the compiler's internal include paths from the output of
135
136 \badcode
137 [clang++|g++] -E -x c++ - -v </dev/null
138 \endcode
139
140 Output looks like:
141
142 \badcode
143 #include <...> search starts here:
144 /usr/local/include
145 /System/Library/Frameworks (framework directory)
146 End of search list.
147 \endcode
148*/
149QStringList getInternalIncludePaths(const QString &compiler)
150{
151 QStringList result;
152 QStringList arguments;
153 arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++")
154 << QStringLiteral("-") << QStringLiteral("-v");
155 QByteArray stdOut;
156 QByteArray stdErr;
157 if (!runProcess(compiler, arguments, &stdOut, &stdErr))
158 return result;
159 const QByteArrayList stdErrLines = stdErr.split('\n');
160 bool isIncludeDir = false;
161 for (const QByteArray &line : stdErrLines) {
162 if (isIncludeDir) {
163 if (line.startsWith(QByteArrayLiteral("End of search list"))) {
164 isIncludeDir = false;
165 } else {
166 QByteArray prefix("-I");
167 QByteArray headerPath{line.trimmed()};
168 if (headerPath.endsWith(frameworkSuffix())) {
169 headerPath.truncate(headerPath.size() - frameworkSuffix().size());
170 prefix = QByteArrayLiteral("-F");
171 }
172 result.append(QString::fromLocal8Bit(prefix + headerPath));
173 }
174 } else if (line.startsWith(QByteArrayLiteral("#include <...> search starts here"))) {
175 isIncludeDir = true;
176 }
177 }
178
179 return result;
180}
181
182bool isGeneratedFile(const QString &path)
183{
184 QString fileName = QFileInfo(path).fileName();
185 return fileName.startsWith("moc_") ||
186 fileName.startsWith("qrc_") ||
187 fileName.startsWith("ui_");
188}
189
190/*!
191 Returns a string list containing the path and fragment components of the
192 given \a linkText. Fragments begin with a "#" character, following HTML
193 conventions.
194
195 Links with only a path or only a fragment will result in lists of one
196 element. A link with both path and fragment will result in a list of two
197 elements. Additional fragments are discarded.
198
199 Escaped "#" characters ("\\#") are interpreted differently to regular "#"
200 characters. These can be used to represent "#" characters in titles, but
201 not in fragments.
202*/
203QStringList pathAndFragment(const QString &linkText)
204{
205 QStringList pieces = linkText.split("\\#"_L1);
206 QStringList result;
207 QString next;
208
209 for (auto &piece : pieces) {
210 QStringList fragmentPieces = piece.split('#');
211 next += fragmentPieces.takeFirst();
212 if (!fragmentPieces.isEmpty()) {
213 result.append(next);
214 next = fragmentPieces.first();
215 }
216 if (result.count() == 2)
217 break;
218 }
219 if (!next.isEmpty() && result.count() < 2)
220 result.append(next);
221
222 return result;
223}
224
225/*!
226 Constructs an href link from an example file name.
227
228 The \a path is the path to the example file. The \a project is the
229 module name (used as prefix). The \a fileExt is the file extension
230 for the generated link.
231 */
232QString linkForExampleFile(const QString &path, const QString &project, const QString &fileExt)
233{
234 QString link = project.toLower() + QLatin1Char('-') + path;
235 return TextUtils::asAsciiPrintable(link) + QLatin1Char('.') + fileExt;
236}
237
238/*!
239 Constructs a title for a file or image page in an example.
240
241 Returns the base name of \a fileName with the appropriate suffix
242 based on \a kind: " Example File" for ExampleFileKind::File,
243 " Image File" for ExampleFileKind::Image.
244
245 Use this overload when you already know whether the file is an
246 example file or image (e.g., when iterating separate file/image lists).
247 */
248QString exampleFileTitle(const QString &fileName, ExampleFileKind kind)
249{
250 const QString suffix = [kind]() {
251 switch (kind) {
252 case ExampleFileKind::File:
253 return " Example File"_L1;
254 case ExampleFileKind::Image:
255 return " Image File"_L1;
256 }
257 Q_UNREACHABLE();
258 }();
259 return QFileInfo(fileName).fileName() + suffix;
260}
261
262/*!
263 Constructs a title for a file or image page in an example.
264
265 If \a fileName is found in \a files, returns the base name with
266 " Example File" suffix. If found in \a images, returns the base
267 name with " Image File" suffix. If not found in either list,
268 returns an empty string.
269
270 Matching uses exact string equality, not basename comparison.
271
272 \note This overload performs O(n) membership checks. When iterating
273 known file or image lists, prefer the overload taking ExampleFileKind.
274 */
275QString exampleFileTitle(const QStringList &files, const QStringList &images, const QString &fileName)
276{
277 if (files.contains(fileName))
278 return exampleFileTitle(fileName, ExampleFileKind::File);
279 if (images.contains(fileName))
280 return exampleFileTitle(fileName, ExampleFileKind::Image);
281 return {};
282}
283
284} // namespace Utilities
285
286QT_END_NAMESPACE
Definition inode.h:20
The Location class provides a way to mark a location in a file.
Definition location.h:20
Combined button and popup list for selecting options.
This namespace holds QDoc-internal utility methods.
Definition utilities.h:21
QString uniqueIdentifier(const Location &loc, const QString &prefix)
Returns a unique identifier based on location loc, with a given prefix.
Definition utilities.cpp:76
QString exampleFileTitle(const QStringList &files, const QStringList &images, const QString &fileName)
Constructs a title for a file or image page in an example.
static void setDebugEnabled(bool value)
Definition utilities.cpp:21
QStringList getInternalIncludePaths(const QString &compiler)
QString exampleFileTitle(const QString &fileName, ExampleFileKind kind)
Constructs a title for a file or image page in an example.
bool debugging()
Definition utilities.cpp:39
bool isGeneratedFile(const QString &path)
const INode * nodeForString(const QString &string)
Converts a string representation of a pointer address to an INode pointer.
Definition utilities.cpp:53
void stopDebugging(const QString &message)
Definition utilities.cpp:33
static QByteArray frameworkSuffix()
QStringList pathAndFragment(const QString &linkText)
Returns a string list containing the path and fragment components of the given linkText.
void startDebugging(const QString &message)
Definition utilities.cpp:27
static bool runProcess(const QString &program, const QStringList &arguments, QByteArray *stdOutIn, QByteArray *stdErrIn)
Definition utilities.cpp:87
QString linkForExampleFile(const QString &path, const QString &project, const QString &fileExt)
Constructs an href link from an example file name.
QString stringForNode(const INode *node)
Converts an INode pointer address to its string representation.
Definition utilities.cpp:67