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");
68 QStringLiteral(
"redirectdocumentationtodevnull");
97
98
99
112
113
114
117 next.append(QString());
121
122
123
124
132
133
134
135
146
147
148
156
157
158
159
162 if (ch == QLatin1Char(
'{')) {
165 }
else if (ch == QLatin1Char(
'}')) {
167 location.fatal(QStringLiteral(
"Unexpected '}'"));
170 const QStringList suffixes = pop().accum;
171 const QStringList prefixes = top().next;
174 for (
const auto &prefix : prefixes) {
175 for (
const auto &suffix : suffixes)
176 top().next << prefix + suffix;
178 }
else if (ch == QLatin1Char(
',') && size() > 1) {
182 for (QString &topNext : top().next)
188
189
193 location.fatal(QStringLiteral(
"Missing '}'"));
200bool Config::m_debug =
false;
201bool Config::m_atomsDump =
false;
206QMap<QString, QString>
Config::m_extractedDirs;
207QStack<QString>
Config::m_workingDirs;
208QMap<QString, QStringList>
Config::m_includeFilesMap;
211
212
213
214
217
218
219
220
221
222
223
224
225
228 if (m_name.isEmpty())
229 return defaultString;
232 for (
const auto &value : std::as_const(m_values)) {
233 if (!result.isEmpty() && !result.endsWith(QChar(
'\n')))
234 result.append(QChar(
' '));
235 result.append(value.m_value);
241
242
246 for (
const auto &value : std::as_const(m_values))
247 result << value.m_value;
252
253
256 const auto &stringList = asStringList();
257 return QSet<QString>(stringList.cbegin(), stringList.cend());
261
262
265 return QVariant(asString()).toBool();
269
270
271
272
273
274
275
278 const QStringList strs = asStringList();
283 for (
const auto &str : strs)
289
290
291
294 m_expandVars << other.m_expandVars;
295 QList<ExpandVar>::Iterator it = m_expandVars.end();
296 it -= other.m_expandVars.size();
297 std::for_each(it, m_expandVars.end(), [
this](ExpandVar &v) {
298 v.m_valueIndex += m_values.size();
300 m_values << other.m_values;
301 m_location = other.m_location;
305
306
307
308
309
310
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
332
333
334
335
336void Config::
init(
const QString &programName,
const QStringList &args)
338 m_prog = programName;
339 processCommandLineOptions(args);
349
350
353 m_location = Location();
354 m_configVars.clear();
355 m_includeFilesMap.clear();
356 m_excludedPaths.reset();
360
361
379 const auto setListFlag = [
this](
const QString &key,
bool test) {
380 setStringList(key, QStringList(test ? QStringLiteral(
"true") : QStringLiteral(
"false")));
382#define SET(opt, test) setListFlag(opt, m_parser.isSet(m_parser.test))
391 m_parser.isSet(m_parser.noLinkErrorsOption)
392 || qEnvironmentVariableIsSet(
"QDOC_NOLINKERRORS"));
398
399
400
401
402
409 load(Location(), fileName);
410 if (m_location.isEmpty())
411 m_location = Location(fileName);
413 m_location.setEtc(
true);
429
430
431void Config::expandVariables()
433 for (
auto &configVar : m_configVars) {
434 for (
auto it = configVar.m_expandVars.crbegin(); it != configVar.m_expandVars.crend(); ++it) {
435 Q_ASSERT(it->m_valueIndex < configVar.m_values.size());
436 const QString &key = it->m_var;
437 const auto &refVar = m_configVars.value(key);
438 if (refVar.m_name.isEmpty()) {
439 configVar.m_location.fatal(
440 QStringLiteral(
"Environment or configuration variable '%1' undefined")
442 }
else if (!refVar.m_expandVars.empty()) {
443 configVar.m_location.fatal(
444 QStringLiteral(
"Nested variable expansion not allowed"),
445 QStringLiteral(
"When expanding '%1' at %2:%3")
446 .arg(refVar.m_name, refVar.m_location.filePath(),
447 QString::number(refVar.m_location.lineNo())));
450 if (it->m_delim.isNull())
451 expanded = m_configVars.value(key).asStringList().join(QString());
453 expanded = m_configVars.value(key).asStringList().join(it->m_delim);
454 configVar.m_values[it->m_valueIndex].m_value.insert(it->m_index, expanded);
456 configVar.m_expandVars.clear();
461
462
465 m_configVars.insert(var, ConfigVar(var, values, QDir::currentPath()));
469
470
471
474 m_configVars[var].append(ConfigVar(var, values, QDir::currentPath()));
478
479
480void Config::processCommandLineOptions(
const QStringList &args)
482 m_parser.process(args);
484 m_defines = m_parser.values(m_parser.defineOption);
485 m_dependModules = m_parser.values(m_parser.dependsOption);
489 generateExamples = !m_parser.isSet(m_parser.noExamplesOption);
490 if (m_parser.isSet(m_parser.installDirOption))
491 installDir = m_parser.value(m_parser.installDirOption);
492 if (m_parser.isSet(m_parser.outputDirOption))
493 overrideOutputDir = QDir(m_parser.value(m_parser.outputDirOption)).absolutePath();
495 const auto outputFormats = m_parser.values(m_parser.outputFormatOption);
496 for (
const auto &format : outputFormats)
497 overrideOutputFormats.insert(format);
498 m_debug = m_parser.isSet(m_parser.debugOption) || qEnvironmentVariableIsSet(
"QDOC_DEBUG");
499 m_atomsDump = m_parser.isSet(m_parser.atomsDumpOption);
500 m_showInternal = m_parser.isSet(m_parser.showInternalOption)
501 || qEnvironmentVariableIsSet(
"QDOC_SHOW_INTERNAL");
503 if (m_parser.isSet(m_parser.prepareOption))
505 if (m_parser.isSet(m_parser.generateOption))
507 if (m_debug || m_parser.isSet(m_parser.logProgressOption))
509 if (m_parser.isSet(m_parser.timestampsOption))
511 if (m_parser.isSet(m_parser.useDocBookExtensions))
515void Config::setIncludePaths()
517 QDir currentDir = QDir::current();
518 const auto addIncludePaths = [
this, currentDir](
const char *flag,
const QStringList &paths) {
519 for (
const auto &path : paths)
520 m_includePaths << currentDir.absoluteFilePath(path).insert(0, flag);
523 addIncludePaths(
"-I", m_parser.values(m_parser.includePathOption));
524#ifdef QDOC_PASS_ISYSTEM
525 addIncludePaths(
"-isystem", m_parser.values(m_parser.includePathSystemOption));
527 addIncludePaths(
"-F", m_parser.values(m_parser.frameworkOption));
531
532
533void Config::setIndexDirs()
535 m_indexDirs = m_parser.values(m_parser.indexDirOption);
536 auto it = std::remove_if(m_indexDirs.begin(), m_indexDirs.end(),
537 [](
const QString &s) {
return !QFile::exists(s); });
539 std::for_each(it, m_indexDirs.end(), [](
const QString &s) {
540 qCWarning(lcQdoc) <<
"Cannot find index directory: " << s;
542 m_indexDirs.erase(it, m_indexDirs.end());
546
547
548
549
550
554 if (overrideOutputDir.isNull())
557 t = overrideOutputDir;
560 t += QLatin1Char(
'/') + project.toLower();
562 if (m_configVars.value(format + Config::dot +
"nosubdirs").asBool()) {
563 QString singleOutputSubdir = m_configVars.value(format + Config::dot +
"outputsubdir").asString();
564 if (singleOutputSubdir.isEmpty())
565 singleOutputSubdir =
"html";
566 t += QLatin1Char(
'/') + singleOutputSubdir;
568 return QDir::cleanPath(t);
572
573
574
575
578 if (overrideOutputFormats.isEmpty())
581 return overrideOutputFormats;
599
600
601
602
603
604
608 const auto &configVar = m_configVars.value(var);
610 for (
const auto &value : configVar.m_values) {
611 const QString ¤tPath = value.m_path;
612 QString rawValue = value.m_value.simplified();
615 if (flags & IncludePaths) {
616 const QStringList prefixes = QStringList()
617 << QLatin1String(
"-I")
618 << QLatin1String(
"-F")
619 << QLatin1String(
"-isystem");
620 const auto end = std::end(prefixes);
622 std::find_if(std::begin(prefixes), end,
623 [&rawValue](
const QString &p) {
624 return rawValue.startsWith(p);
628 rawValue.remove(0, it->size());
629 if (rawValue.isEmpty())
632 prefix = prefixes[0];
636 QDir dir(rawValue.trimmed());
637 const QString path = dir.path();
639 if (dir.isRelative())
640 dir.setPath(currentPath + QLatin1Char(
'/') + path);
641 if ((flags & Validate) && !QFileInfo::exists(dir.path()))
642 configVar.m_location.warning(QStringLiteral(
"Cannot find file or directory: %1").arg(path));
644 const QString canonicalPath = dir.canonicalPath();
645 if (!canonicalPath.isEmpty())
646 result.append(prefix + canonicalPath);
647 else if (path.contains(QLatin1Char(
'*')) || path.contains(QLatin1Char(
'?')))
651 qUtf8Printable(QStringLiteral(
"%1: Ignored nonexistent path \'%2\'")
652 .arg(configVar.m_location.toString(), rawValue));
659
660
661
662
663
664
665
669 const auto subRegExps = getRegExpList(var);
671 for (
const auto ®Exp : subRegExps) {
672 if (!regExp.isValid())
674 if (!pattern.isEmpty())
675 pattern += QLatin1Char(
'|');
676 pattern += QLatin1String(
"(?:") + regExp.pattern() + QLatin1Char(
')');
678 if (pattern.isEmpty())
679 pattern = QLatin1String(
"$x");
680 return QRegularExpression(pattern);
684
685
686
687
690 const QStringList strs = m_configVars.value(var).asStringList();
691 QList<QRegularExpression> regExps;
692 for (
const auto &str : strs)
693 regExps += QRegularExpression(str);
698
699
700
701
702
705 QSet<QString> result;
706 QString varDot = var + QLatin1Char(
'.');
707 for (
auto it = m_configVars.constBegin(); it != m_configVars.constEnd(); ++it) {
708 if (it.key().startsWith(varDot)) {
709 QString subVar = it.key().mid(varDot.size());
710 int dot = subVar.indexOf(QLatin1Char(
'.'));
712 subVar.truncate(dot);
713 result.insert(subVar);
720
721
722
723
726 QString ext = QFileInfo(fileName).suffix();
728 if (!m_includeFilesMap.contains(ext)) {
730 result.erase(std::remove_if(result.begin(), result.end(),
731 [&](
const QString &s) {
return !s.endsWith(ext); }),
733 const QStringList dirs =
737 for (
const auto &dir : dirs)
738 result += getFilesHere(dir,
"*." + ext, location());
739 result.removeDuplicates();
740 m_includeFilesMap.insert(ext, result);
742 const QStringList &paths = (*m_includeFilesMap.find(ext));
743 QString match = fileName;
744 if (!match.startsWith(
'/'))
746 for (
const auto &path : paths) {
747 if (path.endsWith(match))
754
755
756
757
758
759
760
761
763 const QSet<QString> &excludedDirs,
764 const QSet<QString> &excludedFiles)
766 QStringList result = getCanonicalPathList(filesVar, Validate);
767 const QStringList dirs = getCanonicalPathList(dirsVar, Validate);
771 for (
const auto &dir : dirs)
772 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
777 const QSet<QString> &excludedFiles)
780 const QStringList dirs = getCanonicalPathList(
"exampledirs");
781 const QString nameFilter =
" *.qdoc";
783 for (
const auto &dir : dirs)
784 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
789 const QSet<QString> &excludedFiles)
792 const QStringList dirs = getCanonicalPathList(
"exampledirs");
795 for (
const auto &dir : dirs)
796 result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles);
808
809
810
813 QFileInfo fileInfo(examplePath);
814 QStringList validNames;
815 validNames << QLatin1String(
"CMakeLists.txt")
816 << fileInfo.fileName() + QLatin1String(
".pro")
817 << fileInfo.fileName() + QLatin1String(
".qmlproject")
818 << fileInfo.fileName() + QLatin1String(
".pyproject")
819 << QLatin1String(
"qbuild.pro");
823 for (
const auto &name : std::as_const(validNames)) {
824 projectFile = Config::findFile(Location(), m_exampleFiles, m_exampleDirs,
825 examplePath + QLatin1Char(
'/') + name);
826 if (!projectFile.isEmpty())
852
853
854
855
856
857
858
859
861 const QStringList &dirs,
const QString &fileName,
862 QString *userFriendlyFilePath)
864 if (fileName.isEmpty() || fileName.startsWith(QLatin1Char(
'/'))) {
865 if (userFriendlyFilePath)
866 *userFriendlyFilePath = fileName;
871 QStringList components = fileName.split(QLatin1Char(
'?'));
872 QString firstComponent = components.first();
874 for (
const auto &file : files) {
875 if (file == firstComponent || file.endsWith(QLatin1Char(
'/') + firstComponent)) {
876 fileInfo.setFile(file);
877 if (!fileInfo.exists())
878 location.fatal(QStringLiteral(
"File '%1' does not exist").arg(file));
883 if (fileInfo.fileName().isEmpty()) {
884 for (
const auto &dir : dirs) {
885 fileInfo.setFile(QDir(dir), firstComponent);
886 if (fileInfo.exists())
891 if (userFriendlyFilePath)
892 userFriendlyFilePath->clear();
893 if (!fileInfo.exists())
903 if (userFriendlyFilePath) {
904 for (
auto c = components.constBegin();;) {
905 bool isArchive = (c != components.constEnd() - 1);
906 userFriendlyFilePath->append(*c);
909 QString extracted = m_extractedDirs[fileInfo.filePath()];
912 fileInfo.setFile(QDir(extracted), *c);
917 userFriendlyFilePath->append(QLatin1Char(
'?'));
922 return fileInfo.filePath();
938
939
940
941
942
943
945 const QString &userFriendlySourceFilePath,
const QString &targetDirPath)
956 QFile inFile(sourceFilePath);
957 if (!inFile.open(QFile::ReadOnly)) {
958 location.warning(QStringLiteral(
"Cannot open input file for copy: '%1': %2")
959 .arg(sourceFilePath, inFile.errorString()));
997 QString outFileName{userFriendlySourceFilePath};
998 QFileInfo outFileNameInfo{userFriendlySourceFilePath};
999 if (outFileNameInfo.isAbsolute())
1000 outFileName = outFileNameInfo.fileName();
1002 outFileName = targetDirPath +
"/" + outFileName;
1003 QDir targetDir(targetDirPath);
1004 if (!targetDir.exists())
1005 targetDir.mkpath(
".");
1007 QFile outFile(outFileName);
1008 if (!outFile.open(QFile::WriteOnly)) {
1010 location.warning(QStringLiteral(
"Cannot open output file for copy: '%1': %2")
1011 .arg(outFileName, outFile.errorString()));
1023 while ((len = inFile.read(buffer,
sizeof(buffer))) > 0)
1024 outFile.write(buffer, len);
1029
1030
1031
1035 for (
int i = 0; i != value.size(); ++i) {
1036 uint c = value[i].unicode();
1038 max = qMax(max,
static_cast<
int>(c));
1044
1045
1046
1047bool Config::isMetaKeyChar(QChar ch)
1049 return ch.isLetterOrNumber() || ch == QLatin1Char(
'_') || ch == QLatin1Char(
'.')
1050 || ch == QLatin1Char(
'{') || ch == QLatin1Char(
'}') || ch == QLatin1Char(
',');
1054
1055
1056
1057QStringList
Config::loadMaster(
const QString &fileName)
1060 QFile fin(fileName);
1061 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1062 if (!Config::installDir.isEmpty()) {
1063 qsizetype prefix = location.filePath().size() - location.fileName().size();
1064 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1065 + fileName.right(fileName.size() - prefix));
1067 if (!fin.open(QFile::ReadOnly | QFile::Text))
1068 location.fatal(QStringLiteral(
"Cannot open master qdocconf file '%1': %2")
1069 .arg(fileName, fin.errorString()));
1071 QTextStream stream(&fin);
1072 QStringList qdocFiles;
1073 QDir configDir(QFileInfo(fileName).canonicalPath());
1074 QString line = stream.readLine();
1075 while (!line.isNull()) {
1076 if (!line.isEmpty())
1077 qdocFiles.append(QFileInfo(configDir, line).filePath());
1078 line = stream.readLine();
1085
1086
1087
1088
1089
1092 QFileInfo fileInfo(fileName);
1093 pushWorkingDir(fileInfo.canonicalPath());
1094 static const QRegularExpression keySyntax(QRegularExpression::anchoredPattern(QLatin1String(
"\\w+(?:\\.\\w+)*")));
1098 location.advance(c);
1104#define SKIP_SPACES()
1105 while (c.isSpace() && cc != '\n')
1113 location.fatal(QStringLiteral(
"Too many nested includes"));
1115 QFile fin(fileInfo.fileName());
1116 if (!fin.open(QFile::ReadOnly | QFile::Text)) {
1117 if (!Config::installDir.isEmpty()) {
1118 qsizetype prefix = location.filePath().size() - location.fileName().size();
1119 fin.setFileName(Config::installDir + QLatin1Char(
'/')
1120 + fileName.right(fileName.size() - prefix));
1122 if (!fin.open(QFile::ReadOnly | QFile::Text))
1124 QStringLiteral(
"Cannot open file '%1': %2").arg(fileName, fin.errorString()));
1127 QTextStream stream(&fin);
1128 QString text = stream.readAll();
1129 text += QLatin1String(
"\n\n");
1130 text += QLatin1Char(
'\0');
1133 location.push(fileName);
1137 QChar c = text.at(0);
1138 uint cc = c.unicode();
1139 while (i < text.size()) {
1142 }
else if (c.isSpace()) {
1144 }
else if (cc ==
'#') {
1147 }
while (cc !=
'\n');
1148 }
else if (isMetaKeyChar(c)) {
1151 QStringList rhsValues;
1152 QList<ExpandVar> expandVars;
1154 bool inQuote =
false;
1155 bool needsExpansion =
false;
1159 stack.process(c, location);
1161 }
while (isMetaKeyChar(c));
1163 const QStringList keys = stack.getExpanded(location);
1166 if (keys.size() == 1 && keys.first() == QLatin1String(
"include")) {
1167 QString includeFile;
1170 location.fatal(QStringLiteral(
"Bad include syntax"));
1174 while (!c.isSpace() && cc !=
'#' && cc !=
')') {
1179 while (c.isLetterOrNumber() || cc ==
'_') {
1183 if (!var.isEmpty()) {
1184 const QByteArray val = qgetenv(var.toLatin1().data());
1186 location.fatal(QStringLiteral(
"Environment variable '%1' undefined")
1189 includeFile += QString::fromLatin1(val);
1199 location.fatal(QStringLiteral(
"Bad include syntax"));
1202 if (cc !=
'#' && cc !=
'\n')
1203 location.fatal(QStringLiteral(
"Trailing garbage"));
1206
1207
1208 load(location, QFileInfo(QDir(m_workingDirs.top()), includeFile).filePath());
1211
1212
1213
1219 location.fatal(QStringLiteral(
"Expected '=' or '+=' after key"));
1225 qsizetype metaCharPos;
1230 }
else if (cc >
'0' && cc <
'8') {
1231 word += QChar(c.digitValue());
1233 }
else if ((metaCharPos = QString::fromLatin1(
"abfnrtv").indexOf(c))
1235 word += QLatin1Char(
"\a\b\f\n\r\t\v"[metaCharPos]);
1240 }
else if (c.isSpace() || cc ==
'#') {
1243 location.fatal(QStringLiteral(
"Unterminated string"));
1246 if (!word.isEmpty() || needsExpansion) {
1249 needsExpansion =
false;
1251 if (cc ==
'\n' || cc ==
'#')
1255 }
else if (cc ==
'"') {
1257 if (!word.isEmpty() || needsExpansion)
1260 needsExpansion =
false;
1264 }
else if (cc ==
'$') {
1267 bool braces =
false;
1273 while (c.isLetterOrNumber() || cc ==
'_') {
1285 else if (delim ==
'}')
1288 location.fatal(QStringLiteral(
"Missing '}'"));
1290 if (!var.isEmpty()) {
1291 const QByteArray val = qgetenv(var.toLatin1().constData());
1293 expandVars <<
ExpandVar(rhsValues.size(), word.size(), var, delim);
1294 needsExpansion =
true;
1295 }
else if (braces) {
1296 text.insert(i, QString::fromLatin1(val));
1300 word += QString::fromLatin1(val);
1304 if (!inQuote && cc ==
'=')
1305 location.fatal(QStringLiteral(
"Unexpected '='"));
1309 for (
const auto &key : keys) {
1310 if (!keySyntax.match(key).hasMatch())
1311 keyLoc.fatal(QStringLiteral(
"Invalid key '%1'").arg(key));
1313 ConfigVar configVar(key, rhsValues, QDir::currentPath(), keyLoc, expandVars);
1314 if (plus && m_configVars.contains(key)) {
1315 m_configVars[key].append(configVar);
1317 m_configVars.insert(key, configVar);
1322 location.fatal(QStringLiteral(
"Unexpected character '%1' at beginning of line").arg(c));
1332bool Config::isFileExcluded(
const QString &fileName,
const QSet<QString> &excludedFiles)
1334 for (
const QString &entry : excludedFiles) {
1335 if (entry.contains(QLatin1Char(
'*')) || entry.contains(QLatin1Char(
'?'))) {
1336 QRegularExpression re(QRegularExpression::wildcardToRegularExpression(entry));
1337 if (re.match(fileName).hasMatch())
1341 return excludedFiles.contains(fileName);
1344QStringList
Config::getFilesHere(
const QString &uncleanDir,
const QString &nameFilter,
1345 const Location &location,
const QSet<QString> &excludedDirs,
1346 const QSet<QString> &excludedFiles)
1351 location.isEmpty() ? QDir::cleanPath(uncleanDir) : QDir(uncleanDir).canonicalPath();
1353 if (excludedDirs.contains(dir))
1358 dirInfo.setNameFilters(nameFilter.split(QLatin1Char(
' ')));
1359 dirInfo.setSorting(QDir::Name);
1360 dirInfo.setFilter(QDir::Files);
1361 QStringList fileNames = dirInfo.entryList();
1362 for (
const auto &file : std::as_const(fileNames)) {
1365 if (!file.startsWith(QLatin1Char(
'~'))) {
1366 QString s = dirInfo.filePath(file);
1367 QString c = QDir::cleanPath(s);
1368 if (!isFileExcluded(c, excludedFiles))
1373 dirInfo.setNameFilters(QStringList(QLatin1String(
"*")));
1374 dirInfo.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
1375 fileNames = dirInfo.entryList();
1376 for (
const auto &file : fileNames)
1377 result += getFilesHere(dirInfo.filePath(file), nameFilter, location, excludedDirs,
1383
1384
1385
1386void Config::pushWorkingDir(
const QString &dir)
1388 m_workingDirs.push(dir);
1389 QDir::setCurrent(dir);
1393
1394
1395
1396
1399 Q_ASSERT(!m_workingDirs.isEmpty());
1400 m_workingDirs.pop();
1401 if (!m_workingDirs.isEmpty())
1402 QDir::setCurrent(m_workingDirs.top());
1406 if (m_excludedPaths)
1407 return *m_excludedPaths;
1412 QSet<QString> excludedDirs = QSet<QString>(excludedDirList.cbegin(), excludedDirList.cend());
1413 QSet<QString> excludedFiles = QSet<QString>(excludedFilesList.cbegin(), excludedFilesList.cend());
1415 m_excludedPaths.emplace(ExcludedPaths{excludedDirs, excludedFiles});
1417 return *m_excludedPaths;
1421 static QStringList accepted_header_file_extensions{
1422 "ch",
"h",
"h++",
"hh",
"hpp",
"hxx"
1427 QStringList headerList =
1430 std::set<HeaderFilePath> headers{};
1432 for (
const auto& header : headerList) {
1433 if (header.contains(
"doc/snippets"))
continue;
1435 if (!accepted_header_file_extensions.contains(QFileInfo{header}.suffix()))
1438 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 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