ProjectExplorer: Allow to add custom output parsers programatically

This enables plugins to add custom parsers to the global pool.

Fixes: QTCREATORBUG-24403
Change-Id: Id600c12fc66876879a5a2975139d72f87c4f2e30
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2020-07-30 14:54:10 +02:00
parent 996f490e97
commit 4bbf76a344
6 changed files with 83 additions and 62 deletions

View File

@@ -59,7 +59,6 @@ const char channelKey[] = "Channel";
const char exampleKey[] = "Example"; const char exampleKey[] = "Example";
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal {
bool CustomParserExpression::operator ==(const CustomParserExpression &other) const bool CustomParserExpression::operator ==(const CustomParserExpression &other) const
{ {
@@ -177,6 +176,33 @@ void CustomParserSettings::fromMap(const QVariantMap &map)
warning.fromMap(map.value(warningKey).toMap()); warning.fromMap(map.value(warningKey).toMap());
} }
CustomParsersAspect::CustomParsersAspect(Target *target)
{
Q_UNUSED(target)
setId("CustomOutputParsers");
setSettingsKey("CustomOutputParsers");
setDisplayName(tr("Custom Output Parsers"));
setConfigWidgetCreator([this] {
const auto widget = new Internal::CustomParsersSelectionWidget;
widget->setSelectedParsers(m_parsers);
connect(widget, &Internal::CustomParsersSelectionWidget::selectionChanged,
this, [this, widget] { m_parsers = widget->selectedParsers(); });
return widget;
});
}
void CustomParsersAspect::fromMap(const QVariantMap &map)
{
m_parsers = transform(map.value(settingsKey()).toList(), &Utils::Id::fromSetting);
}
void CustomParsersAspect::toMap(QVariantMap &map) const
{
map.insert(settingsKey(), transform(m_parsers, &Utils::Id::toSetting));
}
namespace Internal {
CustomParser::CustomParser(const CustomParserSettings &settings) CustomParser::CustomParser(const CustomParserSettings &settings)
{ {
setObjectName("CustomParser"); setObjectName("CustomParser");
@@ -192,8 +218,8 @@ void CustomParser::setSettings(const CustomParserSettings &settings)
CustomParser *CustomParser::createFromId(Utils::Id id) CustomParser *CustomParser::createFromId(Utils::Id id)
{ {
const Internal::CustomParserSettings parser = findOrDefault(ProjectExplorerPlugin::customParsers(), const CustomParserSettings parser = findOrDefault(ProjectExplorerPlugin::customParsers(),
[id](const Internal::CustomParserSettings &p) { return p.id == id; }); [id](const CustomParserSettings &p) { return p.id == id; });
if (parser.id.isValid()) if (parser.id.isValid())
return new CustomParser(parser); return new CustomParser(parser);
return nullptr; return nullptr;
@@ -347,31 +373,6 @@ void CustomParsersSelectionWidget::updateSummary()
setSummaryText(tr("There are %n custom parsers active", nullptr, parsers.count())); setSummaryText(tr("There are %n custom parsers active", nullptr, parsers.count()));
} }
CustomParsersAspect::CustomParsersAspect(Target *target)
{
Q_UNUSED(target)
setId("CustomOutputParsers");
setSettingsKey("CustomOutputParsers");
setDisplayName(tr("Custom Output Parsers"));
setConfigWidgetCreator([this] {
const auto widget = new CustomParsersSelectionWidget;
widget->setSelectedParsers(m_parsers);
connect(widget, &CustomParsersSelectionWidget::selectionChanged,
this, [this, widget] { m_parsers = widget->selectedParsers(); });
return widget;
});
}
void CustomParsersAspect::fromMap(const QVariantMap &map)
{
m_parsers = transform(map.value(settingsKey()).toList(), &Utils::Id::fromSetting);
}
void CustomParsersAspect::toMap(QVariantMap &map) const
{
map.insert(settingsKey(), transform(m_parsers, &Utils::Id::toSetting));
}
} // namespace Internal } // namespace Internal
// Unit tests: // Unit tests:

View File

@@ -37,9 +37,7 @@
namespace ProjectExplorer { namespace ProjectExplorer {
class Target; class Target;
namespace Internal { class PROJECTEXPLORER_EXPORT CustomParserExpression
class CustomParserExpression
{ {
public: public:
enum CustomParserChannel { enum CustomParserChannel {
@@ -80,7 +78,7 @@ private:
int m_messageCap = 3; int m_messageCap = 3;
}; };
class CustomParserSettings class PROJECTEXPLORER_EXPORT CustomParserSettings
{ {
public: public:
bool operator ==(const CustomParserSettings &other) const; bool operator ==(const CustomParserSettings &other) const;
@@ -95,6 +93,24 @@ public:
CustomParserExpression warning; CustomParserExpression warning;
}; };
class PROJECTEXPLORER_EXPORT CustomParsersAspect : public ProjectConfigurationAspect
{
Q_OBJECT
public:
CustomParsersAspect(Target *target);
void setParsers(const QList<Utils::Id> &parsers) { m_parsers = parsers; }
const QList<Utils::Id> parsers() const { return m_parsers; }
private:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
QList<Utils::Id> m_parsers;
};
namespace Internal {
class CustomParser : public ProjectExplorer::OutputTaskParser class CustomParser : public ProjectExplorer::OutputTaskParser
{ {
public: public:
@@ -132,23 +148,7 @@ private:
void updateSummary(); void updateSummary();
}; };
class CustomParsersAspect : public ProjectConfigurationAspect
{
Q_OBJECT
public:
CustomParsersAspect(Target *target);
void setParsers(const QList<Utils::Id> &parsers) { m_parsers = parsers; }
const QList<Utils::Id> parsers() const { return m_parsers; }
private:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
QList<Utils::Id> m_parsers;
};
} // namespace Internal } // namespace Internal
} // namespace ProjectExplorer } // namespace ProjectExplorer
Q_DECLARE_METATYPE(ProjectExplorer::Internal::CustomParserExpression::CustomParserChannel); Q_DECLARE_METATYPE(ProjectExplorer::CustomParserExpression::CustomParserChannel);

View File

@@ -77,10 +77,10 @@ CustomToolChain::CustomToolChain() :
setTypeDisplayName(tr("Custom")); setTypeDisplayName(tr("Custom"));
} }
Internal::CustomParserSettings CustomToolChain::customParserSettings() const CustomParserSettings CustomToolChain::customParserSettings() const
{ {
return findOrDefault(ProjectExplorerPlugin::customParsers(), return findOrDefault(ProjectExplorerPlugin::customParsers(),
[this](const Internal::CustomParserSettings &s) { [this](const CustomParserSettings &s) {
return s.id == outputParserId(); return s.id == outputParserId();
}); });
} }
@@ -310,7 +310,7 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
// Restore Pre-4.13 settings. // Restore Pre-4.13 settings.
if (outputParserId() == Internal::CustomParser::id()) { if (outputParserId() == Internal::CustomParser::id()) {
Internal::CustomParserSettings customParserSettings; CustomParserSettings customParserSettings;
customParserSettings.error.setPattern( customParserSettings.error.setPattern(
data.value("ProjectExplorer.CustomToolChain.ErrorPattern").toString()); data.value("ProjectExplorer.CustomToolChain.ErrorPattern").toString());
customParserSettings.error.setFileNameCap( customParserSettings.error.setFileNameCap(
@@ -320,7 +320,7 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
customParserSettings.error.setMessageCap( customParserSettings.error.setMessageCap(
data.value("ProjectExplorer.CustomToolChain.ErrorMessageCap").toInt()); data.value("ProjectExplorer.CustomToolChain.ErrorMessageCap").toInt());
customParserSettings.error.setChannel( customParserSettings.error.setChannel(
static_cast<Internal::CustomParserExpression::CustomParserChannel>( static_cast<CustomParserExpression::CustomParserChannel>(
data.value("ProjectExplorer.CustomToolChain.ErrorChannel").toInt())); data.value("ProjectExplorer.CustomToolChain.ErrorChannel").toInt()));
customParserSettings.error.setExample( customParserSettings.error.setExample(
data.value("ProjectExplorer.CustomToolChain.ErrorExample").toString()); data.value("ProjectExplorer.CustomToolChain.ErrorExample").toString());
@@ -333,7 +333,7 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
customParserSettings.warning.setMessageCap( customParserSettings.warning.setMessageCap(
data.value("ProjectExplorer.CustomToolChain.WarningMessageCap").toInt()); data.value("ProjectExplorer.CustomToolChain.WarningMessageCap").toInt());
customParserSettings.warning.setChannel( customParserSettings.warning.setChannel(
static_cast<Internal::CustomParserExpression::CustomParserChannel>( static_cast<CustomParserExpression::CustomParserChannel>(
data.value("ProjectExplorer.CustomToolChain.WarningChannel").toInt())); data.value("ProjectExplorer.CustomToolChain.WarningChannel").toInt()));
customParserSettings.warning.setExample( customParserSettings.warning.setExample(
data.value("ProjectExplorer.CustomToolChain.WarningExample").toString()); data.value("ProjectExplorer.CustomToolChain.WarningExample").toString());
@@ -343,8 +343,7 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
customParserSettings.id = Utils::Id::fromString(QUuid::createUuid().toString()); customParserSettings.id = Utils::Id::fromString(QUuid::createUuid().toString());
setOutputParserId(customParserSettings.id); setOutputParserId(customParserSettings.id);
customParserSettings.displayName = tr("Parser for toolchain %1").arg(displayName()); customParserSettings.displayName = tr("Parser for toolchain %1").arg(displayName());
QList<Internal::CustomParserSettings> settings QList<CustomParserSettings> settings = ProjectExplorerPlugin::customParsers();
= ProjectExplorerPlugin::customParsers();
settings << customParserSettings; settings << customParserSettings;
ProjectExplorerPlugin::setCustomParsers(settings); ProjectExplorerPlugin::setCustomParsers(settings);
} }
@@ -476,7 +475,7 @@ CustomToolChainConfigWidget::CustomToolChainConfigWidget(CustomToolChain *tc) :
const QList<CustomToolChain::Parser> parsers = CustomToolChain::parsers(); const QList<CustomToolChain::Parser> parsers = CustomToolChain::parsers();
for (const auto &parser : parsers) for (const auto &parser : parsers)
m_errorParserComboBox->addItem(parser.displayName, parser.parserId.toString()); m_errorParserComboBox->addItem(parser.displayName, parser.parserId.toString());
for (const Internal::CustomParserSettings &s : ProjectExplorerPlugin::customParsers()) for (const CustomParserSettings &s : ProjectExplorerPlugin::customParsers())
m_errorParserComboBox->addItem(s.displayName, s.id.toString()); m_errorParserComboBox->addItem(s.displayName, s.id.toString());
auto parserLayoutWidget = new QWidget; auto parserLayoutWidget = new QWidget;

View File

@@ -112,7 +112,7 @@ public:
private: private:
CustomToolChain(); CustomToolChain();
Internal::CustomParserSettings customParserSettings() const; CustomParserSettings customParserSettings() const;
Utils::FilePath m_compilerCommand; Utils::FilePath m_compilerCommand;
Utils::FilePath m_makeCommand; Utils::FilePath m_makeCommand;

View File

@@ -555,7 +555,7 @@ public:
MiniProjectTargetSelector * m_targetSelector; MiniProjectTargetSelector * m_targetSelector;
ProjectExplorerSettings m_projectExplorerSettings; ProjectExplorerSettings m_projectExplorerSettings;
BuildPropertiesSettings m_buildPropertiesSettings; BuildPropertiesSettings m_buildPropertiesSettings;
QList<Internal::CustomParserSettings> m_customParsers; QList<CustomParserSettings> m_customParsers;
bool m_shouldHaveRunConfiguration = false; bool m_shouldHaveRunConfiguration = false;
bool m_shuttingDown = false; bool m_shuttingDown = false;
Utils::Id m_runMode = Constants::NO_RUN_MODE; Utils::Id m_runMode = Constants::NO_RUN_MODE;
@@ -3897,6 +3897,25 @@ void ProjectExplorerPlugin::setCustomParsers(const QList<CustomParserSettings> &
} }
} }
void ProjectExplorerPlugin::addCustomParser(const CustomParserSettings &settings)
{
QTC_ASSERT(settings.id.isValid(), return);
QTC_ASSERT(!contains(dd->m_customParsers, [&settings](const CustomParserSettings &s) {
return s.id == settings.id;
}), return);
dd->m_customParsers << settings;
emit m_instance->customParsersChanged();
}
void ProjectExplorerPlugin::removeCustomParser(Id id)
{
erase(dd->m_customParsers, [id](const CustomParserSettings &s) {
return s.id == id;
});
emit m_instance->customParsersChanged();
}
const QList<CustomParserSettings> ProjectExplorerPlugin::customParsers() const QList<CustomParserSettings> ProjectExplorerPlugin::customParsers()
{ {
return dd->m_customParsers; return dd->m_customParsers;

View File

@@ -49,6 +49,7 @@ class FilePath;
namespace ProjectExplorer { namespace ProjectExplorer {
class BuildPropertiesSettings; class BuildPropertiesSettings;
class CustomParserSettings;
class RunControl; class RunControl;
class RunConfiguration; class RunConfiguration;
class Project; class Project;
@@ -58,7 +59,6 @@ class FileNode;
namespace Internal { namespace Internal {
class AppOutputSettings; class AppOutputSettings;
class CustomParserSettings;
class MiniProjectTargetSelector; class MiniProjectTargetSelector;
class ProjectExplorerSettings; class ProjectExplorerSettings;
} }
@@ -141,8 +141,10 @@ public:
static const BuildPropertiesSettings &buildPropertiesSettings(); static const BuildPropertiesSettings &buildPropertiesSettings();
static void showQtSettings(); static void showQtSettings();
static void setCustomParsers(const QList<Internal::CustomParserSettings> &settings); static void setCustomParsers(const QList<CustomParserSettings> &settings);
static const QList<Internal::CustomParserSettings> customParsers(); static void addCustomParser(const CustomParserSettings &settings);
static void removeCustomParser(Utils::Id id);
static const QList<CustomParserSettings> customParsers();
static void startRunControl(RunControl *runControl); static void startRunControl(RunControl *runControl);
static void showOutputPaneForRunControl(RunControl *runControl); static void showOutputPaneForRunControl(RunControl *runControl);