aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qtsupport/qtoutputformatter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qtsupport/qtoutputformatter.cpp')
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp297
1 files changed, 110 insertions, 187 deletions
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 52517c5847..8975328dd0 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -27,6 +27,7 @@
#include "qtkitinformation.h"
#include "qtsupportconstants.h"
+#include "qttestparser.h"
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
@@ -45,19 +46,14 @@
#include <QTextCursor>
#include <QUrl>
+#include <tuple>
+
using namespace ProjectExplorer;
using namespace Utils;
namespace QtSupport {
namespace Internal {
-struct LinkResult
-{
- int start = -1;
- int end = -1;
- QString href;
-};
-
class QtOutputFormatterPrivate
{
public:
@@ -81,38 +77,30 @@ public:
const QRegularExpression qtTestFailUnix;
const QRegularExpression qtTestFailWin;
QPointer<Project> project;
- QList<FormattedText> lastLine;
FileInProjectFinder projectFinder;
- QTextCursor cursor;
};
-class QtOutputFormatter : public OutputFormatter
+class QtOutputLineParser : public OutputLineParser
{
public:
- explicit QtOutputFormatter(Target *target);
- ~QtOutputFormatter() override;
-
- void appendMessage(const QString &text, Utils::OutputFormat format) override;
- void handleLink(const QString &href) override;
- void setPlainTextEdit(QPlainTextEdit *plainText) override;
+ explicit QtOutputLineParser(Target *target);
+ ~QtOutputLineParser() override;
protected:
- void clearLastLine() override;
virtual void openEditor(const QString &fileName, int line, int column = -1);
private:
+ Result handleLine(const QString &text, Utils::OutputFormat format) override;
+ bool handleLink(const QString &href) override;
+
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;
+ LinkSpec matchLine(const QString &line) const;
QtOutputFormatterPrivate *d;
friend class QtSupportPlugin; // for testing
};
-QtOutputFormatter::QtOutputFormatter(Target *target)
+QtOutputLineParser::QtOutputLineParser(Target *target)
: d(new QtOutputFormatterPrivate)
{
d->project = target ? target->project() : nullptr;
@@ -123,28 +111,28 @@ QtOutputFormatter::QtOutputFormatter(Target *target)
connect(d->project,
&Project::fileListChanged,
this,
- &QtOutputFormatter::updateProjectFileList,
+ &QtOutputLineParser::updateProjectFileList,
Qt::QueuedConnection);
}
}
-QtOutputFormatter::~QtOutputFormatter()
+QtOutputLineParser::~QtOutputLineParser()
{
delete d;
}
-LinkResult QtOutputFormatter::matchLine(const QString &line) const
+OutputLineParser::LinkSpec QtOutputLineParser::matchLine(const QString &line) const
{
- LinkResult lr;
+ LinkSpec lr;
auto hasMatch = [&lr, line](const QRegularExpression &regex) {
const QRegularExpressionMatch match = regex.match(line);
if (!match.hasMatch())
return false;
- lr.href = match.captured(1);
- lr.start = match.capturedStart(1);
- lr.end = lr.start + lr.href.length();
+ lr.target = match.captured(1);
+ lr.startPos = match.capturedStart(1);
+ lr.length = lr.target.length();
return true;
};
@@ -164,165 +152,87 @@ LinkResult QtOutputFormatter::matchLine(const QString &line) const
return lr;
}
-void QtOutputFormatter::appendMessage(const QString &txt, OutputFormat format)
+OutputLineParser::Result QtOutputLineParser::handleLine(const QString &txt, OutputFormat format)
{
- appendMessage(txt, charFormat(format));
+ Q_UNUSED(format);
+ const LinkSpec lr = matchLine(txt);
+ if (!lr.target.isEmpty())
+ return Result(Status::Done, {lr});
+ return Status::NotHandled;
}
-void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFormat &fmt)
+bool QtOutputLineParser::handleLink(const QString &href)
{
- QString deferredText;
-
- const int length = txt.length();
- for (int start = 0, pos = -1; start < length; start = pos + 1) {
- bool linkHandled = false;
- pos = txt.indexOf('\n', start);
- const QString newPart = txt.mid(start, (pos == -1) ? -1 : pos - start + 1);
- QString line = newPart;
- QTextCharFormat format = fmt;
- if (!d->lastLine.isEmpty()) {
- line = d->lastLine.last().text + newPart;
- format = d->lastLine.last().format;
- }
-
- LinkResult lr = matchLine(line);
- if (!lr.href.isEmpty()) {
- // Found something && line continuation
- d->cursor.insertText(deferredText, fmt);
- deferredText.clear();
- if (!d->lastLine.isEmpty())
- clearLastLine();
- appendLine(lr, line, format);
- linkHandled = true;
- } else {
- // Found nothing, just emit the new part
- deferredText += newPart;
- }
-
- if (pos == -1) {
- d->lastLine.clear();
- if (!linkHandled)
- d->lastLine.append(FormattedText(line, format));
- break;
- }
- d->lastLine.clear(); // Handled line continuation
+ QTC_ASSERT(!href.isEmpty(), return false);
+ static const QRegularExpression qmlLineColumnLink("^(" QT_QML_URL_REGEXP ")" // url
+ ":(\\d+)" // line
+ ":(\\d+)$"); // column
+ const QRegularExpressionMatch qmlLineColumnMatch = qmlLineColumnLink.match(href);
+
+ const auto getFileToOpen = [this](const QUrl &fileUrl) {
+ return chooseFileFromList(d->projectFinder.findFile(fileUrl)).toString();
+ };
+ if (qmlLineColumnMatch.hasMatch()) {
+ const QUrl fileUrl = QUrl(qmlLineColumnMatch.captured(1));
+ const int line = qmlLineColumnMatch.captured(2).toInt();
+ const int column = qmlLineColumnMatch.captured(3).toInt();
+ openEditor(getFileToOpen(fileUrl), line, column - 1);
+ return true;
}
- d->cursor.insertText(deferredText, fmt);
-}
-void QtOutputFormatter::appendMessage(const QString &txt, const QTextCharFormat &format)
-{
- if (!d->cursor.atEnd())
- d->cursor.movePosition(QTextCursor::End);
- d->cursor.beginEditBlock();
-
- const QList<FormattedText> ansiTextList = parseAnsi(txt, format);
- for (const FormattedText &output : ansiTextList)
- appendMessagePart(output.text, output.format);
-
- d->cursor.endEditBlock();
-
- emit contentChanged();
-}
+ static const QRegularExpression qmlLineLink("^(" QT_QML_URL_REGEXP ")" // url
+ ":(\\d+)$"); // line
+ const QRegularExpressionMatch qmlLineMatch = qmlLineLink.match(href);
+
+ if (qmlLineMatch.hasMatch()) {
+ const char scheme[] = "file://";
+ const QString filePath = qmlLineMatch.captured(1);
+ QUrl fileUrl = QUrl(filePath);
+ if (!fileUrl.isValid() && filePath.startsWith(scheme))
+ fileUrl = QUrl::fromLocalFile(filePath.mid(int(strlen(scheme))));
+ const int line = qmlLineMatch.captured(2).toInt();
+ openEditor(getFileToOpen(fileUrl), line);
+ return true;
+ }
-void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, OutputFormat format)
-{
- appendLine(lr, line, charFormat(format));
-}
+ QString fileName;
+ int line = -1;
-void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line,
- const QTextCharFormat &format)
-{
- d->cursor.insertText(line.left(lr.start), format);
- d->cursor.insertText(line.mid(lr.start, lr.end - lr.start), linkFormat(format, lr.href));
- d->cursor.insertText(line.mid(lr.end), format);
-}
+ static const QRegularExpression qtErrorLink("^(.*):(\\d+)$");
+ const QRegularExpressionMatch qtErrorMatch = qtErrorLink.match(href);
+ if (qtErrorMatch.hasMatch()) {
+ fileName = qtErrorMatch.captured(1);
+ line = qtErrorMatch.captured(2).toInt();
+ }
-void QtOutputFormatter::handleLink(const QString &href)
-{
- if (!href.isEmpty()) {
- static const QRegularExpression qmlLineColumnLink("^(" QT_QML_URL_REGEXP ")" // url
- ":(\\d+)" // line
- ":(\\d+)$"); // column
- const QRegularExpressionMatch qmlLineColumnMatch = qmlLineColumnLink.match(href);
-
- const auto getFileToOpen = [this](const QUrl &fileUrl) {
- return chooseFileFromList(d->projectFinder.findFile(fileUrl)).toString();
- };
- if (qmlLineColumnMatch.hasMatch()) {
- const QUrl fileUrl = QUrl(qmlLineColumnMatch.captured(1));
- const int line = qmlLineColumnMatch.captured(2).toInt();
- const int column = qmlLineColumnMatch.captured(3).toInt();
- openEditor(getFileToOpen(fileUrl), line, column - 1);
- return;
- }
-
- static const QRegularExpression qmlLineLink("^(" QT_QML_URL_REGEXP ")" // url
- ":(\\d+)$"); // line
- const QRegularExpressionMatch qmlLineMatch = qmlLineLink.match(href);
-
- if (qmlLineMatch.hasMatch()) {
- const char scheme[] = "file://";
- const QString filePath = qmlLineMatch.captured(1);
- QUrl fileUrl = QUrl(filePath);
- if (!fileUrl.isValid() && filePath.startsWith(scheme))
- fileUrl = QUrl::fromLocalFile(filePath.mid(int(strlen(scheme))));
- const int line = qmlLineMatch.captured(2).toInt();
- openEditor(getFileToOpen(fileUrl), line);
- return;
- }
-
- QString fileName;
- int line = -1;
-
- static const QRegularExpression qtErrorLink("^(.*):(\\d+)$");
- const QRegularExpressionMatch qtErrorMatch = qtErrorLink.match(href);
- if (qtErrorMatch.hasMatch()) {
- fileName = qtErrorMatch.captured(1);
- line = qtErrorMatch.captured(2).toInt();
- }
-
- static const QRegularExpression qtAssertLink("^(.+), line (\\d+)$");
- const QRegularExpressionMatch qtAssertMatch = qtAssertLink.match(href);
- if (qtAssertMatch.hasMatch()) {
- fileName = qtAssertMatch.captured(1);
- line = qtAssertMatch.captured(2).toInt();
- }
-
- static const QRegularExpression qtTestFailLink("^(.*)\\((\\d+)\\)$");
- const QRegularExpressionMatch qtTestFailMatch = qtTestFailLink.match(href);
- if (qtTestFailMatch.hasMatch()) {
- fileName = qtTestFailMatch.captured(1);
- line = qtTestFailMatch.captured(2).toInt();
- }
-
- if (!fileName.isEmpty()) {
- fileName = getFileToOpen(QUrl::fromLocalFile(fileName));
- openEditor(fileName, line);
- return;
- }
+ static const QRegularExpression qtAssertLink("^(.+), line (\\d+)$");
+ const QRegularExpressionMatch qtAssertMatch = qtAssertLink.match(href);
+ if (qtAssertMatch.hasMatch()) {
+ fileName = qtAssertMatch.captured(1);
+ line = qtAssertMatch.captured(2).toInt();
}
-}
-void QtOutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
-{
- OutputFormatter::setPlainTextEdit(plainText);
- d->cursor = plainText ? plainText->textCursor() : QTextCursor();
-}
+ static const QRegularExpression qtTestFailLink("^(.*)\\((\\d+)\\)$");
+ const QRegularExpressionMatch qtTestFailMatch = qtTestFailLink.match(href);
+ if (qtTestFailMatch.hasMatch()) {
+ fileName = qtTestFailMatch.captured(1);
+ line = qtTestFailMatch.captured(2).toInt();
+ }
-void QtOutputFormatter::clearLastLine()
-{
- OutputFormatter::clearLastLine();
- if (!d->lastLine.isEmpty())
- d->lastLine.removeLast();
+ if (!fileName.isEmpty()) {
+ fileName = getFileToOpen(QUrl::fromLocalFile(fileName));
+ openEditor(fileName, line);
+ return true;
+ }
+ return false;
}
-void QtOutputFormatter::openEditor(const QString &fileName, int line, int column)
+void QtOutputLineParser::openEditor(const QString &fileName, int line, int column)
{
Core::EditorManager::openEditorAt(fileName, line, column);
}
-void QtOutputFormatter::updateProjectFileList()
+void QtOutputLineParser::updateProjectFileList()
{
if (d->project)
d->projectFinder.setProjectFiles(d->project->files(Project::SourceFiles));
@@ -332,9 +242,10 @@ void QtOutputFormatter::updateProjectFileList()
QtOutputFormatterFactory::QtOutputFormatterFactory()
{
- setFormatterCreator([](Target *t) -> OutputFormatter * {
- BaseQtVersion *qt = QtKitAspect::qtVersion(t->kit());
- return qt ? new QtOutputFormatter(t) : nullptr;
+ setFormatterCreator([](Target *t) -> QList<OutputLineParser *> {
+ if (QtKitAspect::qtVersion(t ? t->kit() : nullptr))
+ return {new QtTestParser, new QtOutputLineParser(t)};
+ return {};
});
}
@@ -355,11 +266,11 @@ namespace QtSupport {
using namespace QtSupport::Internal;
-class TestQtOutputFormatter : public QtOutputFormatter
+class TestQtOutputLineParser : public QtOutputLineParser
{
public:
- TestQtOutputFormatter() :
- QtOutputFormatter(nullptr)
+ TestQtOutputLineParser() :
+ QtOutputLineParser(nullptr)
{
}
@@ -376,6 +287,11 @@ public:
int column = -1;
};
+class TestQtOutputFormatter : public OutputFormatter
+{
+public:
+ TestQtOutputFormatter() { setLineParsers({new TestQtOutputLineParser}); }
+};
void QtSupportPlugin::testQtOutputFormatter_data()
{
@@ -393,7 +309,7 @@ void QtSupportPlugin::testQtOutputFormatter_data()
QTest::newRow("pass through")
<< "Pass through plain text."
- << -1 << -1 << QString()
+ << -1 << -2 << QString()
<< QString() << -1 << -1;
QTest::newRow("qrc:/main.qml:20")
@@ -499,14 +415,14 @@ void QtSupportPlugin::testQtOutputFormatter()
QFETCH(int, line);
QFETCH(int, column);
- TestQtOutputFormatter formatter;
+ TestQtOutputLineParser formatter;
- LinkResult result = formatter.matchLine(input);
- formatter.handleLink(result.href);
+ QtOutputLineParser::LinkSpec result = formatter.matchLine(input);
+ formatter.handleLink(result.target);
- QCOMPARE(result.start, linkStart);
- QCOMPARE(result.end, linkEnd);
- QCOMPARE(result.href, href);
+ QCOMPARE(result.startPos, linkStart);
+ QCOMPARE(result.startPos + result.length, linkEnd);
+ QCOMPARE(result.target, href);
QCOMPARE(formatter.fileName, file);
QCOMPARE(formatter.line, line);
@@ -566,8 +482,13 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage()
QFETCH(QString, outputText);
QFETCH(QTextCharFormat, inputFormat);
QFETCH(QTextCharFormat, outputFormat);
+ if (outputFormat == QTextCharFormat())
+ outputFormat = formatter.charFormat(StdOutFormat);
+ if (inputFormat != QTextCharFormat())
+ formatter.overrideTextCharFormat(inputFormat);
- formatter.appendMessage(inputText, inputFormat);
+ formatter.appendMessage(inputText, StdOutFormat);
+ formatter.flush();
QCOMPARE(edit.toPlainText(), outputText);
QCOMPARE(edit.currentCharFormat(), outputFormat);
@@ -576,6 +497,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage()
void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi()
{
QPlainTextEdit edit;
+
TestQtOutputFormatter formatter;
formatter.setPlainTextEdit(&edit);
@@ -588,7 +510,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi()
"file://test.cpp:123 "
"Blue\n";
- formatter.appendMessage(inputText, QTextCharFormat());
+ formatter.appendMessage(inputText, StdOutFormat);
QCOMPARE(edit.toPlainText(), outputText);
@@ -597,7 +519,8 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi()
edit.moveCursor(QTextCursor::WordRight);
edit.moveCursor(QTextCursor::Right);
- QCOMPARE(edit.currentCharFormat(), OutputFormatter::linkFormat(QTextCharFormat(), "file://test.cpp:123"));
+ QCOMPARE(edit.currentCharFormat(),
+ OutputFormatter::linkFormat(QTextCharFormat(), "file://test.cpp:123"));
edit.moveCursor(QTextCursor::End);
QCOMPARE(edit.currentCharFormat(), blueFormat());