7#include <QtCore/qdir.h>
8#include <QtCore/qfile.h>
9#include <QtCore/qtemporaryfile.h>
10#include <QtCore/qtextstream.h>
11#include <QtCore/qvariant.h>
12#include <QtCore/qregularexpression.h>
16QString ConfigStrings::AUTOLINKERRORS = QStringLiteral(
"autolinkerrors");
69 QStringLiteral(
"redirectdocumentationtodevnull");
98
99
100
113
114
115
118 next.append(QString());
122
123
124
125
133
134
135
136
147
148
149
157
158
159
160
163 if (ch == QLatin1Char(
'{')) {
166 }
else if (ch == QLatin1Char(
'}')) {
168 location.fatal(QStringLiteral(
"Unexpected '}'"));
171 const QStringList suffixes = pop().accum;
172 const QStringList prefixes = top().next;
175 for (
const auto &prefix : prefixes) {
176 for (
const auto &suffix : suffixes)
177 top().next << prefix + suffix;
179 }
else if (ch == QLatin1Char(
',') && size() > 1) {
183 for (QString &topNext : top().next)
189
190
194 location.fatal(QStringLiteral(
"Missing '}'"));
201bool Config::m_debug =
false;
202bool Config::m_atomsDump =
false;
207QMap<QString, QString>
Config::m_extractedDirs;
208QStack<QString>
Config::m_workingDirs;
209QMap<QString, QStringList>
Config::m_includeFilesMap;
212
213
214
215
218
219
220
221
222
223
224
225
226
229 if (m_name.isEmpty())
230 return defaultString;
233 for (
const auto &value : std::as_const(m_values)) {
234 if (!result.isEmpty() && !result.endsWith(QChar(
'\n')))
235 result.append(QChar(
' '));
236 result.append(value.m_value);
242
243
247 for (
const auto &value : std::as_const(m_values))
248 result << value.m_value;
253
254
257 const auto &stringList = asStringList();
258 return QSet<QString>(stringList.cbegin(), stringList.cend());
262
263
266 return QVariant(asString()).toBool();
270
271
272
273
274
275
276
279 const QStringList strs = asStringList();
284 for (
const auto &str : strs)
290
291
292
295 m_expandVars << other.m_expandVars;
296 QList<ExpandVar>::Iterator it = m_expandVars.end();
297 it -= other.m_expandVars.size();
298 std::for_each(it, m_expandVars.end(), [
this](ExpandVar &v) {
299 v.m_valueIndex += m_values.size();
301 m_values << other.m_values;
302 m_location = other.m_location;
306
307
308
309
310
311
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
333
334
335
336
337void Config::
init(
const QString &programName,
const QStringList &args)
339 m_prog = programName;
340 processCommandLineOptions(args);
350
351
354 m_location = Location();
355 m_configVars.clear();
356 m_includeFilesMap.clear();
357 m_excludedPaths.reset();
361
362
380 const auto setListFlag = [
this](
const QString &key,
bool test) {
381 setStringList(key, QStringList(test ? QStringLiteral(
"true") : QStringLiteral(
"false")));
383#define SET(opt, test) setListFlag(opt, m_parser.isSet(m_parser.test))
392 m_parser.isSet(m_parser.noLinkErrorsOption)
393 || qEnvironmentVariableIsSet(
"QDOC_NOLINKERRORS"));
399
400
401
402
403
410 load(Location(), fileName);
411 if (m_location.isEmpty())
412 m_location = Location(fileName);
414 m_location.setEtc(
true);
430
431
432void Config::expandVariables()
434 for (
auto &configVar : m_configVars) {
435 for (
auto it = configVar.m_expandVars.crbegin(); it != configVar.m_expandVars.crend(); ++it) {
436 Q_ASSERT(it->m_valueIndex < configVar.m_values.size());
437 const QString &key = it->m_var;
438 const auto &refVar = m_configVars.value(key);
439 if (refVar.m_name.isEmpty()) {
440 configVar.m_location.fatal(
441 QStringLiteral(
"Environment or configuration variable '%1' undefined")
443 }
else if (!refVar.m_expandVars.empty()) {
444 configVar.m_location.fatal(
445 QStringLiteral(
"Nested variable expansion not allowed"),
446 QStringLiteral(
"When expanding '%1' at %2:%3")
447 .arg(refVar.m_name, refVar.m_location.filePath(),
448 QString::number(refVar.m_location.lineNo())));
451 if (it->m_delim.isNull())
452 expanded = m_configVars.value(key).asStringList().join(QString());
454 expanded = m_configVars.value(key).asStringList().join(it->m_delim);
455 configVar.m_values[it->m_valueIndex].m_value.insert(it->m_index, expanded);
457 configVar.m_expandVars.clear();
462
463
466 m_configVars.insert(var, ConfigVar(var, values, QDir::currentPath()));
470
471
472
475 m_configVars[var].append(ConfigVar(var, values, QDir::currentPath()));
479
480
481void Config::processCommandLineOptions(
const QStringList &args)
483 m_parser.process(args);
485 m_defines = m_parser.values(m_parser.defineOption);
486 m_dependModules = m_parser.values(m_parser.dependsOption);
490 generateExamples = !m_parser.isSet(m_parser.noExamplesOption);
491 if (m_parser.isSet(m_parser.installDirOption))
492 installDir = m_parser.value(m_parser.installDirOption);
493 if (m_parser.isSet(m_parser.outputDirOption))
494 overrideOutputDir = QDir(m_parser.value(m_parser.outputDirOption)).absolutePath();
496 const auto outputFormats = m_parser.values(m_parser.outputFormatOption);
497 for (
const auto &format : outputFormats)
498 overrideOutputFormats.insert(format);
499 m_debug = m_parser.isSet(m_parser.debugOption) || qEnvironmentVariableIsSet(
"QDOC_DEBUG");
500 m_atomsDump = m_parser.isSet(m_parser.atomsDumpOption);
501 m_showInternal = m_parser.isSet(m_parser.showInternalOption)
502 || qEnvironmentVariableIsSet(
"QDOC_SHOW_INTERNAL");
504 if (m_parser.isSet(m_parser.prepareOption))
506 if (m_parser.isSet(m_parser.generateOption))
508 if (m_debug || m_parser.isSet(m_parser.logProgressOption))
510 if (m_parser.isSet(m_parser.timestampsOption))
512 if (m_parser.isSet(m_parser.useDocBookExtensions))
516void Config::setIncludePaths()
518 QDir currentDir = QDir::current();
519 const auto addIncludePaths = [
this, currentDir](
const char *flag,
const QStringList &paths) {
520 for (
const auto &path : paths)
521 m_includePaths << currentDir.absoluteFilePath(path).insert(0, flag);
524 addIncludePaths(
"-I", m_parser.values(m_parser.includePathOption));
525#ifdef QDOC_PASS_ISYSTEM
526 addIncludePaths(
"-isystem", m_parser.values(m_parser.includePathSystemOption));
528 addIncludePaths(
"-F", m_parser.values(m_parser.frameworkOption));
532
533
534void Config::setIndexDirs()
536 m_indexDirs = m_parser.values(m_parser.indexDirOption);
537 auto it = std::remove_if(m_indexDirs.begin(), m_indexDirs.end(),
538 [](
const QString &s) {
return !QFile::exists(s); });
540 std::for_each(it, m_indexDirs.end(), [](
const QString &s) {
541 qCWarning(lcQdoc) <<
"Cannot find index directory: " << s;
543 m_indexDirs.erase(it, m_indexDirs.end());
547
548
549
550
551
555 if (overrideOutputDir.isNull())
558 t = overrideOutputDir;
561 t += QLatin1Char(
'/') + project.toLower();
563 if (m_configVars.value(format + Config::dot +
"nosubdirs").asBool()) {
564 QString singleOutputSubdir = m_configVars.value(format + Config::dot +
"outputsubdir").asString();
565 if (singleOutputSubdir.isEmpty())
566 singleOutputSubdir =
"html";
567 t += QLatin1Char(
'/') + singleOutputSubdir;
569 return QDir::cleanPath(t);
573
574
575
576
579 if (overrideOutputFormats.isEmpty())
582 return overrideOutputFormats;
600
601
602
603
604
605
609 const auto &configVar = m_configVars.value(var);
611 for (
const auto &value : configVar.m_values) {
612 const QString ¤tPath = value.m_path;
613 QString rawValue = value.m_value.simplified();
616 if (flags & IncludePaths) {
617 const QStringList prefixes = QStringList()
618 << QLatin1String(
"-I")
619 << QLatin1String(
"-F")
620 << QLatin1String(
"-isystem");
621 const auto end = std::end(prefixes);
623 std::find_if(std::begin(prefixes), end,
624 [&rawValue](
const QString &p) {
625 return rawValue.startsWith(p);
629 rawValue.remove(0, it->size());
630 if (rawValue.isEmpty())
633 prefix = prefixes[0];
637 QDir dir(rawValue.trimmed());
638 const QString path = dir.path();
640 if (dir.isRelative())
641 dir.setPath(currentPath + QLatin1Char(
'/') + path);
642 if ((flags & Validate) && !QFileInfo::exists(dir.path()))
643 configVar.m_location.warning(QStringLiteral(
"Cannot find file or directory: %1").arg(path));
645 const QString canonicalPath = dir.canonicalPath();
646 if (!canonicalPath.isEmpty())
647 result.append(prefix + canonicalPath);
648 else if (path.contains(QLatin1Char(
'*')) || path.contains(QLatin1Char(
'?')))
652 qUtf8Printable(QStringLiteral(
"%1: Ignored nonexistent path \'%2\'")
653 .arg(configVar.m_location.toString(), rawValue));
660
661
662
663
664
665
666
670 const auto subRegExps = getRegExpList(var);
672 for (
const auto ®Exp : subRegExps) {
673 if (!regExp.isValid())
675 if (!pattern.isEmpty())
676 pattern += QLatin1Char(
'|');
677 pattern += QLatin1String(
"(?:") + regExp.pattern() + QLatin1Char(
')');
679 if (pattern.isEmpty())
680 pattern = QLatin1String(
"$x");
681 return QRegularExpression(pattern);
685
686
687
688
691 const QStringList strs = m_configVars.value(var).asStringList();
692 QList<QRegularExpression> regExps;
693 for (
const auto &str : strs)
694 regExps += QRegularExpression(str);
699
700
701
702
703
706 QSet<QString> result;
707 QString varDot = var + QLatin1Char(
'.');
708 for (
auto it = m_configVars.constBegin(); it != m_configVars.constEnd(); ++it) {
709 if (it.key().startsWith(varDot)) {
710 QString subVar = it.key().mid(varDot.size());
711 int dot = subVar.indexOf(QLatin1Char(
'.'));
713 subVar.truncate(dot);
714 result.insert(subVar);
721
722
723
724
727 QString ext = QFileInfo(fileName).suffix();
729 if (!m_includeFilesMap.contains(ext)) {
731 result.erase(std::remove_if(result.begin(), result.end(),
732 [&](
const QString &s) {
return !s.endsWith(ext); }),
734 const QStringList dirs =
738 for (
const auto &dir : dirs)
739 result += getFilesHere(dir,
"*." + ext, location());
740 result.removeDuplicates();
741 m_includeFilesMap.insert(ext, result);
743 const QStringList &paths = (*m_includeFilesMap.find(ext));
744 QString match = fileName;
745 if (!match.startsWith(
'/'))
747 for (
const auto &path : paths) {
748 if (path.endsWith(match))
755
756
757
758
759
760
761
762
764 const QSet<QString> &excludedDirs,
765 const QSet<QString> &excludedFiles)
767 QStringList result = getCanonicalPathList(filesVar, Validate);
768 const QStringList dirs = getCanonicalPathList(dirsVar, Validate);
772 for (
const auto &dir : dirs)
773 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
778 const QSet<QString> &excludedFiles)
781 const QStringList dirs = getCanonicalPathList(
"exampledirs");
782 const QString nameFilter =
" *.qdoc";
784 for (
const auto &dir : dirs)
785 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
790 const QSet<QString> &excludedFiles)
793 const QStringList dirs = getCanonicalPathList(
"exampledirs");
796 for (
const auto &dir : dirs)
797 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
809
810
811
814 QFileInfo fileInfo(examplePath);
815 QStringList validNames;
816 validNames << QLatin1String(
"CMakeLists.txt")
817 << fileInfo.fileName() + QLatin1String(
".pro")
818 << fileInfo.fileName() + QLatin1String(
".qmlproject")
819 << fileInfo.fileName() + QLatin1String(
".pyproject")
820 << QLatin1String(
"qbuild.pro");
824 for (
const auto &name : std::as_const(validNames)) {
825 projectFile = Config::findFile(Location(), m_exampleFiles, m_exampleDirs,
826 examplePath + QLatin1Char(
'/') + name);
827 if (!projectFile.isEmpty())
853
854
855
856
857
858
859
860
862 const QStringList &dirs,
const QString &fileName,
863 QString *userFriendlyFilePath)
865 if (fileName.isEmpty() || fileName.startsWith(QLatin1Char(
'/'))) {
866 if (userFriendlyFilePath)
867 *userFriendlyFilePath = fileName;
872 QStringList components = fileName.split(QLatin1Char(
'?'));
873 QString firstComponent = components.first();
875 for (
const auto &file : files) {
876 if (file == firstComponent || file.endsWith(QLatin1Char(
'/') + firstComponent)) {
877 fileInfo.setFile(file);
878 if (!fileInfo.exists())
879 location.fatal(QStringLiteral(
"File '%1' does not exist").arg(file));
884 if (fileInfo.fileName().isEmpty()) {
885 for (
const auto &dir : dirs) {
886 fileInfo.setFile(QDir(dir), firstComponent);
887 if (fileInfo.exists())
892 if (userFriendlyFilePath)
893 userFriendlyFilePath->clear();
894 if (!fileInfo.exists())
904 if (userFriendlyFilePath) {
905 for (
auto c = components.constBegin();;) {
906 bool isArchive = (c != components.constEnd() - 1);
907 userFriendlyFilePath->append(*c);
910 QString extracted = m_extractedDirs[fileInfo.filePath()];
913 fileInfo.setFile(QDir(extracted), *c);
918 userFriendlyFilePath->append(QLatin1Char(
'?'));
923 return fileInfo.filePath();
939
940
941
942
943
944
946 const QString &userFriendlySourceFilePath,
const QString &targetDirPath)
957 QFile inFile(sourceFilePath);
958 if (!inFile.open(QFile::ReadOnly)) {
959 location.warning(QStringLiteral(
"Cannot open input file for copy: '%1': %2")
960 .arg(sourceFilePath, inFile.errorString()));
998 QString outFileName{userFriendlySourceFilePath};
999 QFileInfo outFileNameInfo{userFriendlySourceFilePath};
1000 if (outFileNameInfo.isAbsolute())
1001 outFileName = outFileNameInfo.fileName();
1003 outFileName = targetDirPath +
"/" + outFileName;
1004 QDir targetDir(targetDirPath);
1005 if (!targetDir.exists())
1006 targetDir.mkpath(
".");
1008 QFile outFile(outFileName);
1009 if (!outFile.open(QFile::WriteOnly)) {
1011 location.warning(QStringLiteral(
"Cannot open output file for copy: '%1': %2")
1012 .arg(outFileName, outFile.errorString()));
1024 while ((len = inFile.read(buffer,
sizeof(buffer))) > 0)
1025 outFile.write(buffer, len);
1030
1031
1032
1036 for (
int i = 0; i != value.size(); ++i) {
1037 uint c = value[i].unicode();
1039 max = qMax(max,
static_cast<
int>(c));
1045
1046
1047
1048bool Config::isMetaKeyChar(QChar ch)
1050 return ch.isLetterOrNumber() || ch == QLatin1Char(
'_') || ch == QLatin1Char(
'.')
1051 || ch == QLatin1Char(
'{') || ch == QLatin1Char(
'}') || ch == QLatin1Char(
',');
1055
1056
1057
1058QStringList
Config::loadMaster(
const QString &fileName)
1061 QFile fin(fileName);
1062 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1063 if (!Config::installDir.isEmpty()) {
1064 qsizetype prefix = location.filePath().size() - location.fileName().size();
1065 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1066 + fileName.right(fileName.size() - prefix));
1068 if (!fin.open(QFile::ReadOnly | QFile::Text))
1069 location.fatal(QStringLiteral(
"Cannot open master qdocconf file '%1': %2")
1070 .arg(fileName, fin.errorString()));
1072 QTextStream stream(&fin);
1073 QStringList qdocFiles;
1074 QDir configDir(QFileInfo(fileName).canonicalPath());
1075 QString line = stream.readLine();
1076 while (!line.isNull()) {
1077 if (!line.isEmpty())
1078 qdocFiles.append(QFileInfo(configDir, line).filePath());
1079 line = stream.readLine();
1086
1087
1088
1089
1090
1093 QFileInfo fileInfo(fileName);
1094 pushWorkingDir(fileInfo.canonicalPath());
1095 static const QRegularExpression keySyntax(QRegularExpression::anchoredPattern(QLatin1String(
"\\w+(?:\\.\\w+)*")));
1099 location.advance(c);
1105#define SKIP_SPACES()
1106 while (c.isSpace() && cc != '\n')
1114 location.fatal(QStringLiteral(
"Too many nested includes"));
1116 QFile fin(fileInfo.fileName());
1117 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1118 if (!Config::installDir.isEmpty()) {
1119 qsizetype prefix = location.filePath().size() - location.fileName().size();
1120 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1121 + fileName.right(fileName.size() - prefix));
1123 if (!fin.open(QFile::ReadOnly | QFile::Text))
1125 QStringLiteral(
"Cannot open file '%1': %2").arg(fileName, fin.errorString()));
1128 QTextStream stream(&fin);
1129 QString text = stream.readAll();
1130 text += QLatin1String(
"\n\n");
1131 text += QLatin1Char(
'\0');
1134 location.push(fileName);
1138 QChar c = text.at(0);
1139 uint cc = c.unicode();
1140 while (i < text.size()) {
1143 }
else if (c.isSpace()) {
1145 }
else if (cc ==
'#') {
1148 }
while (cc !=
'\n');
1149 }
else if (isMetaKeyChar(c)) {
1152 QStringList rhsValues;
1153 QList<ExpandVar> expandVars;
1155 bool inQuote =
false;
1156 bool needsExpansion =
false;
1160 stack.process(c, location);
1162 }
while (isMetaKeyChar(c));
1164 const QStringList keys = stack.getExpanded(location);
1167 if (keys.size() == 1 && keys.first() == QLatin1String(
"include")) {
1168 QString includeFile;
1171 location.fatal(QStringLiteral(
"Bad include syntax"));
1175 while (!c.isSpace() && cc !=
'#' && cc !=
')') {
1180 while (c.isLetterOrNumber() || cc ==
'_') {
1184 if (!var.isEmpty()) {
1185 const QByteArray val = qgetenv(var.toLatin1().data());
1187 location.fatal(QStringLiteral(
"Environment variable '%1' undefined")
1190 includeFile += QString::fromLatin1(val);
1200 location.fatal(QStringLiteral(
"Bad include syntax"));
1203 if (cc !=
'#' && cc !=
'\n')
1204 location.fatal(QStringLiteral(
"Trailing garbage"));
1207
1208
1209 load(location, QFileInfo(QDir(m_workingDirs.top()), includeFile).filePath());
1212
1213
1214
1220 location.fatal(QStringLiteral(
"Expected '=' or '+=' after key"));
1226 qsizetype metaCharPos;
1231 }
else if (cc >
'0' && cc <
'8') {
1232 word += QChar(c.digitValue());
1234 }
else if ((metaCharPos = QString::fromLatin1(
"abfnrtv").indexOf(c))
1236 word += QLatin1Char(
"\a\b\f\n\r\t\v"[metaCharPos]);
1241 }
else if (c.isSpace() || cc ==
'#') {
1244 location.fatal(QStringLiteral(
"Unterminated string"));
1247 if (!word.isEmpty() || needsExpansion) {
1250 needsExpansion =
false;
1252 if (cc ==
'\n' || cc ==
'#')
1256 }
else if (cc ==
'"') {
1258 if (!word.isEmpty() || needsExpansion)
1261 needsExpansion =
false;
1265 }
else if (cc ==
'$') {
1268 bool braces =
false;
1274 while (c.isLetterOrNumber() || cc ==
'_') {
1286 else if (delim ==
'}')
1289 location.fatal(QStringLiteral(
"Missing '}'"));
1291 if (!var.isEmpty()) {
1292 const QByteArray val = qgetenv(var.toLatin1().constData());
1294 expandVars <<
ExpandVar(rhsValues.size(), word.size(), var, delim);
1295 needsExpansion =
true;
1296 }
else if (braces) {
1297 text.insert(i, QString::fromLatin1(val));
1301 word += QString::fromLatin1(val);
1305 if (!inQuote && cc ==
'=')
1306 location.fatal(QStringLiteral(
"Unexpected '='"));
1310 for (
const auto &key : keys) {
1311 if (!keySyntax.match(key).hasMatch())
1312 keyLoc.fatal(QStringLiteral(
"Invalid key '%1'").arg(key));
1314 ConfigVar configVar(key, rhsValues, QDir::currentPath(), keyLoc, expandVars);
1315 if (plus && m_configVars.contains(key)) {
1316 m_configVars[key].append(configVar);
1318 m_configVars.insert(key, configVar);
1323 location.fatal(QStringLiteral(
"Unexpected character '%1' at beginning of line").arg(c));
1333bool Config::isFileExcluded(
const QString &fileName,
const QSet<QString> &excludedFiles)
1335 for (
const QString &entry : excludedFiles) {
1336 if (entry.contains(QLatin1Char(
'*')) || entry.contains(QLatin1Char(
'?'))) {
1337 QRegularExpression re(QRegularExpression::wildcardToRegularExpression(entry));
1338 if (re.match(fileName).hasMatch())
1342 return excludedFiles.contains(fileName);
1345QStringList
Config::getFilesHere(
const QString &uncleanDir,
const QString &nameFilter,
1346 const Location &location,
const QSet<QString> &excludedDirs,
1347 const QSet<QString> &excludedFiles)
1352 location.isEmpty() ? QDir::cleanPath(uncleanDir) : QDir(uncleanDir).canonicalPath();
1354 if (excludedDirs.contains(dir))
1359 dirInfo.setNameFilters(nameFilter.split(QLatin1Char(
' ')));
1360 dirInfo.setSorting(QDir::Name);
1361 dirInfo.setFilter(QDir::Files);
1362 QStringList fileNames = dirInfo.entryList();
1363 for (
const auto &file : std::as_const(fileNames)) {
1366 if (!file.startsWith(QLatin1Char(
'~'))) {
1367 QString s = dirInfo.filePath(file);
1368 QString c = QDir::cleanPath(s);
1369 if (!isFileExcluded(c, excludedFiles))
1374 dirInfo.setNameFilters(QStringList(QLatin1String(
"*")));
1375 dirInfo.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
1376 fileNames = dirInfo.entryList();
1377 for (
const auto &file : fileNames)
1378 result += getFilesHere(dirInfo.filePath(file), nameFilter, location, excludedDirs,
1384
1385
1386
1387void Config::pushWorkingDir(
const QString &dir)
1389 m_workingDirs.push(dir);
1390 QDir::setCurrent(dir);
1394
1395
1396
1397
1400 Q_ASSERT(!m_workingDirs.isEmpty());
1401 m_workingDirs.pop();
1402 if (!m_workingDirs.isEmpty())
1403 QDir::setCurrent(m_workingDirs.top());
1407 if (m_excludedPaths)
1408 return *m_excludedPaths;
1413 QSet<QString> excludedDirs = QSet<QString>(excludedDirList.cbegin(), excludedDirList.cend());
1414 QSet<QString> excludedFiles = QSet<QString>(excludedFilesList.cbegin(), excludedFilesList.cend());
1416 m_excludedPaths.emplace(ExcludedPaths{excludedDirs, excludedFiles});
1418 return *m_excludedPaths;
1422 static QStringList accepted_header_file_extensions{
1423 "ch",
"h",
"h++",
"hh",
"hpp",
"hxx"
1428 QStringList headerList =
1431 std::set<HeaderFilePath> headers{};
1433 for (
const auto& header : headerList) {
1434 if (header.contains(
"doc/snippets"))
continue;
1436 if (!accepted_header_file_extensions.contains(QFileInfo{header}.suffix()))
1439 headers.insert(HeaderFilePath{QFileInfo{header}.canonicalPath(), QFileInfo{header}.fileName()});
contains all the information for a single config variable in a .qdocconf file.
QString asString(const QString defaultString=QString()) const
Returns this configuration variable as a string.
QStringList asStringList() const
Returns this config variable as a string list.
int asInt() const
Returns this configuration variable as an integer; iterates through the string list,...
bool asBool() const
Returns this config variable as a boolean.
QSet< QString > asStringSet() const
Returns this config variable as a string set.
The Config class contains the configuration variables for controlling how qdoc produces documentation...
static QString installDir
QString getOutputDir(const QString &format=QString("HTML")) const
Function to return the correct outputdir for the output format.
std::set< HeaderFilePath > getHeaderFiles()
static bool generateExamples
void insertStringList(const QString &var, const QStringList &values)
Adds the values from a string list to the configuration variable var.
QStringList getAllFiles(const QString &filesVar, const QString &dirsVar, const QSet< QString > &excludedDirs=QSet< QString >(), const QSet< QString > &excludedFiles=QSet< QString >())
Builds and returns a list of file pathnames for the file type specified by filesVar (e....
void reset()
Resets the Config instance - used by load()
void setStringList(const QString &var, const QStringList &values)
Sets the values of a configuration variable var from a string list.
void clear()
Clears the location and internal maps for config variables.
QSet< QString > subVars(const QString &var) const
This function is slower than it could be.
PathFlags
Flags used for retrieving canonicalized paths from Config.
const ExcludedPaths & getExcludedPaths()
QSet< QString > getOutputFormats() const
Function to return the correct outputformats.
static void popWorkingDir()
Pop the top entry from the stack of working directories.
QRegularExpression getRegExp(const QString &var) const
Calls getRegExpList() with the control variable var and iterates through the resulting list of regula...
QString getExampleProjectFile(const QString &examplePath)
Returns the path to the project file for examplePath, or an empty string if no project file was found...
static QSet< QString > overrideOutputFormats
static QString overrideOutputDir
QStringList getCanonicalPathList(const QString &var, PathFlags flags=None) const
Returns a path list where all paths from the config variable var are canonicalized.
void load(const QString &fileName)
Loads and parses the qdoc configuration file fileName.
QList< QRegularExpression > getRegExpList(const QString &var) const
Looks up the configuration variable var in the string list map, converts the string list to a list of...
QStringList getExampleImageFiles(const QSet< QString > &excludedDirs, const QSet< QString > &excludedFiles)
QStringList getExampleQdocFiles(const QSet< QString > &excludedDirs, const QSet< QString > &excludedFiles)
void init(const QString &programName, const QStringList &args)
Initializes the Config with programName and sets all internal state variables to either default value...
QString getIncludeFilePath(const QString &fileName) const
Searches for a path to fileName in 'sources', 'sourcedirs', and 'exampledirs' config variables and re...
The Location class provides a way to mark a location in a file.
void start()
If the file position on top of the stack has a line number less than 1, set its line number to 1 and ...
An entry in a stack, where each entry is a list of string values.
void close()
Stop accumulating values and append the list of accumulated values to the complete list of accumulate...
void open()
Start accumulating values in a list by appending an empty string to the list.
Q_DECLARE_TYPEINFO(MetaStackEntry, Q_RELOCATABLE_TYPE)
#define CONFIG_REDIRECTDOCUMENTATIONTODEVNULL
#define CONFIG_FILEEXTENSIONS
#define CONFIG_AUTOLINKERRORS
#define CONFIG_SHOWINTERNAL
#define CONFIG_DOCBOOKEXTENSIONS
#define CONFIG_SINGLEEXEC
#define CONFIG_FALSEHOODS
#define CONFIG_EXAMPLEDIRS
#define CONFIG_WARNABOUTMISSINGPROJECTFILES
#define CONFIG_SYNTAXHIGHLIGHTING
#define CONFIG_TIMESTAMPS
#define CONFIG_NOLINKERRORS
#define CONFIG_LOGPROGRESS
#define CONFIG_SOURCEDIRS
#define CONFIG_CODEINDENT
#define CONFIG_WARNABOUTMISSINGIMAGES
#define CONFIG_OUTPUTFORMATS
#define CONFIG_LOCATIONINFO
#define CONFIG_IMAGEEXTENSIONS
#define CONFIG_EXCLUDEFILES
#define CONFIG_EXCLUDEDIRS
#define CONFIG_HEADERDIRS
#define CONFIG_INCLUDEPATHS
Combined button and popup list for selecting options.
static QString HEADERSTYLES
static QString IGNORESINCE
static QString CODESUFFIX
static QString EXAMPLEDIRS
static QString CODEINDENT
static QString HEADERDIRS
static QString NATURALLANGUAGE
static QString WARNABOUTMISSINGPROJECTFILES
static QString SINGLEEXEC
static QString SOURCEDIRS
static QString IGNOREDIRECTIVES
static QString EXCLUDEDIRS
static QString FILEEXTENSIONS
static QString OUTPUTFORMATS
static QString REDIRECTDOCUMENTATIONTODEVNULL
static QString LANDINGPAGE
static QString MODULEHEADER
static QString CPPCLASSESPAGE
static QString PRODUCTNAME
static QString BUILDVERSION
static QString DOCBOOKEXTENSIONS
static QString VERSIONSYM
static QString IMAGEEXTENSIONS
static QString EXAMPLESINSTALLPATH
static QString HEADERSCRIPTS
static QString SOURCEENCODING
static QString IGNORETOKENS
static QString NAVIGATION
static QString SYNTAXHIGHLIGHTING
static QString IGNOREWORDS
static QString INCLUDEPATHS
static QString WARNINGLIMIT
static QString STYLESHEETS
static QString LANDINGTITLE
static QString CODEPREFIX
static QString LOGPROGRESS
static QString FALSEHOODS
static QString TRADEMARKSPAGE
static QString QMLTYPESPAGE
static QString EXCLUDEFILES
static QString EXTRAIMAGES
static QString NOLINKERRORS
static QString LOCATIONINFO
static QString TIMESTAMPS
static QString WARNABOUTMISSINGIMAGES
static QString DOCUMENTATIONINHEADERS
static QString SHOWINTERNAL
static QString CPPCLASSESTITLE
static QString QUOTINGINFORMATION
static QString FORMATTING
static QString MANIFESTMETA
static QString OUTPUTPREFIXES
static QString DESCRIPTION
static QString OUTPUTSUFFIXES
static QString QMLTYPESTITLE