diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp index d2f21c90b16bec162cb907322bb2f6ce53784cf4..c86e7f5d646623ae54ae5796db65d02308ec60a6 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp @@ -27,6 +27,8 @@ #include <projectexplorer/kit.h> +#include <utils/algorithm.h> +#include <utils/fileutils.h> #include <utils/macroexpander.h> #include <utils/qtcassert.h> @@ -219,6 +221,91 @@ CMakeConfigItem CMakeConfigItem::fromString(const QString &s) return item; } +static QByteArray trimCMakeCacheLine(const QByteArray &in) { + int start = 0; + while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t')) + ++start; + + return in.mid(start, in.count() - start - 1); +} + +static QByteArrayList splitCMakeCacheLine(const QByteArray &line) { + const int colonPos = line.indexOf(':'); + if (colonPos < 0) + return QByteArrayList(); + + const int equalPos = line.indexOf('=', colonPos + 1); + if (equalPos < colonPos) + return QByteArrayList(); + + return QByteArrayList() << line.mid(0, colonPos) + << line.mid(colonPos + 1, equalPos - colonPos - 1) + << line.mid(equalPos + 1); +} + +QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FileName &cacheFile, QString *errorMessage) +{ + CMakeConfig result; + QFile cache(cacheFile.toString()); + if (!cache.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (errorMessage) + *errorMessage = QCoreApplication::translate("CMakeProjectManager::CMakeConfigItem", "Failed to open %1 for reading.") + .arg(cacheFile.toUserOutput()); + return CMakeConfig(); + } + + QSet<QByteArray> advancedSet; + QMap<QByteArray, QByteArray> valuesMap; + QByteArray documentation; + while (!cache.atEnd()) { + const QByteArray line = trimCMakeCacheLine(cache.readLine()); + + if (line.isEmpty() || line.startsWith('#')) + continue; + + if (line.startsWith("//")) { + documentation = line.mid(2); + continue; + } + + const QByteArrayList pieces = splitCMakeCacheLine(line); + if (pieces.isEmpty()) + continue; + + QTC_ASSERT(pieces.count() == 3, continue); + const QByteArray key = pieces.at(0); + const QByteArray type = pieces.at(1); + const QByteArray value = pieces.at(2); + + if (key.endsWith("-ADVANCED") && value == "1") { + advancedSet.insert(key.left(key.count() - 9 /* "-ADVANCED" */)); + } else if (key.endsWith("-STRINGS") && CMakeConfigItem::typeStringToType(type) == CMakeConfigItem::INTERNAL) { + valuesMap[key.left(key.count() - 8) /* "-STRINGS" */] = value; + } else { + CMakeConfigItem::Type t = CMakeConfigItem::typeStringToType(type); + result << CMakeConfigItem(key, t, documentation, value); + } + } + + // Set advanced flags: + for (int i = 0; i < result.count(); ++i) { + CMakeConfigItem &item = result[i]; + item.isAdvanced = advancedSet.contains(item.key); + + if (valuesMap.contains(item.key)) { + item.values = CMakeConfigItem::cmakeSplitValue(QString::fromUtf8(valuesMap[item.key])); + } else if (item.key == "CMAKE_BUILD_TYPE") { + // WA for known options + item.values << "" << "Debug" << "Release" << "MinSizeRel" << "RelWithDebInfo"; + } + } + + Utils::sort(result, CMakeConfigItem::sortOperator()); + + return result; + +} + QString CMakeConfigItem::toString(const Utils::MacroExpander *expander) const { if (key.isEmpty() || type == CMakeProjectManager::CMakeConfigItem::STATIC) diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h index e52a3ee535a91febe0f08d0186387ef51ead18da..392d727647007b892cf48a1c64616e6c54020c90 100644 --- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h +++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h @@ -31,7 +31,10 @@ #include <functional> namespace ProjectExplorer { class Kit; } -namespace Utils { class MacroExpander; } +namespace Utils { +class FileName; +class MacroExpander; +} // namespace Utils namespace CMakeProjectManager { @@ -55,6 +58,7 @@ public: static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator(); static CMakeConfigItem fromString(const QString &s); + static QList<CMakeConfigItem> itemsFromFile(const Utils::FileName &input, QString *errorMessage); QString toString(const Utils::MacroExpander *expander = nullptr) const; QString toArgument(const Utils::MacroExpander *expander = nullptr) const; diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 17469565f79c77455c6d09cbb6e95cf518f7f637..41b32e954a77526c54cb0c681e1cbdb9affe5cce 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -123,28 +123,6 @@ static QStringList toArguments(const CMakeConfig &config, const MacroExpander *e }); } -static QByteArray trimCMakeCacheLine(const QByteArray &in) { - int start = 0; - while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t')) - ++start; - - return in.mid(start, in.count() - start - 1); -} - -static QByteArrayList splitCMakeCacheLine(const QByteArray &line) { - const int colonPos = line.indexOf(':'); - if (colonPos < 0) - return QByteArrayList(); - - const int equalPos = line.indexOf('=', colonPos + 1); - if (equalPos < colonPos) - return QByteArrayList(); - - return QByteArrayList() << line.mid(0, colonPos) - << line.mid(colonPos + 1, equalPos - colonPos - 1) - << line.mid(equalPos + 1); -} - // -------------------------------------------------------------------- // TeaLeafReader: // -------------------------------------------------------------------- @@ -242,7 +220,7 @@ CMakeConfig TeaLeafReader::parsedConfiguration() const if (!cacheFile.exists()) return result; QString errorMessage; - m_cmakeCache = parseConfiguration(cacheFile, &errorMessage); + m_cmakeCache = CMakeConfigItem::itemsFromFile(cacheFile, &errorMessage); if (!errorMessage.isEmpty()) emit errorOccured(errorMessage); const FileName sourceOfBuildDir @@ -257,67 +235,6 @@ CMakeConfig TeaLeafReader::parsedConfiguration() const return result; } -CMakeConfig TeaLeafReader::parseConfiguration(const FileName &cacheFile, QString *errorMessage) const -{ - CMakeConfig result; - QFile cache(cacheFile.toString()); - if (!cache.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (errorMessage) - *errorMessage = tr("Failed to open %1 for reading.").arg(cacheFile.toUserOutput()); - return CMakeConfig(); - } - - QSet<QByteArray> advancedSet; - QMap<QByteArray, QByteArray> valuesMap; - QByteArray documentation; - while (!cache.atEnd()) { - const QByteArray line = trimCMakeCacheLine(cache.readLine()); - - if (line.isEmpty() || line.startsWith('#')) - continue; - - if (line.startsWith("//")) { - documentation = line.mid(2); - continue; - } - - const QByteArrayList pieces = splitCMakeCacheLine(line); - if (pieces.isEmpty()) - continue; - - QTC_ASSERT(pieces.count() == 3, continue); - const QByteArray key = pieces.at(0); - const QByteArray type = pieces.at(1); - const QByteArray value = pieces.at(2); - - if (key.endsWith("-ADVANCED") && value == "1") { - advancedSet.insert(key.left(key.count() - 9 /* "-ADVANCED" */)); - } else if (key.endsWith("-STRINGS") && CMakeConfigItem::typeStringToType(type) == CMakeConfigItem::INTERNAL) { - valuesMap[key.left(key.count() - 8) /* "-STRINGS" */] = value; - } else { - CMakeConfigItem::Type t = CMakeConfigItem::typeStringToType(type); - result << CMakeConfigItem(key, t, documentation, value); - } - } - - // Set advanced flags: - for (int i = 0; i < result.count(); ++i) { - CMakeConfigItem &item = result[i]; - item.isAdvanced = advancedSet.contains(item.key); - - if (valuesMap.contains(item.key)) { - item.values = CMakeConfigItem::cmakeSplitValue(QString::fromUtf8(valuesMap[item.key])); - } else if (item.key == "CMAKE_BUILD_TYPE") { - // WA for known options - item.values << "" << "Debug" << "Release" << "MinSizeRel" << "RelWithDebInfo"; - } - } - - sort(result, CMakeConfigItem::sortOperator()); - - return result; -} - void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles) { root->setDisplayName(m_projectName); diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h index 45ecc2486d0376612a2560db3f9330e477b4bdf7..9c54472d61ba8f5b96e8a6394581a3319214f388 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.h +++ b/src/plugins/cmakeprojectmanager/tealeafreader.h @@ -70,8 +70,6 @@ private: bool extractCXXFlagsFromMake(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache); bool extractCXXFlagsFromNinja(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache); - CMakeConfig parseConfiguration(const Utils::FileName &cacheFile, QString *errorMessage) const; - Utils::QtcProcess *m_cmakeProcess = nullptr; // For error reporting: