forked from qt-creator/qt-creator
Utils/all: Create an OutputFormatterFactory
Essentially following the scheme used for the various project configurations. This makes it possible to construct OutputFormatters by Id only, potentially reducing hard plugin dependencies and opening the road to have several output formatters per RunConfiguration/Outputpane/... Change-Id: I4b5fb6fb6be8b0d9a0859f178bb0effc3398b09e Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -35,7 +35,6 @@
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <utils/detailswidget.h>
|
||||
@@ -133,7 +132,6 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Core::Id id)
|
||||
postStartShellCmdAspect->setSettingsKey("Android.PostStartShellCmdListKey");
|
||||
postStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device after application quits."));
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
connect(target->project(), &Project::parsingFinished, this, [this] {
|
||||
updateTargetInformation();
|
||||
});
|
||||
|
@@ -33,8 +33,6 @@
|
||||
#include <projectexplorer/runconfigurationaspects.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
|
||||
#include <remotelinux/remotelinuxenvironmentaspect.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
@@ -87,8 +85,6 @@ QdbRunConfiguration::QdbRunConfiguration(Target *target, Core::Id id)
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<FullCommandLineAspect>(this);
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
|
||||
connect(target, &Target::deploymentDataChanged,
|
||||
this, &QdbRunConfiguration::updateTargetInformation);
|
||||
connect(target, &Target::applicationTargetsChanged,
|
||||
|
@@ -39,7 +39,6 @@
|
||||
#include <projectexplorer/runconfigurationaspects.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
@@ -114,8 +113,6 @@ IosRunConfiguration::IosRunConfiguration(Target *target, Core::Id id)
|
||||
addAspect<ArgumentsAspect>();
|
||||
|
||||
m_deviceTypeAspect = addAspect<IosDeviceTypeAspect>(this);
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
}
|
||||
|
||||
void IosDeviceTypeAspect::deviceChanges()
|
||||
|
@@ -406,14 +406,6 @@ Runnable RunConfiguration::runnable() const
|
||||
return r;
|
||||
}
|
||||
|
||||
OutputFormatter *RunConfiguration::createOutputFormatter() const
|
||||
{
|
||||
if (m_outputFormatterCreator)
|
||||
return m_outputFormatterCreator(project());
|
||||
return new OutputFormatter();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\class ProjectExplorer::IRunConfigurationFactory
|
||||
|
||||
|
@@ -180,11 +180,6 @@ protected:
|
||||
/// convenience function to get current build configuration.
|
||||
BuildConfiguration *activeBuildConfiguration() const;
|
||||
|
||||
template<class T> void setOutputFormatter()
|
||||
{
|
||||
m_outputFormatterCreator = [](Project *project) { return new T(project); };
|
||||
}
|
||||
|
||||
virtual void updateEnabledState();
|
||||
virtual void doAdditionalSetup(const RunConfigurationCreationInfo &) {}
|
||||
|
||||
@@ -195,7 +190,6 @@ private:
|
||||
|
||||
QString m_buildKey;
|
||||
bool m_isEnabled = false;
|
||||
std::function<Utils::OutputFormatter *(Project *)> m_outputFormatterCreator;
|
||||
CommandLineGetter m_commandLineGetter;
|
||||
};
|
||||
|
||||
|
@@ -326,11 +326,7 @@ void RunControl::setRunConfiguration(RunConfiguration *runConfig)
|
||||
d->runConfiguration = runConfig;
|
||||
d->runConfigId = runConfig->id();
|
||||
d->runnable = runConfig->runnable();
|
||||
d->displayName = runConfig->displayName();
|
||||
if (auto outputFormatter = runConfig->createOutputFormatter()) {
|
||||
delete d->outputFormatter;
|
||||
d->outputFormatter = outputFormatter;
|
||||
}
|
||||
d->displayName = runConfig->displayName();
|
||||
d->macroExpander = runConfig->macroExpander();
|
||||
setTarget(runConfig->target());
|
||||
}
|
||||
@@ -340,6 +336,12 @@ void RunControl::setTarget(Target *target)
|
||||
QTC_ASSERT(target, return);
|
||||
QTC_CHECK(!d->target);
|
||||
d->target = target;
|
||||
|
||||
delete d->outputFormatter;
|
||||
d->outputFormatter = OutputFormatterFactory::createFormatter(target);
|
||||
if (!d->outputFormatter)
|
||||
d->outputFormatter = new OutputFormatter();
|
||||
|
||||
setKit(target->kit());
|
||||
d->project = target->project();
|
||||
}
|
||||
@@ -1557,4 +1559,37 @@ void Runnable::setCommandLine(const CommandLine &cmdLine)
|
||||
commandLineArguments = cmdLine.arguments();
|
||||
}
|
||||
|
||||
// OutputFormatterFactory
|
||||
|
||||
static QList<OutputFormatterFactory *> g_outputFormatterFactories;
|
||||
|
||||
OutputFormatterFactory::OutputFormatterFactory()
|
||||
{
|
||||
// This is a bit cheating: We know that only two formatters exist right now,
|
||||
// and this here gives the second (python) implicit more priority.
|
||||
// For a final solution, probably all matching formatters should be used
|
||||
// in parallel, so there's no need to invent a fancy priority system here.
|
||||
g_outputFormatterFactories.prepend(this);
|
||||
}
|
||||
|
||||
OutputFormatterFactory::~OutputFormatterFactory()
|
||||
{
|
||||
g_outputFormatterFactories.removeOne(this);
|
||||
}
|
||||
|
||||
OutputFormatter *OutputFormatterFactory::createFormatter(Target *target)
|
||||
{
|
||||
for (auto factory : qAsConst(g_outputFormatterFactories)) {
|
||||
if (auto formatter = factory->m_creator(target))
|
||||
return formatter;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OutputFormatterFactory::setFormatterCreator
|
||||
(const std::function<OutputFormatter *(Target *)> &creator)
|
||||
{
|
||||
m_creator = creator;
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -309,4 +309,21 @@ private:
|
||||
bool m_useTerminal = false;
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT OutputFormatterFactory
|
||||
{
|
||||
protected:
|
||||
OutputFormatterFactory();
|
||||
|
||||
public:
|
||||
virtual ~OutputFormatterFactory();
|
||||
|
||||
static Utils::OutputFormatter *createFormatter(Target *target);
|
||||
|
||||
protected:
|
||||
void setFormatterCreator(const std::function<Utils::OutputFormatter *(Target *)> &creator);
|
||||
|
||||
private:
|
||||
std::function<Utils::OutputFormatter *(Target *)> m_creator;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -147,7 +147,7 @@ static QTextCharFormat linkFormat(const QTextCharFormat &inputFormat, const QStr
|
||||
class PythonOutputFormatter : public OutputFormatter
|
||||
{
|
||||
public:
|
||||
PythonOutputFormatter(Project *)
|
||||
PythonOutputFormatter()
|
||||
// Note that moc dislikes raw string literals.
|
||||
: filePattern("^(\\s*)(File \"([^\"]+)\", line (\\d+), .*$)")
|
||||
{
|
||||
@@ -217,6 +217,19 @@ private:
|
||||
const QRegularExpression filePattern;
|
||||
};
|
||||
|
||||
class PythonOutputFormatterFactory : public OutputFormatterFactory
|
||||
{
|
||||
public:
|
||||
PythonOutputFormatterFactory()
|
||||
{
|
||||
setFormatterCreator([](Target *t) -> OutputFormatter * {
|
||||
if (t->project()->mimeType() == Constants::C_PY_MIMETYPE)
|
||||
return new PythonOutputFormatter;
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class InterpreterAspect : public ProjectConfigurationAspect
|
||||
@@ -370,7 +383,6 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Core::Id id)
|
||||
|
||||
addAspect<TerminalAspect>();
|
||||
|
||||
setOutputFormatter<PythonOutputFormatter>();
|
||||
setCommandLineGetter([this, interpreterAspect, argumentsAspect] {
|
||||
CommandLine cmd{interpreterAspect->currentInterpreter().command, {mainScript()}};
|
||||
cmd.addArgs(argumentsAspect->arguments(macroExpander()), CommandLine::Raw);
|
||||
@@ -810,7 +822,9 @@ class PythonPluginPrivate
|
||||
{
|
||||
public:
|
||||
PythonEditorFactory editorFactory;
|
||||
PythonOutputFormatterFactory outputFormatterFactory;
|
||||
PythonRunConfigurationFactory runConfigFactory;
|
||||
|
||||
RunWorkerFactory runWorkerFactory{
|
||||
RunWorkerFactory::make<SimpleTargetRunner>(),
|
||||
{ProjectExplorer::Constants::NORMAL_RUN_MODE},
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
#include <qtsupport/qtsupportconstants.h>
|
||||
#include <qtsupport/desktopqtversion.h>
|
||||
|
||||
@@ -319,7 +318,6 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
|
||||
connect(m_mainQmlFileAspect, &MainQmlFileAspect::changed,
|
||||
this, &QmlProjectRunConfiguration::updateEnabledState);
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
connect(target, &Target::kitChanged,
|
||||
this, &QmlProjectRunConfiguration::updateEnabledState);
|
||||
|
||||
|
@@ -68,8 +68,6 @@ QnxRunConfiguration::QnxRunConfiguration(Target *target, Core::Id id)
|
||||
libAspect->setLabelText(tr("Path to Qt libraries on device"));
|
||||
libAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
|
||||
auto updateTargetInformation = [this, target, exeAspect, symbolsAspect] {
|
||||
|
||||
BuildTargetInfo bti = buildTargetInfo();
|
||||
|
@@ -98,8 +98,6 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Core::Id id, Ki
|
||||
|
||||
}
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
this, &DesktopRunConfiguration::updateTargetInformation);
|
||||
}
|
||||
|
@@ -25,13 +25,18 @@
|
||||
|
||||
#include "qtoutputformatter.h"
|
||||
|
||||
#include "qtkitinformation.h"
|
||||
#include "qtsupportconstants.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/ansiescapecodehandler.h>
|
||||
#include <utils/fileinprojectfinder.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/outputformatter.h>
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
@@ -44,13 +49,19 @@ using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace QtSupport {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
struct LinkResult
|
||||
{
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
QString href;
|
||||
};
|
||||
|
||||
class QtOutputFormatterPrivate
|
||||
{
|
||||
public:
|
||||
QtOutputFormatterPrivate(Project *proj)
|
||||
QtOutputFormatterPrivate()
|
||||
: qmlError("(" QT_QML_URL_REGEXP // url
|
||||
":\\d+" // colon, line
|
||||
"(?::\\d+)?)" // colon, column (optional)
|
||||
@@ -60,11 +71,6 @@ public:
|
||||
, qtAssertX(QT_ASSERT_X_REGEXP)
|
||||
, qtTestFailUnix(QT_TEST_FAIL_UNIX_REGEXP)
|
||||
, qtTestFailWin(QT_TEST_FAIL_WIN_REGEXP)
|
||||
, project(proj)
|
||||
{
|
||||
}
|
||||
|
||||
~QtOutputFormatterPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -80,16 +86,41 @@ public:
|
||||
QTextCursor cursor;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
QtOutputFormatter::QtOutputFormatter(Project *project)
|
||||
: d(new Internal::QtOutputFormatterPrivate(project))
|
||||
class QtOutputFormatter : public OutputFormatter
|
||||
{
|
||||
if (project) {
|
||||
d->projectFinder.setProjectFiles(project->files(Project::SourceFiles));
|
||||
d->projectFinder.setProjectDirectory(project->projectDirectory());
|
||||
public:
|
||||
explicit QtOutputFormatter(Target *target);
|
||||
~QtOutputFormatter() override;
|
||||
|
||||
connect(project,
|
||||
void appendMessage(const QString &text, Utils::OutputFormat format) override;
|
||||
void handleLink(const QString &href) override;
|
||||
void setPlainTextEdit(QPlainTextEdit *plainText) override;
|
||||
|
||||
protected:
|
||||
void clearLastLine() override;
|
||||
virtual void openEditor(const QString &fileName, int line, int column = -1);
|
||||
|
||||
private:
|
||||
void updateProjectFileList();
|
||||
LinkResult matchLine(const QString &line) const;
|
||||
void appendMessagePart(const QString &txt, const QTextCharFormat &fmt);
|
||||
void appendLine(const LinkResult &lr, const QString &line, Utils::OutputFormat format);
|
||||
void appendLine(const LinkResult &lr, const QString &line, const QTextCharFormat &format);
|
||||
void appendMessage(const QString &text, const QTextCharFormat &format) override;
|
||||
|
||||
QtOutputFormatterPrivate *d;
|
||||
friend class QtSupportPlugin; // for testing
|
||||
};
|
||||
|
||||
QtOutputFormatter::QtOutputFormatter(Target *target)
|
||||
: d(new QtOutputFormatterPrivate)
|
||||
{
|
||||
d->project = target ? target->project() : nullptr;
|
||||
if (d->project) {
|
||||
d->projectFinder.setProjectFiles(d->project->files(Project::SourceFiles));
|
||||
d->projectFinder.setProjectDirectory(d->project->projectDirectory());
|
||||
|
||||
connect(d->project,
|
||||
&Project::fileListChanged,
|
||||
this,
|
||||
&QtOutputFormatter::updateProjectFileList,
|
||||
@@ -308,6 +339,17 @@ void QtOutputFormatter::updateProjectFileList()
|
||||
d->projectFinder.setProjectFiles(d->project->files(Project::SourceFiles));
|
||||
}
|
||||
|
||||
// QtOutputFormatterFactory
|
||||
|
||||
QtOutputFormatterFactory::QtOutputFormatterFactory()
|
||||
{
|
||||
setFormatterCreator([](Target *t) -> OutputFormatter * {
|
||||
BaseQtVersion *qt = QtKitAspect::qtVersion(t->kit());
|
||||
return qt ? new QtOutputFormatter(t) : nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QtSupport
|
||||
|
||||
// Unit tests:
|
||||
|
@@ -25,9 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "qtsupport_global.h"
|
||||
|
||||
#include <utils/outputformatter.h>
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
|
||||
// "file" or "qrc", colon, optional '//', '/' and further characters
|
||||
#define QT_QML_URL_REGEXP "(?:file|qrc):(?://)?/.+?"
|
||||
@@ -36,50 +34,14 @@
|
||||
#define QT_TEST_FAIL_UNIX_REGEXP "^ Loc: \\[((?<file>.+)(?|\\((?<line>\\d+)\\)|:(?<line>\\d+)))\\]$"
|
||||
#define QT_TEST_FAIL_WIN_REGEXP "^((?<file>.+)\\((?<line>\\d+)\\)) : failure location\\s*$"
|
||||
|
||||
namespace ProjectExplorer { class Project; }
|
||||
|
||||
namespace QtSupport {
|
||||
|
||||
struct LinkResult
|
||||
{
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
QString href;
|
||||
};
|
||||
|
||||
namespace Internal {
|
||||
class QtOutputFormatterPrivate;
|
||||
class QtSupportPlugin;
|
||||
}
|
||||
|
||||
class QTSUPPORT_EXPORT QtOutputFormatter : public Utils::OutputFormatter
|
||||
class QtOutputFormatterFactory : public ProjectExplorer::OutputFormatterFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QtOutputFormatter(ProjectExplorer::Project *project);
|
||||
~QtOutputFormatter() override;
|
||||
|
||||
void appendMessage(const QString &text, Utils::OutputFormat format) override;
|
||||
void handleLink(const QString &href) override;
|
||||
void setPlainTextEdit(QPlainTextEdit *plainText) override;
|
||||
|
||||
protected:
|
||||
void clearLastLine() override;
|
||||
virtual void openEditor(const QString &fileName, int line, int column = -1);
|
||||
|
||||
private:
|
||||
void updateProjectFileList();
|
||||
LinkResult matchLine(const QString &line) const;
|
||||
void appendMessagePart(const QString &txt, const QTextCharFormat &fmt);
|
||||
void appendLine(const LinkResult &lr, const QString &line, Utils::OutputFormat format);
|
||||
void appendLine(const LinkResult &lr, const QString &line, const QTextCharFormat &format);
|
||||
void appendMessage(const QString &text, const QTextCharFormat &format) override;
|
||||
|
||||
Internal::QtOutputFormatterPrivate *d;
|
||||
|
||||
// for testing
|
||||
friend class Internal::QtSupportPlugin;
|
||||
QtOutputFormatterFactory();
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QtSupport
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "gettingstartedwelcomepage.h"
|
||||
#include "qtkitinformation.h"
|
||||
#include "qtoptionspage.h"
|
||||
#include "qtoutputformatter.h"
|
||||
#include "qtsupportconstants.h"
|
||||
#include "qtversionfactory.h"
|
||||
#include "qtversionmanager.h"
|
||||
@@ -85,6 +86,8 @@ public:
|
||||
ExamplesWelcomePage tutorialPage{false};
|
||||
|
||||
QtKitAspect qtKiAspect;
|
||||
|
||||
QtOutputFormatterFactory qtOutputFormatterFactory;
|
||||
};
|
||||
|
||||
QtSupportPlugin::~QtSupportPlugin()
|
||||
|
@@ -33,8 +33,6 @@
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
@@ -68,7 +66,6 @@ RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *tar
|
||||
addAspect<X11ForwardingAspect>();
|
||||
|
||||
setDefaultDisplayName(runConfigDefaultDisplayName());
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
}
|
||||
|
||||
bool RemoteLinuxCustomRunConfiguration::isConfigured() const
|
||||
|
@@ -37,8 +37,6 @@
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtoutputformatter.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
@@ -70,8 +68,6 @@ RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Core::I
|
||||
if (HostOsInfo::isAnyUnixHost())
|
||||
addAspect<X11ForwardingAspect>();
|
||||
|
||||
setOutputFormatter<QtSupport::QtOutputFormatter>();
|
||||
|
||||
connect(target, &Target::deploymentDataChanged,
|
||||
this, &RemoteLinuxRunConfiguration::updateTargetInformation);
|
||||
connect(target, &Target::applicationTargetsChanged,
|
||||
|
Reference in New Issue
Block a user