diff options
author | Topi Reinio <topi.reinio@qt.io> | 2019-06-07 15:12:54 +0200 |
---|---|---|
committer | Topi Reinio <topi.reinio@qt.io> | 2019-06-07 15:22:42 +0200 |
commit | c7c3e2f26af0842631c95f054600b6b90ef3675b (patch) | |
tree | 443673aa54138f871c3054dd86034fb6e117c822 | |
parent | eb5e165deb3bccdae40c146e3d311464b7548641 (diff) | |
download | qttools-c7c3e2f26af0842631c95f054600b6b90ef3675b.tar.gz |
qdoc: Fix regressions in include path handling
Commit 50a172f8 broke the way QDoc parses include paths passed
from qdocconf files by always prepending them with '-I'. While
this ensured that Clang uses them as include paths, QDoc no
longer found module headers local to the documentation project
as '-I/path/to/module' is never a valid file system path.
This change fixes the issue and removes duplicated and
unnecessary code.
Fixes: QTBUG-76279
Change-Id: I7006000ec6be823afd10bae59eb88780ccf32b23
Reviewed-by: Martin Smith <martin.smith@qt.io>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
-rw-r--r-- | src/qdoc/clangcodeparser.cpp | 115 |
1 files changed, 61 insertions, 54 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index 407f67604..76ac62897 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -1022,19 +1022,24 @@ void ClangCodeParser::initializeParser(const Config &config) version_ = config.getString(CONFIG_VERSION); const auto args = config.getStringList(CONFIG_INCLUDEPATHS); QStringList squeezedArgs; - int i = 0; - while (i < args.size()) { - if (args.at(i) != QLatin1String("-I")) { - if (args.at(i).startsWith(QLatin1String("-I"))) - squeezedArgs << args.at(i); - else - squeezedArgs << QLatin1String("-I") + args.at(i); - } - i++; + for (const auto &p : args) { + if (p.startsWith(QLatin1String("-I"))) + squeezedArgs << p.mid(2).trimmed(); + else + squeezedArgs << p; } + // Remove empty paths and duplicates + squeezedArgs.removeAll({}); + squeezedArgs.removeDuplicates(); includePaths_.resize(squeezedArgs.size()); std::transform(squeezedArgs.begin(), squeezedArgs.end(), includePaths_.begin(), - [](const QString &s) { return s.toUtf8(); }); + [](const QString &s) { + QByteArray path(s.toUtf8()); + QFileInfo fi(QDir::current(), s); + if (fi.exists()) + path = fi.canonicalFilePath().toUtf8(); + return path.prepend("-I"); + }); CppCodeParser::initializeParser(config); pchFileDir_.reset(nullptr); allHeaders_.clear(); @@ -1206,14 +1211,6 @@ bool ClangCodeParser::getMoreArgs() moreArgs_ = includePaths_; } - // Canonicalize include paths - for (int i = 0; i < moreArgs_.size(); ++i) { - if (!moreArgs_.at(i).startsWith("-")) { - QFileInfo fi(QDir::current(), moreArgs_[i]); - if (fi.exists()) - moreArgs_[i] = fi.canonicalFilePath().toLatin1(); - } - } return guessedIncludePaths; } @@ -1232,49 +1229,59 @@ void ClangCodeParser::buildPCH() QByteArray header; QByteArray privateHeaderDir; Location::logToStdErrAlways("Build & visit PCH for " + moduleHeader()); - // Find the path to the module's header (e.g. QtGui/QtGui) to be used - // as pre-compiled header - for (const auto &p : qAsConst(includePaths_)) { - if (p.endsWith(module)) { - QByteArray candidate = p + "/" + module; - if (p.startsWith("-I")) - candidate = candidate.mid(2); - if (QFile::exists(QString::fromUtf8(candidate))) { - header = candidate; + // 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) {} + + 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; - } - } - } - if (header.isEmpty()) { - for (const auto &p : qAsConst(includePaths_)) { - QByteArray candidate = p + "/" + module; - if (QFile::exists(QString::fromUtf8(candidate))) { - header = candidate; + case Private: + candidate_.append("private"); break; - } - } - } - // Find the path to the module's private header directory (e.g. - // include/QtGui/5.8.0/QtGui/private) to use for including all - // the private headers in the PCH. - for (const auto &p : qAsConst(includePaths_)) { - if (p.endsWith(module)) { - QByteArray candidate = p + "/private"; - if (QFile::exists(QString::fromUtf8(candidate))) { - privateHeaderDir = candidate; + default: break; } + if (p.startsWith("-I")) + candidate_ = candidate_.mid(2); + return QFile::exists(QString::fromUtf8(candidate_)); } - } - if (header.isEmpty()) { - QByteArray installDocDir = Config::installDir.toUtf8(); - const QByteArray candidate = installDocDir + "/../include/" + module + "/" + module; - if (QFile::exists(QString::fromUtf8(candidate))) - header = candidate; - } + }; + + // First, search for an include path that contains the module name, then any path + QByteArray candidate; + auto it = std::find_if(includePaths_.begin(), + includePaths_.end(), + FindPredicate(candidate, module, FindPredicate::Module)); + if (it == includePaths_.end()) + it = std::find_if(includePaths_.begin(), + includePaths_.end(), + FindPredicate(candidate, module, FindPredicate::Any)); + if (it != includePaths_.end()) + header = candidate; + + // Find the path to module's private headers - currently unused + it = std::find_if(includePaths_.begin(), + includePaths_.end(), + FindPredicate(candidate, module, FindPredicate::Private)); + if (it != includePaths_.end()) + privateHeaderDir = candidate; + if (header.isEmpty()) { qWarning() << "(qdoc) Could not find the module header in the include path for module" - << module << " (include paths: "<< includePaths_ << ")"; + << module << " (include paths: " << includePaths_ << ")"; } else { args_.push_back("-xc++"); CXTranslationUnit tu; |