9#include <QtCore/qcryptographichash.h>
10#include <QtCore/qfileinfo.h>
11#include <QtCore/qprocess.h>
15Q_LOGGING_CATEGORY(lcQdoc,
"qt.qdoc")
16Q_LOGGING_CATEGORY(lcQdocClang,
"qt.qdoc.clang")
19
20
21
22
26 const_cast<QLoggingCategory &>(lcQdoc()).setEnabled(QtDebugMsg, value);
27 const_cast<QLoggingCategory &>(lcQdocClang()).setEnabled(QtDebugMsg, value);
33 qCDebug(lcQdoc,
"START DEBUGGING: %ls", qUtf16Printable(message));
38 qCDebug(lcQdoc,
"STOP DEBUGGING: %ls", qUtf16Printable(message));
44 return lcQdoc().isEnabled(QtDebugMsg);
48
49
50
51
52
53
54
55
58 return reinterpret_cast<
const INode *>(string.toULongLong());
61
62
63
64
65
66
67
68
69
72 return QString::number(
reinterpret_cast<quintptr>(node));
76
77
78
81 Q_ASSERT(!loc.filePath().isEmpty());
82 QFileInfo fi{loc.filePath()};
83 const auto id = QLatin1String(
"%1_%2_%3").arg(prefix, fi.fileName(), QString::number(loc.lineNo()));
84 return asAsciiPrintable(id);
89
90
91
92
93
94
95
96
99 static QString terminator = QStringLiteral(
".");
100 if (wordPosition == numberOfWords - 1)
103 return comma(wordPosition, numberOfWords);
107
108
109
110
111
112
113
114
115
116
119 if (wordPosition == numberOfWords - 1)
121 if (numberOfWords == 2)
122 return QStringLiteral(
" and ");
123 if (wordPosition == 0 || wordPosition < numberOfWords - 2)
124 return QStringLiteral(
", ");
125 return QStringLiteral(
", and ");
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
159 auto legal_ascii = [](
const uint value) {
160 const uint start_ascii_subset{ 32 };
161 const uint end_ascii_subset{ 126 };
163 return value >= start_ascii_subset && value <= end_ascii_subset;
168 bool has_non_alnum_content{
false };
170 for (
const auto &c : str) {
171 char16_t u = c.unicode();
173 has_non_alnum_content =
true;
174 if (u >=
'A' && u <=
'Z')
176 if ((u >=
'a' && u <=
'z') || (u >=
'0' && u <=
'9')) {
177 result += QLatin1Char(u);
180 result += QLatin1Char(
'-');
184 if (result.endsWith(QLatin1Char(
'-')))
187 if (has_non_alnum_content) {
188 auto title_hash = QString::fromLocal8Bit(
189 QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5).toHex());
190 title_hash.truncate(8);
191 if (!result.isEmpty())
192 result.append(QLatin1Char(
'-'));
193 result.append(title_hash);
201 qsizetype n = str.size();
203 marked.reserve(n * 2 + 30);
204 const QChar *data = str.constData();
205 for (
int i = 0; i != n; ++i) {
206 switch (data[i].unicode()) {
227
228
229static bool runProcess(
const QString &program,
const QStringList &arguments,
230 QByteArray *stdOutIn, QByteArray *stdErrIn)
233 process.start(program, arguments, QProcess::ReadWrite);
234 if (!process.waitForStarted()) {
235 qCDebug(lcQdoc).nospace() <<
"Unable to start " << process.program()
236 <<
": " << process.errorString();
239 process.closeWriteChannel();
240 const bool finished = process.waitForFinished();
241 const QByteArray stdErr = process.readAllStandardError();
245 *stdOutIn = process.readAllStandardOutput();
248 qCDebug(lcQdoc).nospace() << process.program() <<
" timed out: " << stdErr;
253 if (process.exitStatus() != QProcess::NormalExit) {
254 qCDebug(lcQdoc).nospace() << process.program() <<
" crashed: " << stdErr;
258 if (process.exitCode() != 0) {
259 qCDebug(lcQdoc).nospace() << process.program() <<
" exited with "
260 << process.exitCode() <<
": " << stdErr;
268
269
271 return QByteArrayLiteral(
" (framework directory)");
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
294 QStringList arguments;
295 arguments << QStringLiteral(
"-E") << QStringLiteral(
"-x") << QStringLiteral(
"c++")
296 << QStringLiteral(
"-") << QStringLiteral(
"-v");
299 if (!runProcess(compiler, arguments, &stdOut, &stdErr))
301 const QByteArrayList stdErrLines = stdErr.split(
'\n');
302 bool isIncludeDir =
false;
303 for (
const QByteArray &line : stdErrLines) {
305 if (line.startsWith(QByteArrayLiteral(
"End of search list"))) {
306 isIncludeDir =
false;
308 QByteArray prefix(
"-I");
309 QByteArray headerPath{line.trimmed()};
310 if (headerPath.endsWith(frameworkSuffix())) {
311 headerPath.truncate(headerPath.size() - frameworkSuffix().size());
312 prefix = QByteArrayLiteral(
"-F");
314 result.append(QString::fromLocal8Bit(prefix + headerPath));
316 }
else if (line.startsWith(QByteArrayLiteral(
"#include <...> search starts here"))) {
326 QString fileName = QFileInfo(path).fileName();
327 return fileName.startsWith(
"moc_") ||
328 fileName.startsWith(
"qrc_") ||
329 fileName.startsWith(
"ui_");
The Location class provides a way to mark a location in a file.
This namespace holds QDoc-internal utility methods.
QString uniqueIdentifier(const Location &loc, const QString &prefix)
Returns a unique identifier based on location loc, with a given prefix.
static void setDebugEnabled(bool value)
QStringList getInternalIncludePaths(const QString &compiler)
bool isGeneratedFile(const QString &path)
QString asAsciiPrintable(const QString &name)
Returns an ascii-printable representation of str.
QString protect(const QString &string)
const INode * nodeForString(const QString &string)
Converts a string representation of a pointer address to an INode pointer.
void stopDebugging(const QString &message)
static QByteArray frameworkSuffix()
QString comma(qsizetype wordPosition, qsizetype numberOfWords)
QString separator(qsizetype wordPosition, qsizetype numberOfWords)
void startDebugging(const QString &message)
static bool runProcess(const QString &program, const QStringList &arguments, QByteArray *stdOutIn, QByteArray *stdErrIn)
QString stringForNode(const INode *node)
Converts an INode pointer address to its string representation.