From 2ff642d8e4e2f16b01d20ad589d07f4620f0f914 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Fri, 14 Apr 2017 21:45:41 +0200 Subject: [PATCH] CustomToolChain: Allow MSVC output parser on non-Windows systems To do that, move the existing enumeration-based system to a string base. MSVC/Windows and Custom/Unix shared the same enumeration value (3), so we must provide an operating system aware upgrade path. Task-number: QTCREATORBUG-16247 Change-Id: I8beeeabc09119fc501933a7287f2f982195363a2 Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/clangparser.cpp | 5 + src/plugins/projectexplorer/clangparser.h | 2 + src/plugins/projectexplorer/customparser.cpp | 5 + src/plugins/projectexplorer/customparser.h | 2 + .../projectexplorer/customtoolchain.cpp | 113 ++++++++++++------ src/plugins/projectexplorer/customtoolchain.h | 24 ++-- src/plugins/projectexplorer/gccparser.cpp | 5 + src/plugins/projectexplorer/gccparser.h | 2 + .../projectexplorer/linuxiccparser.cpp | 5 + src/plugins/projectexplorer/linuxiccparser.h | 2 + src/plugins/projectexplorer/msvcparser.cpp | 5 + src/plugins/projectexplorer/msvcparser.h | 2 + 12 files changed, 118 insertions(+), 54 deletions(-) diff --git a/src/plugins/projectexplorer/clangparser.cpp b/src/plugins/projectexplorer/clangparser.cpp index b860d68b0fd..98d733e69fc 100644 --- a/src/plugins/projectexplorer/clangparser.cpp +++ b/src/plugins/projectexplorer/clangparser.cpp @@ -122,6 +122,11 @@ void ClangParser::stdError(const QString &line) IOutputParser::stdError(line); } +Core::Id ClangParser::id() +{ + return Core::Id("ProjectExplorer.OutputParser.Clang"); +} + // Unit tests: #ifdef WITH_TESTS diff --git a/src/plugins/projectexplorer/clangparser.h b/src/plugins/projectexplorer/clangparser.h index 642a1d6177e..b3c559714b9 100644 --- a/src/plugins/projectexplorer/clangparser.h +++ b/src/plugins/projectexplorer/clangparser.h @@ -40,6 +40,8 @@ public: ClangParser(); void stdError(const QString &line); + static Core::Id id(); + private: QRegularExpression m_commandRegExp; QRegularExpression m_inLineRegExp; diff --git a/src/plugins/projectexplorer/customparser.cpp b/src/plugins/projectexplorer/customparser.cpp index d6f96f47dec..34a9833b1d5 100644 --- a/src/plugins/projectexplorer/customparser.cpp +++ b/src/plugins/projectexplorer/customparser.cpp @@ -140,6 +140,11 @@ void CustomParser::setSettings(const CustomParserSettings &settings) m_warning = settings.warning; } +Core::Id CustomParser::id() +{ + return Core::Id("ProjectExplorer.OutputParser.Custom"); +} + bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel, const CustomParserExpression &expression, Task::TaskType taskType) { diff --git a/src/plugins/projectexplorer/customparser.h b/src/plugins/projectexplorer/customparser.h index a9e2c7b29c8..e1490baeabc 100644 --- a/src/plugins/projectexplorer/customparser.h +++ b/src/plugins/projectexplorer/customparser.h @@ -91,6 +91,8 @@ public: void setSettings(const CustomParserSettings &settings); + static Core::Id id(); + private: bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel, const CustomParserExpression &expression, Task::TaskType taskType); diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp index f0b68c1e903..06a3b041e89 100644 --- a/src/plugins/projectexplorer/customtoolchain.cpp +++ b/src/plugins/projectexplorer/customtoolchain.cpp @@ -83,7 +83,7 @@ static const char warningExampleKeyC[] = "ProjectExplorer.CustomToolChain.Warnin CustomToolChain::CustomToolChain(Detection d) : ToolChain(Constants::CUSTOM_TOOLCHAIN_TYPEID, d), - m_outputParser(Gcc) + m_outputParserId(GccParser::id()) { } CustomToolChain::CustomToolChain(Core::Id language, Detection d) : CustomToolChain(d) @@ -222,16 +222,17 @@ FileNameList CustomToolChain::suggestedMkspecList() const IOutputParser *CustomToolChain::outputParser() const { - switch (m_outputParser) { - case Gcc: return new GccParser; - case Clang: return new ClangParser; - case LinuxIcc: return new LinuxIccParser; -#if defined(Q_OS_WIN) - case Msvc: return new MsvcParser; -#endif - case Custom: return new CustomParser(m_customParserSettings); - default: return nullptr; - } + if (m_outputParserId == GccParser::id()) + return new GccParser; + if (m_outputParserId == ClangParser::id()) + return new ClangParser; + if (m_outputParserId == LinuxIccParser::id()) + return new LinuxIccParser; + if (m_outputParserId == MsvcParser::id()) + return new MsvcParser; + if (m_outputParserId == CustomParser::id()) + return new CustomParser(m_customParserSettings); + return nullptr; } QStringList CustomToolChain::headerPathsList() const @@ -326,7 +327,7 @@ QVariantMap CustomToolChain::toMap() const data.insert(QLatin1String(headerPathsKeyC), headerPathsList()); data.insert(QLatin1String(cxx11FlagsKeyC), m_cxx11Flags); data.insert(QLatin1String(mkspecsKeyC), mkspecs()); - data.insert(QLatin1String(outputParserKeyC), m_outputParser); + data.insert(QLatin1String(outputParserKeyC), m_outputParserId.toSetting()); data.insert(QLatin1String(errorPatternKeyC), m_customParserSettings.error.pattern()); data.insert(QLatin1String(errorFileNameCapKeyC), m_customParserSettings.error.fileNameCap()); data.insert(QLatin1String(errorLineNumberCapKeyC), m_customParserSettings.error.lineNumberCap()); @@ -355,7 +356,7 @@ bool CustomToolChain::fromMap(const QVariantMap &data) setHeaderPaths(data.value(QLatin1String(headerPathsKeyC)).toStringList()); m_cxx11Flags = data.value(QLatin1String(cxx11FlagsKeyC)).toStringList(); setMkspecs(data.value(QLatin1String(mkspecsKeyC)).toString()); - m_outputParser = (OutputParser)data.value(QLatin1String(outputParserKeyC)).toInt(); + setOutputParserId(Core::Id::fromSetting(data.value(QLatin1String(outputParserKeyC)))); m_customParserSettings.error.setPattern(data.value(QLatin1String(errorPatternKeyC)).toString()); m_customParserSettings.error.setFileNameCap(data.value(QLatin1String(errorFileNameCapKeyC)).toInt()); m_customParserSettings.error.setLineNumberCap(data.value(QLatin1String(errorLineNumberCapKeyC)).toInt()); @@ -371,8 +372,6 @@ bool CustomToolChain::fromMap(const QVariantMap &data) static_cast(data.value(QLatin1String(warningChannelKeyC)).toInt())); m_customParserSettings.warning.setExample(data.value(QLatin1String(warningExampleKeyC)).toString()); - QTC_ASSERT(m_outputParser >= Gcc && m_outputParser < OutputParserCount, return false); - return true; } @@ -389,16 +388,51 @@ bool CustomToolChain::operator ==(const ToolChain &other) const && m_systemHeaderPaths == customTc->m_systemHeaderPaths; } -CustomToolChain::OutputParser CustomToolChain::outputParserType() const +Core::Id CustomToolChain::outputParserId() const { - return m_outputParser; + return m_outputParserId; } -void CustomToolChain::setOutputParserType(CustomToolChain::OutputParser parser) +static Core::Id convertLegacySettings(Core::Id parserId) { - if (m_outputParser == parser) + enum OutputParser + { + Gcc = 0, + Clang = 1, + LinuxIcc = 2, + Msvc = 3, + Custom = 4, + OutputParserCount + }; + + bool ok; + const OutputParser index = static_cast(parserId.toString().toInt(&ok)); + if (!ok) + return parserId; + + switch (index) { + case Gcc: + return GccParser::id(); + case Clang: + return ClangParser::id(); + case LinuxIcc: + return LinuxIccParser::id(); + case Msvc: + return HostOsInfo::isWindowsHost() ? MsvcParser::id() : CustomParser::id(); + case Custom: + return CustomParser::id(); + default: + return parserId; + } +} + +void CustomToolChain::setOutputParserId(Core::Id parserId) +{ + parserId = convertLegacySettings(parserId); + + if (m_outputParserId == parserId) return; - m_outputParser = parser; + m_outputParserId = parserId; toolChainUpdated(); } @@ -415,18 +449,16 @@ void CustomToolChain::setCustomParserSettings(const CustomParserSettings &settin toolChainUpdated(); } -QString CustomToolChain::parserName(CustomToolChain::OutputParser parser) +QList CustomToolChain::parsers() { - switch (parser) { - case Gcc: return tr("GCC"); - case Clang: return tr("Clang"); - case LinuxIcc: return tr("ICC"); -#if defined(Q_OS_WIN) - case Msvc: return tr("MSVC"); -#endif - case Custom: return tr("Custom"); - default: return QString(); - } + QList result; + result.append({GccParser::id(), tr("GCC")}); + result.append({ClangParser::id(), tr("Clang")}); + result.append({LinuxIccParser::id(), tr("ICC")}); + result.append({MsvcParser::id(), tr("MSVC")}); + result.append({CustomParser::id(), tr("Custom")}); + + return result; } ToolChainConfigWidget *CustomToolChain::configurationWidget() @@ -536,8 +568,9 @@ CustomToolChainConfigWidget::CustomToolChainConfigWidget(CustomToolChain *tc) : { Q_ASSERT(tc); - for (int i = 0; i < CustomToolChain::OutputParserCount; ++i) - m_errorParserComboBox->addItem(CustomToolChain::parserName((CustomToolChain::OutputParser)i)); + const QList parsers = CustomToolChain::parsers(); + for (auto parser : parsers) + m_errorParserComboBox->addItem(parser.displayName, parser.parserId.toString()); auto parserLayoutWidget = new QWidget; auto parserLayout = new QHBoxLayout(parserLayoutWidget); @@ -581,7 +614,7 @@ CustomToolChainConfigWidget::CustomToolChainConfigWidget(CustomToolChain *tc) : this, &CustomToolChainConfigWidget::errorParserChanged); connect(m_customParserSettingsButton, &QAbstractButton::clicked, this, &CustomToolChainConfigWidget::openCustomParserSettingsDialog); - errorParserChanged(m_errorParserComboBox->currentIndex()); + errorParserChanged(); } void CustomToolChainConfigWidget::updateSummaries() @@ -593,9 +626,10 @@ void CustomToolChainConfigWidget::updateSummaries() emit dirty(); } -void CustomToolChainConfigWidget::errorParserChanged(int index) +void CustomToolChainConfigWidget::errorParserChanged(int ) { - m_customParserSettingsButton->setEnabled(index == m_errorParserComboBox->count() - 1); + const auto currentId = Core::Id::fromSetting(m_errorParserComboBox->currentData()); + m_customParserSettingsButton->setEnabled(currentId == CustomParser::id()); emit dirty(); } @@ -627,7 +661,7 @@ void CustomToolChainConfigWidget::applyImpl() tc->setCxx11Flags(m_cxx11Flags->text().split(QLatin1Char(','))); tc->setMkspecs(m_mkspecs->text()); tc->setDisplayName(displayName); // reset display name - tc->setOutputParserType((CustomToolChain::OutputParser)m_errorParserComboBox->currentIndex()); + tc->setOutputParserId(Core::Id::fromSetting(m_errorParserComboBox->currentData())); tc->setCustomParserSettings(m_customParserSettings); } @@ -643,7 +677,8 @@ void CustomToolChainConfigWidget::setFromToolchain() m_headerPaths->setPlainText(tc->headerPathsList().join(QLatin1Char('\n'))); m_cxx11Flags->setText(tc->cxx11Flags().join(QLatin1Char(','))); m_mkspecs->setText(tc->mkspecs()); - m_errorParserComboBox->setCurrentIndex(tc->outputParserType()); + int index = m_errorParserComboBox->findData(tc->outputParserId().toSetting()); + m_errorParserComboBox->setCurrentIndex(index); m_customParserSettings = tc->customParserSettings(); blockSignals(blocked); } @@ -659,7 +694,7 @@ bool CustomToolChainConfigWidget::isDirtyImpl() const || m_headerDetails->entries() != tc->headerPathsList() || m_cxx11Flags->text().split(QLatin1Char(',')) != tc->cxx11Flags() || m_mkspecs->text() != tc->mkspecs() - || m_errorParserComboBox->currentIndex() == tc->outputParserType() + || Core::Id::fromSetting(m_errorParserComboBox->currentData()) == tc->outputParserId() || m_customParserSettings != tc->customParserSettings(); } diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h index a1dfe319bde..fa5ec68ed01 100644 --- a/src/plugins/projectexplorer/customtoolchain.h +++ b/src/plugins/projectexplorer/customtoolchain.h @@ -59,16 +59,10 @@ class PROJECTEXPLORER_EXPORT CustomToolChain : public ToolChain Q_DECLARE_TR_FUNCTIONS(CustomToolChain) public: - enum OutputParser - { - Gcc = 0, - Clang = 1, - LinuxIcc = 2, -#if defined(Q_OS_WIN) - Msvc = 3, -#endif - Custom, - OutputParserCount + class Parser { + public: + Core::Id parserId; ///< A unique id identifying a parser + QString displayName; ///< A translateable name to show in the user interface }; QString typeDisplayName() const override; @@ -113,11 +107,11 @@ public: ToolChain *clone() const override; - OutputParser outputParserType() const; - void setOutputParserType(OutputParser parser); + Core::Id outputParserId() const; + void setOutputParserId(Core::Id parserId); CustomParserSettings customParserSettings() const; void setCustomParserSettings(const CustomParserSettings &settings); - static QString parserName(OutputParser parser); + static QList parsers(); protected: CustomToolChain(const CustomToolChain &) = default; @@ -135,7 +129,7 @@ private: QStringList m_cxx11Flags; Utils::FileNameList m_mkspecs; - OutputParser m_outputParser; + Core::Id m_outputParserId; CustomParserSettings m_customParserSettings; friend class Internal::CustomToolChainFactory; @@ -175,7 +169,7 @@ public: private: void updateSummaries(); - void errorParserChanged(int index); + void errorParserChanged(int index = -1); void openCustomParserSettingsDialog(); protected: diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp index 1d3f510baff..bbc27aeb556 100644 --- a/src/plugins/projectexplorer/gccparser.cpp +++ b/src/plugins/projectexplorer/gccparser.cpp @@ -144,6 +144,11 @@ void GccParser::stdOutput(const QString &line) IOutputParser::stdOutput(line); } +Core::Id GccParser::id() +{ + return Core::Id("ProjectExplorer.OutputParser.Gcc"); +} + void GccParser::newTask(const Task &task) { doFlush(); diff --git a/src/plugins/projectexplorer/gccparser.h b/src/plugins/projectexplorer/gccparser.h index 441122f1c7b..87381a2bbcb 100644 --- a/src/plugins/projectexplorer/gccparser.h +++ b/src/plugins/projectexplorer/gccparser.h @@ -43,6 +43,8 @@ public: void stdError(const QString &line) override; void stdOutput(const QString &line) override; + static Core::Id id(); + protected: void newTask(const Task &task); void doFlush() override; diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp index 4e64f56b3ce..04dbb6c65f1 100644 --- a/src/plugins/projectexplorer/linuxiccparser.cpp +++ b/src/plugins/projectexplorer/linuxiccparser.cpp @@ -116,6 +116,11 @@ void LinuxIccParser::stdError(const QString &line) } } +Core::Id LinuxIccParser::id() +{ + return Core::Id("ProjectExplorer.OutputParser.Icc"); +} + void LinuxIccParser::doFlush() { if (m_temporary.isNull()) diff --git a/src/plugins/projectexplorer/linuxiccparser.h b/src/plugins/projectexplorer/linuxiccparser.h index bfb57d850c0..8697869cd72 100644 --- a/src/plugins/projectexplorer/linuxiccparser.h +++ b/src/plugins/projectexplorer/linuxiccparser.h @@ -41,6 +41,8 @@ public: void stdError(const QString &line) override; + static Core::Id id(); + private: void doFlush() override; diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp index ae7a621f921..df20b5da00b 100644 --- a/src/plugins/projectexplorer/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -168,6 +168,11 @@ void MsvcParser::stdError(const QString &line) IOutputParser::stdError(line); } +Core::Id MsvcParser::id() +{ + return Core::Id("ProjectExplorer.OutputParser.Msvc"); +} + bool MsvcParser::processCompileLine(const QString &line) { doFlush(); diff --git a/src/plugins/projectexplorer/msvcparser.h b/src/plugins/projectexplorer/msvcparser.h index 09bae9eaa76..d06e176c58a 100644 --- a/src/plugins/projectexplorer/msvcparser.h +++ b/src/plugins/projectexplorer/msvcparser.h @@ -43,6 +43,8 @@ public: void stdOutput(const QString &line) override; void stdError(const QString &line) override; + static Core::Id id(); + private: void doFlush() override; bool processCompileLine(const QString &line);