8#include <QtCore/qdir.h>
9#include <QtCore/qfile.h>
10#include <QtCore/qtemporaryfile.h>
11#include <QtCore/qtextstream.h>
12#include <QtCore/qvariant.h>
13#include <QtCore/qregularexpression.h>
17QString ConfigStrings::AUTOLINKERRORS = QStringLiteral(
"autolinkerrors");
74 QStringLiteral(
"redirectdocumentationtodevnull");
76 QStringLiteral(
"reportmissingalttextforimages");
107
108
109
122
123
124
127 next.append(QString());
131
132
133
134
142
143
144
145
156
157
158
166
167
168
169
172 if (ch == QLatin1Char(
'{')) {
175 }
else if (ch == QLatin1Char(
'}')) {
177 location.fatal(QStringLiteral(
"Unexpected '}'"));
180 const QStringList suffixes = pop().accum;
181 const QStringList prefixes = top().next;
184 for (
const auto &prefix : prefixes) {
185 for (
const auto &suffix : suffixes)
186 top().next << prefix + suffix;
188 }
else if (ch == QLatin1Char(
',') && size() > 1) {
192 for (QString &topNext : top().next)
198
199
203 location.fatal(QStringLiteral(
"Missing '}'"));
210bool Config::m_debug =
false;
211bool Config::m_atomsDump =
false;
216QMap<QString, QString>
Config::m_extractedDirs;
217QStack<QString>
Config::m_workingDirs;
218QMap<QString, QStringList>
Config::m_includeFilesMap;
221
222
223
224
227
228
229
230
231
232
233
234
235
238 if (m_name.isEmpty())
239 return defaultString;
242 for (
const auto &value : std::as_const(m_values)) {
243 if (!result.isEmpty() && !result.endsWith(QChar(
'\n')))
244 result.append(QChar(
' '));
245 result.append(value.m_value);
251
252
256 for (
const auto &value : std::as_const(m_values))
257 result << value.m_value;
262
263
266 const auto &stringList = asStringList();
267 return QSet<QString>(stringList.cbegin(), stringList.cend());
271
272
275 return QVariant(asString()).toBool();
279
280
281
282
283
284
285
288 const QStringList strs = asStringList();
293 for (
const auto &str : strs)
299
300
301
304 m_expandVars << other.m_expandVars;
305 QList<ExpandVar>::Iterator it = m_expandVars.end();
306 it -= other.m_expandVars.size();
307 std::for_each(it, m_expandVars.end(), [
this](ExpandVar &v) {
308 v.m_valueIndex += m_values.size();
310 m_values << other.m_values;
311 m_location = other.m_location;
315
316
317
318
319
320
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
342
343
344
345
346void Config::
init(
const QString &programName,
const QStringList &args)
348 m_prog = programName;
349 processCommandLineOptions(args);
359
360
363 m_location = Location();
364 m_configVars.clear();
365 m_includeFilesMap.clear();
366 m_excludedPaths.reset();
367 m_sourceLink.reset();
371
372
391 const auto setListFlag = [
this](
const QString &key,
bool test) {
392 setStringList(key, QStringList(test ? QStringLiteral(
"true") : QStringLiteral(
"false")));
394#define SET(opt, test) setListFlag(opt, m_parser.isSet(m_parser.test))
403 m_parser.isSet(m_parser.noLinkErrorsOption)
404 || qEnvironmentVariableIsSet(
"QDOC_NOLINKERRORS"));
410
411
412
413
414
421 load(Location(), fileName);
422 if (m_location.isEmpty())
423 m_location = Location(fileName);
425 m_location.setEtc(
true);
429 setStringList(varName, getCanonicalPathList(varName, Validate));
442 m_reportMissingAltTextForImages =
445 if (!m_parser.isSet(m_parser.showInternalOption) && !qEnvironmentVariableIsSet(
"QDOC_SHOW_INTERNAL"))
450
451
452void Config::expandVariables()
454 for (
auto &configVar : m_configVars) {
455 for (
auto it = configVar.m_expandVars.crbegin(); it != configVar.m_expandVars.crend(); ++it) {
456 Q_ASSERT(it->m_valueIndex < configVar.m_values.size());
457 const QString &key = it->m_var;
458 const auto &refVar = m_configVars.value(key);
459 if (refVar.m_name.isEmpty()) {
460 configVar.m_location.fatal(
461 QStringLiteral(
"Environment or configuration variable '%1' undefined")
463 }
else if (!refVar.m_expandVars.empty()) {
464 configVar.m_location.fatal(
465 QStringLiteral(
"Nested variable expansion not allowed"),
466 QStringLiteral(
"When expanding '%1' at %2:%3")
467 .arg(refVar.m_name, refVar.m_location.filePath(),
468 QString::number(refVar.m_location.lineNo())));
471 if (it->m_delim.isNull())
472 expanded = m_configVars.value(key).asStringList().join(QString());
474 expanded = m_configVars.value(key).asStringList().join(it->m_delim);
475 configVar.m_values[it->m_valueIndex].m_value.insert(it->m_index, expanded);
477 configVar.m_expandVars.clear();
482
483
486 m_configVars.insert(var, ConfigVar(var, values, QDir::currentPath()));
490
491
492
495 m_configVars[var].append(ConfigVar(var, values, QDir::currentPath()));
499
500
501void Config::processCommandLineOptions(
const QStringList &args)
503 m_parser.process(args);
505 m_defines = m_parser.values(m_parser.defineOption);
506 m_dependModules = m_parser.values(m_parser.dependsOption);
510 generateExamples = !m_parser.isSet(m_parser.noExamplesOption);
511 if (m_parser.isSet(m_parser.installDirOption))
512 installDir = m_parser.value(m_parser.installDirOption);
513 if (m_parser.isSet(m_parser.outputDirOption))
514 overrideOutputDir = QDir(m_parser.value(m_parser.outputDirOption)).absolutePath();
516 const auto outputFormats = m_parser.values(m_parser.outputFormatOption);
517 for (
const auto &format : outputFormats)
518 overrideOutputFormats.insert(format);
519 m_debug = m_parser.isSet(m_parser.debugOption) || qEnvironmentVariableIsSet(
"QDOC_DEBUG");
520 m_atomsDump = m_parser.isSet(m_parser.atomsDumpOption);
521 m_showInternal = m_parser.isSet(m_parser.showInternalOption)
522 || qEnvironmentVariableIsSet(
"QDOC_SHOW_INTERNAL");
524 if (m_parser.isSet(m_parser.prepareOption))
526 if (m_parser.isSet(m_parser.generateOption))
528 if (m_debug || m_parser.isSet(m_parser.logProgressOption))
530 if (m_parser.isSet(m_parser.timestampsOption))
532 if (m_parser.isSet(m_parser.useDocBookExtensions))
536void Config::setIncludePaths()
538 QDir currentDir = QDir::current();
539 const auto addIncludePaths = [
this, currentDir](
const char *flag,
const QStringList &paths) {
540 for (
const auto &path : paths)
541 m_includePaths << currentDir.absoluteFilePath(path).insert(0, flag);
544 addIncludePaths(
"-I", m_parser.values(m_parser.includePathOption));
545#ifdef QDOC_PASS_ISYSTEM
546 addIncludePaths(
"-isystem", m_parser.values(m_parser.includePathSystemOption));
548 addIncludePaths(
"-F", m_parser.values(m_parser.frameworkOption));
552
553
554void Config::setIndexDirs()
556 m_indexDirs = m_parser.values(m_parser.indexDirOption);
557 auto it = std::remove_if(m_indexDirs.begin(), m_indexDirs.end(),
558 [](
const QString &s) {
return !QFile::exists(s); });
560 std::for_each(it, m_indexDirs.end(), [](
const QString &s) {
561 qCWarning(lcQdoc) <<
"Cannot find index directory: " << s;
563 m_indexDirs.erase(it, m_indexDirs.end());
567
568
569
570
571
575 if (overrideOutputDir.isNull())
578 t = overrideOutputDir;
581 t += QLatin1Char(
'/') + project.toLower();
583 if (m_configVars.value(format + Config::dot +
"nosubdirs").asBool()) {
584 QString singleOutputSubdir = m_configVars.value(format + Config::dot +
"outputsubdir").asString();
585 if (singleOutputSubdir.isEmpty())
586 singleOutputSubdir =
"html";
587 t += QLatin1Char(
'/') + singleOutputSubdir;
589 return QDir::cleanPath(t);
593
594
595
596
599 if (overrideOutputFormats.isEmpty())
602 return overrideOutputFormats;
620
621
622
623
624
625
629 const auto &configVar = m_configVars.value(var);
631 for (
const auto &value : configVar.m_values) {
632 const QString ¤tPath = value.m_path;
633 QString rawValue = value.m_value.simplified();
636 if (flags & IncludePaths) {
637 const QStringList prefixes = QStringList()
638 << QLatin1String(
"-I")
639 << QLatin1String(
"-F")
640 << QLatin1String(
"-isystem");
641 const auto end = std::end(prefixes);
643 std::find_if(std::begin(prefixes), end,
644 [&rawValue](
const QString &p) {
645 return rawValue.startsWith(p);
649 rawValue.remove(0, it->size());
650 if (rawValue.isEmpty())
653 prefix = prefixes[0];
657 QDir dir(rawValue.trimmed());
658 const QString path = dir.path();
660 if (dir.isRelative())
661 dir.setPath(currentPath + QLatin1Char(
'/') + path);
662 if ((flags & Validate) && !QFileInfo::exists(dir.path()))
663 configVar.m_location.warning(QStringLiteral(
"Cannot find file or directory: %1").arg(path));
665 const QString canonicalPath = dir.canonicalPath();
666 if (!canonicalPath.isEmpty())
667 result.append(prefix + canonicalPath);
668 else if (path.contains(QLatin1Char(
'*')) || path.contains(QLatin1Char(
'?')))
672 qUtf8Printable(QStringLiteral(
"%1: Ignored nonexistent path \'%2\'")
673 .arg(configVar.m_location.toString(), rawValue));
680
681
682
683
684
685
686
690 const auto subRegExps = getRegExpList(var);
692 for (
const auto ®Exp : subRegExps) {
693 if (!regExp.isValid())
695 if (!pattern.isEmpty())
696 pattern += QLatin1Char(
'|');
697 pattern += QLatin1String(
"(?:") + regExp.pattern() + QLatin1Char(
')');
699 if (pattern.isEmpty())
700 pattern = QLatin1String(
"$x");
701 return QRegularExpression(pattern);
705
706
707
708
711 const QStringList strs = m_configVars.value(var).asStringList();
712 QList<QRegularExpression> regExps;
713 for (
const auto &str : strs)
714 regExps += QRegularExpression(str);
719
720
721
722
723
726 QSet<QString> result;
727 QString varDot = var + QLatin1Char(
'.');
728 for (
auto it = m_configVars.constBegin(); it != m_configVars.constEnd(); ++it) {
729 if (it.key().startsWith(varDot)) {
730 QString subVar = it.key().mid(varDot.size());
731 int dot = subVar.indexOf(QLatin1Char(
'.'));
733 subVar.truncate(dot);
734 result.insert(subVar);
741
742
743
744
747 QString ext = QFileInfo(fileName).suffix();
749 if (!m_includeFilesMap.contains(ext)) {
751 result.erase(std::remove_if(result.begin(), result.end(),
752 [&](
const QString &s) {
return !s.endsWith(ext); }),
754 const QStringList dirs =
758 for (
const auto &dir : dirs)
759 result += getFilesHere(dir,
"*." + ext, location());
760 result.removeDuplicates();
761 m_includeFilesMap.insert(ext, result);
763 const QStringList &paths = (*m_includeFilesMap.find(ext));
764 QString match = fileName;
765 if (!match.startsWith(
'/'))
767 for (
const auto &path : paths) {
768 if (path.endsWith(match))
775
776
777
778
779
780
781
782
784 const QSet<QString> &excludedDirs,
785 const QSet<QString> &excludedFiles)
787 QStringList result = getCanonicalPathList(filesVar, Validate);
788 const QStringList dirs = getCanonicalPathList(dirsVar, Validate);
792 for (
const auto &dir : dirs)
793 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
798 const QSet<QString> &excludedFiles)
801 const QStringList dirs = getCanonicalPathList(
"exampledirs");
802 const QString nameFilter =
" *.qdoc";
804 for (
const auto &dir : dirs)
805 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
810 const QSet<QString> &excludedFiles)
813 const QStringList dirs = getCanonicalPathList(
"exampledirs");
816 for (
const auto &dir : dirs)
817 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
829
830
831
834 QFileInfo fileInfo(examplePath);
835 QStringList validNames;
836 validNames << QLatin1String(
"CMakeLists.txt")
837 << fileInfo.fileName() + QLatin1String(
".pro")
838 << fileInfo.fileName() + QLatin1String(
".qmlproject")
839 << fileInfo.fileName() + QLatin1String(
".pyproject")
840 << QLatin1String(
"qbuild.pro");
844 for (
const auto &name : std::as_const(validNames)) {
845 projectFile = Config::findFile(Location(), m_exampleFiles, m_exampleDirs,
846 examplePath + QLatin1Char(
'/') + name);
847 if (!projectFile.isEmpty())
873
874
875
876
877
878
879
880
882 const QStringList &dirs,
const QString &fileName,
883 QString *userFriendlyFilePath)
885 if (fileName.isEmpty() || fileName.startsWith(QLatin1Char(
'/'))) {
886 if (userFriendlyFilePath)
887 *userFriendlyFilePath = fileName;
892 QStringList components = fileName.split(QLatin1Char(
'?'));
893 QString firstComponent = components.first();
895 for (
const auto &file : files) {
896 if (file == firstComponent || file.endsWith(QLatin1Char(
'/') + firstComponent)) {
897 fileInfo.setFile(file);
898 if (!fileInfo.exists())
899 location.fatal(QStringLiteral(
"File '%1' does not exist").arg(file));
904 if (fileInfo.fileName().isEmpty()) {
905 for (
const auto &dir : dirs) {
906 fileInfo.setFile(QDir(dir), firstComponent);
907 if (fileInfo.exists())
912 if (userFriendlyFilePath)
913 userFriendlyFilePath->clear();
914 if (!fileInfo.exists())
924 if (userFriendlyFilePath) {
925 for (
auto c = components.constBegin();;) {
926 bool isArchive = (c != components.constEnd() - 1);
927 userFriendlyFilePath->append(*c);
930 QString extracted = m_extractedDirs[fileInfo.filePath()];
933 fileInfo.setFile(QDir(extracted), *c);
938 userFriendlyFilePath->append(QLatin1Char(
'?'));
943 return fileInfo.filePath();
959
960
961
962
963
964
966 const QString &userFriendlySourceFilePath,
const QString &targetDirPath)
977 QFile inFile(sourceFilePath);
978 if (!inFile.open(QFile::ReadOnly)) {
979 location.warning(QStringLiteral(
"Cannot open input file for copy: '%1': %2")
980 .arg(sourceFilePath, inFile.errorString()));
1018 QString outFileName{userFriendlySourceFilePath};
1019 QFileInfo outFileNameInfo{userFriendlySourceFilePath};
1020 if (outFileNameInfo.isAbsolute())
1021 outFileName = outFileNameInfo.fileName();
1023 outFileName = targetDirPath +
"/" + outFileName;
1024 QDir targetDir(targetDirPath);
1025 if (!targetDir.exists())
1026 targetDir.mkpath(
".");
1028 QFile outFile(outFileName);
1029 if (!outFile.open(QFile::WriteOnly)) {
1031 location.warning(QStringLiteral(
"Cannot open output file for copy: '%1': %2")
1032 .arg(outFileName, outFile.errorString()));
1044 while ((len = inFile.read(buffer,
sizeof(buffer))) > 0)
1045 outFile.write(buffer, len);
1050
1051
1052
1056 for (
int i = 0; i != value.size(); ++i) {
1057 uint c = value[i].unicode();
1059 max = qMax(max,
static_cast<
int>(c));
1065
1066
1067
1068bool Config::isMetaKeyChar(QChar ch)
1070 return ch.isLetterOrNumber() || ch == QLatin1Char(
'_') || ch == QLatin1Char(
'.')
1071 || ch == QLatin1Char(
'{') || ch == QLatin1Char(
'}') || ch == QLatin1Char(
',');
1075
1076
1077
1078QStringList
Config::loadMaster(
const QString &fileName)
1081 QFile fin(fileName);
1082 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1083 if (!Config::installDir.isEmpty()) {
1084 qsizetype prefix = location.filePath().size() - location.fileName().size();
1085 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1086 + fileName.right(fileName.size() - prefix));
1088 if (!fin.open(QFile::ReadOnly | QFile::Text))
1089 location.fatal(QStringLiteral(
"Cannot open master qdocconf file '%1': %2")
1090 .arg(fileName, fin.errorString()));
1092 QTextStream stream(&fin);
1093 QStringList qdocFiles;
1094 QDir configDir(QFileInfo(fileName).canonicalPath());
1095 QString line = stream.readLine();
1096 while (!line.isNull()) {
1097 if (!line.isEmpty())
1098 qdocFiles.append(QFileInfo(configDir, line).filePath());
1099 line = stream.readLine();
1106
1107
1108
1109
1110
1113 QFileInfo fileInfo(fileName);
1114 pushWorkingDir(fileInfo.canonicalPath());
1115 static const QRegularExpression keySyntax(QRegularExpression::anchoredPattern(QLatin1String(
"\\w+(?:\\.\\w+)*")));
1119 location.advance(c);
1125#define SKIP_SPACES()
1126 while (c.isSpace() && cc != '\n')
1134 location.fatal(QStringLiteral(
"Too many nested includes"));
1136 QFile fin(fileInfo.fileName());
1137 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1138 if (!Config::installDir.isEmpty()) {
1139 qsizetype prefix = location.filePath().size() - location.fileName().size();
1140 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1141 + fileName.right(fileName.size() - prefix));
1143 if (!fin.open(QFile::ReadOnly | QFile::Text))
1145 QStringLiteral(
"Cannot open file '%1': %2").arg(fileName, fin.errorString()));
1148 QTextStream stream(&fin);
1149 QString text = stream.readAll();
1150 text += QLatin1String(
"\n\n");
1151 text += QLatin1Char(
'\0');
1154 location.push(fileName);
1158 QChar c = text.at(0);
1159 uint cc = c.unicode();
1160 while (i < text.size()) {
1163 }
else if (c.isSpace()) {
1165 }
else if (cc ==
'#') {
1168 }
while (cc !=
'\n');
1169 }
else if (isMetaKeyChar(c)) {
1172 QStringList rhsValues;
1173 QList<ExpandVar> expandVars;
1175 bool inQuote =
false;
1176 bool needsExpansion =
false;
1180 stack.process(c, location);
1182 }
while (isMetaKeyChar(c));
1184 const QStringList keys = stack.getExpanded(location);
1187 if (keys.size() == 1 && keys.first() == QLatin1String(
"include")) {
1188 QString includeFile;
1191 location.fatal(QStringLiteral(
"Bad include syntax"));
1195 while (!c.isSpace() && cc !=
'#' && cc !=
')') {
1200 while (c.isLetterOrNumber() || cc ==
'_') {
1204 if (!var.isEmpty()) {
1205 const QByteArray val = qgetenv(var.toLatin1().data());
1207 location.fatal(QStringLiteral(
"Environment variable '%1' undefined")
1210 includeFile += QString::fromLatin1(val);
1220 location.fatal(QStringLiteral(
"Bad include syntax"));
1223 if (cc !=
'#' && cc !=
'\n')
1224 location.fatal(QStringLiteral(
"Trailing garbage"));
1227
1228
1229 load(location, QFileInfo(QDir(m_workingDirs.top()), includeFile).filePath());
1232
1233
1234
1240 location.fatal(QStringLiteral(
"Expected '=' or '+=' after key"));
1246 qsizetype metaCharPos;
1251 }
else if (cc >
'0' && cc <
'8') {
1252 word += QChar(c.digitValue());
1254 }
else if ((metaCharPos = QString::fromLatin1(
"abfnrtv").indexOf(c))
1256 word += QLatin1Char(
"\a\b\f\n\r\t\v"[metaCharPos]);
1261 }
else if (c.isSpace() || cc ==
'#') {
1264 location.fatal(QStringLiteral(
"Unterminated string"));
1267 if (!word.isEmpty() || needsExpansion) {
1270 needsExpansion =
false;
1272 if (cc ==
'\n' || cc ==
'#')
1276 }
else if (cc ==
'"') {
1278 if (!word.isEmpty() || needsExpansion)
1281 needsExpansion =
false;
1285 }
else if (cc ==
'$') {
1288 bool braces =
false;
1294 while (c.isLetterOrNumber() || cc ==
'_') {
1306 else if (delim ==
'}')
1309 location.fatal(QStringLiteral(
"Missing '}'"));
1311 if (!var.isEmpty()) {
1312 const QByteArray val = qgetenv(var.toLatin1().constData());
1314 expandVars <<
ExpandVar(rhsValues.size(), word.size(),
std::move(var), delim);
1315 needsExpansion =
true;
1316 }
else if (braces) {
1317 text.insert(i, QString::fromLatin1(val));
1321 word += QString::fromLatin1(val);
1325 if (!inQuote && cc ==
'=')
1326 location.fatal(QStringLiteral(
"Unexpected '='"));
1330 for (
const auto &key : keys) {
1331 if (!keySyntax.match(key).hasMatch())
1332 keyLoc.fatal(QStringLiteral(
"Invalid key '%1'").arg(key));
1334 ConfigVar configVar(key, rhsValues, QDir::currentPath(), keyLoc, expandVars);
1335 if (plus && m_configVars.contains(key)) {
1336 m_configVars[key].append(configVar);
1338 m_configVars.insert(key, configVar);
1343 location.fatal(QStringLiteral(
"Unexpected character '%1' at beginning of line").arg(c));
1353bool Config::isFileExcluded(
const QString &fileName,
const QSet<QString> &excludedFiles)
1355 for (
const QString &entry : excludedFiles) {
1356 if (entry.contains(QLatin1Char(
'*')) || entry.contains(QLatin1Char(
'?'))) {
1357 QRegularExpression re(QRegularExpression::wildcardToRegularExpression(entry));
1358 if (re.match(fileName).hasMatch())
1362 return excludedFiles.contains(fileName);
1365QStringList
Config::getFilesHere(
const QString &uncleanDir,
const QString &nameFilter,
1366 const Location &location,
const QSet<QString> &excludedDirs,
1367 const QSet<QString> &excludedFiles)
1372 location.isEmpty() ? QDir::cleanPath(uncleanDir) : QDir(uncleanDir).canonicalPath();
1374 if (excludedDirs.contains(dir))
1379 dirInfo.setNameFilters(nameFilter.split(QLatin1Char(
' ')));
1380 dirInfo.setSorting(QDir::Name);
1381 dirInfo.setFilter(QDir::Files);
1382 QStringList fileNames = dirInfo.entryList();
1383 for (
const auto &file : std::as_const(fileNames)) {
1386 if (!file.startsWith(QLatin1Char(
'~'))) {
1387 QString s = dirInfo.filePath(file);
1388 QString c = QDir::cleanPath(s);
1389 if (!isFileExcluded(c, excludedFiles))
1394 dirInfo.setNameFilters(QStringList(QLatin1String(
"*")));
1395 dirInfo.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
1396 fileNames = dirInfo.entryList();
1397 for (
const auto &file : fileNames)
1398 result += getFilesHere(dirInfo.filePath(file), nameFilter, location, excludedDirs,
1404
1405
1406
1407void Config::pushWorkingDir(
const QString &dir)
1409 m_workingDirs.push(dir);
1410 QDir::setCurrent(dir);
1414
1415
1416
1417
1420 Q_ASSERT(!m_workingDirs.isEmpty());
1421 m_workingDirs.pop();
1422 if (!m_workingDirs.isEmpty())
1423 QDir::setCurrent(m_workingDirs.top());
1427 if (m_excludedPaths)
1428 return *m_excludedPaths;
1433 QSet<QString> excludedDirs = QSet<QString>(excludedDirList.cbegin(), excludedDirList.cend());
1434 QSet<QString> excludedFiles = QSet<QString>(excludedFilesList.cbegin(), excludedFilesList.cend());
1436 m_excludedPaths.emplace(ExcludedPaths{std::move(excludedDirs), std::move(excludedFiles)});
1438 return *m_excludedPaths;
1442
1443
1444
1448 return *m_sourceLink;
1452 const auto baseUrl = m_configVars.value(srcUrl).asString();
1453 const auto rootPath = m_configVars.value(srcUrl + dot +
CONFIG_ROOTDIR).asString();
1454 const auto linkText = m_configVars.value(srcUrl + dot +
"linktext").asString();
1455 const auto enabled = m_configVars.value(srcUrl + dot +
"enabled").asBool();
1457 m_sourceLink.emplace(SourceLink{baseUrl, rootPath, linkText, enabled});
1458 return *m_sourceLink;
1462 static QStringList accepted_header_file_extensions{
1463 "ch",
"h",
"h++",
"hh",
"hpp",
"hxx"
1468 QStringList headerList =
1471 std::set<HeaderFilePath> headers{};
1473 for (
const auto& header : headerList) {
1474 if (header.contains(
"doc/snippets"))
continue;
1476 if (!accepted_header_file_extensions.contains(QFileInfo{header}.suffix()))
1479 headers.insert(HeaderFilePath{QFileInfo{header}.canonicalPath(), QFileInfo{header}.fileName()});
1487 InclusionPolicy policy;
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()
InclusionPolicy createInclusionPolicy() const
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.
bool includePrivateType() const
PathFlags
Flags used for retrieving canonicalized paths from Config.
bool includePrivateVariable() const
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...
bool includePrivateFunction() const
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.
bool includePrivate() const
const SourceLink & getSourceLink()
Returns a SourceLink struct with settings required to construct source links to API entities.
bool showInternal() const
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_INCLUDEPRIVATE
#define CONFIG_OUTPUTFORMATS
#define CONFIG_LOCATIONINFO
#define CONFIG_IMAGEEXTENSIONS
#define CONFIG_EXCLUDEFILES
#define CONFIG_EXCLUDEDIRS
#define CONFIG_HEADERDIRS
#define CONFIG_REPORTMISSINGALTTEXTFORIMAGES
#define CONFIG_INCLUDEPATHS
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 LOGWARNINGSDISABLECLIARGS
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 INCLUDEPRIVATE
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 USEALTTEXTASTITLE
static QString CODEPREFIX
static QString LOGPROGRESS
static QString FALSEHOODS
static QString TRADEMARKSPAGE
static QString QMLTYPESPAGE
static QString LOGWARNINGS
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 REPORTMISSINGALTTEXTFORIMAGES
static QString OUTPUTSUFFIXES
static QString PROJECTROOT
static QString QMLTYPESTITLE