summaryrefslogtreecommitdiff
path: root/src/qdoc/clangcodeparser.cpp
diff options
context:
space:
mode:
authorLuca Di Sera <luca.disera@qt.io>2023-03-24 15:08:20 +0100
committerLuca Di Sera <luca.disera@qt.io>2023-03-27 11:45:11 +0100
commit0b6c49e4a396c6561f71c3c8d7cedbc5cfec8353 (patch)
treeb7ac311670c49d10ccea547e8e2065fd12cf50cb /src/qdoc/clangcodeparser.cpp
parentdbd68d439b17f8d3daa253256b3b79e053b01131 (diff)
downloadqttools-0b6c49e4a396c6561f71c3c8d7cedbc5cfec8353.tar.gz
QDoc: Remove nesting level from `ClangCodeParser::buildPCH`
`ClangCodeParser`, the class responsible for parsing Cpp source files during a QDoc run, uses a PCH to speed up compilation when reading the above mentioned source file. A PCH file is built in `ClangCodeParser::buildPCH`. To avoid redoing the same work more than one time if it is unnecessary, `buildPCH` branches on certain conditions and does nothing if those conditions are not met. To make the code easier to read, move the code that performs the PCH building operation to the top level of the method body, instead of branching, and use early returns when the conditions are not satisfied. Change-Id: I95b07a12bc1723ea7bdaee41367483a61dcb5609 Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io> Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Diffstat (limited to 'src/qdoc/clangcodeparser.cpp')
-rw-r--r--src/qdoc/clangcodeparser.cpp219
1 files changed, 110 insertions, 109 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index b50c2b718..95c91aa91 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -1353,127 +1353,128 @@ void ClangCodeParser::getMoreArgs()
*/
void ClangCodeParser::buildPCH(QString module_header)
{
- if (!m_pchFileDir && !module_header.isEmpty()) {
- m_pchFileDir.reset(new QTemporaryDir(QDir::tempPath() + QLatin1String("/qdoc_pch")));
- if (m_pchFileDir->isValid()) {
- const QByteArray module = module_header.toUtf8();
- QByteArray header;
- QByteArray privateHeaderDir;
- qCDebug(lcQdoc) << "Build and visit PCH for" << module_header;
- // A predicate for std::find_if() to locate a path to the module's header
- // (e.g. QtGui/QtGui) to be used as pre-compiled header
- struct FindPredicate
+ if (m_pchFileDir) return;
+ if (module_header.isEmpty()) return;
+
+ m_pchFileDir.reset(new QTemporaryDir(QDir::tempPath() + QLatin1String("/qdoc_pch")));
+ if (m_pchFileDir->isValid()) {
+ const QByteArray module = module_header.toUtf8();
+ QByteArray header;
+ QByteArray privateHeaderDir;
+ qCDebug(lcQdoc) << "Build and visit PCH for" << module_header;
+ // A predicate for std::find_if() to locate a path to the module's header
+ // (e.g. QtGui/QtGui) to be used as pre-compiled header
+ struct FindPredicate
+ {
+ enum SearchType { Any, Module, Private };
+ QByteArray &candidate_;
+ const QByteArray &module_;
+ SearchType type_;
+ FindPredicate(QByteArray &candidate, const QByteArray &module,
+ SearchType type = Any)
+ : candidate_(candidate), module_(module), type_(type)
{
- enum SearchType { Any, Module, Private };
- QByteArray &candidate_;
- const QByteArray &module_;
- SearchType type_;
- FindPredicate(QByteArray &candidate, const QByteArray &module,
- SearchType type = Any)
- : candidate_(candidate), module_(module), type_(type)
- {
- }
+ }
- bool operator()(const QByteArray &p) const
- {
- if (type_ != Any && !p.endsWith(module_))
- return false;
- candidate_ = p + "/";
- switch (type_) {
- case Any:
- case Module:
- candidate_.append(module_);
- break;
- case Private:
- candidate_.append("private");
- break;
- default:
- break;
- }
- if (p.startsWith("-I"))
- candidate_ = candidate_.mid(2);
- return QFile::exists(QString::fromUtf8(candidate_));
+ bool operator()(const QByteArray &p) const
+ {
+ if (type_ != Any && !p.endsWith(module_))
+ return false;
+ candidate_ = p + "/";
+ switch (type_) {
+ case Any:
+ case Module:
+ candidate_.append(module_);
+ break;
+ case Private:
+ candidate_.append("private");
+ break;
+ default:
+ break;
}
- };
-
- // First, search for an include path that contains the module name, then any path
- QByteArray candidate;
- auto it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
- FindPredicate(candidate, module, FindPredicate::Module));
- if (it == m_includePaths.end())
- it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
- FindPredicate(candidate, module, FindPredicate::Any));
- if (it != m_includePaths.end())
- header = candidate;
-
- // Find the path to module's private headers - currently unused
- it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
- FindPredicate(candidate, module, FindPredicate::Private));
- if (it != m_includePaths.end())
- privateHeaderDir = candidate;
+ if (p.startsWith("-I"))
+ candidate_ = candidate_.mid(2);
+ return QFile::exists(QString::fromUtf8(candidate_));
+ }
+ };
+ // First, search for an include path that contains the module name, then any path
+ QByteArray candidate;
+ auto it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
+ FindPredicate(candidate, module, FindPredicate::Module));
+ if (it == m_includePaths.end())
+ it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
+ FindPredicate(candidate, module, FindPredicate::Any));
+ if (it != m_includePaths.end())
+ header = candidate;
+
+ // Find the path to module's private headers - currently unused
+ it = std::find_if(m_includePaths.begin(), m_includePaths.end(),
+ FindPredicate(candidate, module, FindPredicate::Private));
+ if (it != m_includePaths.end())
+ privateHeaderDir = candidate;
+
+ if (header.isEmpty()) {
+ qWarning() << "(qdoc) Could not find the module header in include paths for module"
+ << module << " (include paths: " << m_includePaths << ")";
+ qWarning() << " Artificial module header built from header dirs in qdocconf "
+ "file";
+ }
+ m_args.push_back("-xc++");
+ CXTranslationUnit tu;
+ QString tmpHeader = m_pchFileDir->path() + "/" + module;
+ if (QFile tmpHeaderFile(tmpHeader); tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) {
+ QTextStream out(&tmpHeaderFile);
if (header.isEmpty()) {
- qWarning() << "(qdoc) Could not find the module header in include paths for module"
- << module << " (include paths: " << m_includePaths << ")";
- qWarning() << " Artificial module header built from header dirs in qdocconf "
- "file";
- }
- m_args.push_back("-xc++");
- CXTranslationUnit tu;
- QString tmpHeader = m_pchFileDir->path() + "/" + module;
- if (QFile tmpHeaderFile(tmpHeader); tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) {
- QTextStream out(&tmpHeaderFile);
- if (header.isEmpty()) {
- for (auto it = m_allHeaders.constKeyValueBegin();
- it != m_allHeaders.constKeyValueEnd(); ++it) {
- if (!(*it).first.endsWith(QLatin1String("_p.h"))
- && !(*it).first.startsWith(QLatin1String("moc_"))) {
- QString line = QLatin1String("#include \"") + (*it).second
- + QLatin1String("/") + (*it).first + QLatin1String("\"");
- out << line << "\n";
- }
- }
- } else {
- QFileInfo headerFile(header);
- if (!headerFile.exists()) {
- qWarning() << "Could not find module header file" << header;
- return;
+ for (auto it = m_allHeaders.constKeyValueBegin();
+ it != m_allHeaders.constKeyValueEnd(); ++it) {
+ if (!(*it).first.endsWith(QLatin1String("_p.h"))
+ && !(*it).first.startsWith(QLatin1String("moc_"))) {
+ QString line = QLatin1String("#include \"") + (*it).second
+ + QLatin1String("/") + (*it).first + QLatin1String("\"");
+ out << line << "\n";
}
- out << QLatin1String("#include \"") + header + QLatin1String("\"");
}
+ } else {
+ QFileInfo headerFile(header);
+ if (!headerFile.exists()) {
+ qWarning() << "Could not find module header file" << header;
+ return;
+ }
+ out << QLatin1String("#include \"") + header + QLatin1String("\"");
}
+ }
- CXErrorCode err =
- clang_parseTranslationUnit2(index_, tmpHeader.toLatin1().data(), m_args.data(),
- static_cast<int>(m_args.size()), nullptr, 0,
- flags_ | CXTranslationUnit_ForSerialization, &tu);
- qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << tmpHeader << m_args
- << ") returns" << err;
-
- printDiagnostics(tu);
-
- if (!err && tu) {
- m_pchName = m_pchFileDir->path().toUtf8() + "/" + module + ".pch";
- auto error = clang_saveTranslationUnit(tu, m_pchName.constData(),
- clang_defaultSaveOptions(tu));
- if (error) {
- qCCritical(lcQdoc) << "Could not save PCH file for" << module_header;
- m_pchName.clear();
- } else {
- // Visit the header now, as token from pre-compiled header won't be visited
- // later
- CXCursor cur = clang_getTranslationUnitCursor(tu);
- ClangVisitor visitor(m_qdb, m_allHeaders);
- visitor.visitChildren(cur);
- qCDebug(lcQdoc) << "PCH built and visited for" << module_header;
- }
+ CXErrorCode err =
+ clang_parseTranslationUnit2(index_, tmpHeader.toLatin1().data(), m_args.data(),
+ static_cast<int>(m_args.size()), nullptr, 0,
+ flags_ | CXTranslationUnit_ForSerialization, &tu);
+ qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << tmpHeader << m_args
+ << ") returns" << err;
+
+ printDiagnostics(tu);
+
+ if (!err && tu) {
+ m_pchName = m_pchFileDir->path().toUtf8() + "/" + module + ".pch";
+ auto error = clang_saveTranslationUnit(tu, m_pchName.constData(),
+ clang_defaultSaveOptions(tu));
+ if (error) {
+ qCCritical(lcQdoc) << "Could not save PCH file for" << module_header;
+ m_pchName.clear();
} else {
- m_pchFileDir->remove();
- qCCritical(lcQdoc) << "Could not create PCH file for " << module_header;
+ // Visit the header now, as token from pre-compiled header won't be visited
+ // later
+ CXCursor cur = clang_getTranslationUnitCursor(tu);
+ ClangVisitor visitor(m_qdb, m_allHeaders);
+ visitor.visitChildren(cur);
+ qCDebug(lcQdoc) << "PCH built and visited for" << module_header;
}
- clang_disposeTranslationUnit(tu);
- m_args.pop_back(); // remove the "-xc++";
+ } else {
+ m_pchFileDir->remove();
+ qCCritical(lcQdoc) << "Could not create PCH file for " << module_header;
}
+ clang_disposeTranslationUnit(tu);
+ m_args.pop_back(); // remove the "-xc++";
}
}