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 <tobias.hunger@qt.io>
This commit is contained in:
Andre Hartmann
2017-04-14 21:45:41 +02:00
committed by André Hartmann
parent e19620ddd5
commit 2ff642d8e4
12 changed files with 118 additions and 54 deletions

View File

@@ -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

View File

@@ -40,6 +40,8 @@ public:
ClangParser();
void stdError(const QString &line);
static Core::Id id();
private:
QRegularExpression m_commandRegExp;
QRegularExpression m_inLineRegExp;

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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<CustomParserExpression::CustomParserChannel>(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<OutputParser>(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::Parser> 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<CustomToolChain::Parser> 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<CustomToolChain::Parser> 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();
}

View File

@@ -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<CustomToolChain::Parser> 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:

View File

@@ -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();

View File

@@ -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;

View File

@@ -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())

View File

@@ -41,6 +41,8 @@ public:
void stdError(const QString &line) override;
static Core::Id id();
private:
void doFlush() override;

View File

@@ -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();

View File

@@ -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);